diff --git a/src/main.rs b/src/main.rs index 331d21a..6eddbcc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; - use rand::seq::SliceRandom; #[derive(Clone, Copy, Hash, PartialEq, Eq)] @@ -10,7 +8,7 @@ struct Card { impl std::fmt::Debug for Card { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}{}", self.color.get_symbol(), self.value) + write!(f, "{}{}", self.color.get_symbol(), self.get_value_char()) } } @@ -22,7 +20,7 @@ impl Card { fn cost(&self) -> u8 { match self.color { Color::Spades => { - if self.value == 5 { + if self.value == 6 { 4 } else { 0 @@ -32,6 +30,20 @@ impl Card { _ => 0, } } + + fn get_value_char(&self) -> &'static str { + match self.value { + 1 => "7", + 2 => "8", + 3 => "9", + 4 => "10", + 5 => "J", + 6 => "Q", + 7 => "K", + 8 => "A", + _ => unreachable!(), + } + } } #[derive(Clone, Copy, PartialEq, Eq, Hash)] @@ -53,7 +65,7 @@ impl Color { } } -#[derive(Debug)] +#[derive(Debug, Clone)] enum Knowledge { Full(Vec), Partial([bool; 4]), @@ -65,11 +77,10 @@ fn solve( unseen: &[Card], stack: &mut Vec, remaining: usize, - played: &mut HashSet, -) -> Option<(Option, Vec)> { +) -> Vec { let num_player = knowledge.len(); if remaining == 0 { - Some((None, vec![0.0; num_player])) + vec![0.0; num_player] } else if stack.len() == num_player { let first_card = stack.first().unwrap(); @@ -90,82 +101,79 @@ fn solve( let cost = stack.iter().map(|c| c.cost()).sum::(); let mut new_stack = Vec::new(); - if let Some(mut s) = solve( + let mut s = solve( winning_player, knowledge, unseen, &mut new_stack, remaining - 1, - played, - ) { - s.1[winning_player] += cost as f64; - Some(s) - } else { - None - } + ); + s[winning_player] += cost as f64; + s } else { match &knowledge[current] { Knowledge::Full(cards) => { - if let Some(f) = stack - .first() - .copied() - .filter(|&f| cards.iter().any(|&c| f.color == c.color)) - { - let mut min: Option<(Option, Vec)> = None; - for &c in cards.iter().filter(|&&c| c.color == f.color) { - if !played.contains(&c) { - stack.push(c); - played.insert(c); - if let Some(m) = solve( + let mut min: Option> = None; + let mut own_knowledge = knowledge.to_vec(); + if let Some(first_card) = stack.first().copied() { + for i in 0..cards.len() { + if cards[i].color == first_card.color { + stack.push(cards[i]); + + own_knowledge[current] = Knowledge::Full( + cards + .iter() + .enumerate() + .filter(|(j, _)| j != &i) + .map(|(_, &c)| c) + .collect(), + ); + let m = solve( (current + 1) % num_player, - knowledge, + &own_knowledge, unseen, stack, remaining, - played, - ) { - if let Some(min) = &mut min { - if m.1[current] < min.1[current] { - *min = (Some(c), m.1); - } - } else { - min = Some((Some(c), m.1)); + ); + if let Some(min) = &mut min { + if m[current] < min[current] { + *min = m; } + } else { + min = Some(m); } - stack.pop(); - played.remove(&c); } } - min + } + if let Some(m) = min { + m } else { - let mut min: Option<(Option, Vec)> = None; - for &c in cards { - if !played.contains(&c) { - stack.push(c); - played.insert(c); + let mut min = vec![f64::INFINITY; num_player]; + for i in 0..cards.len() { + stack.push(cards[i]); + own_knowledge[current] = Knowledge::Full( + cards + .iter() + .enumerate() + .filter(|(j, _)| j != &i) + .map(|(_, &c)| c) + .collect(), + ); - if let Some(m) = solve( - (current + 1) % num_player, - knowledge, - unseen, - stack, - remaining, - played, - ) { - if let Some(min) = &mut min { - if m.1[current] < min.1[current] { - *min = (Some(c), m.1); - } - } else { - min = Some((Some(c), m.1)); - } - } - - stack.pop(); - played.remove(&c); + let m = solve( + (current + 1) % num_player, + &own_knowledge, + unseen, + stack, + remaining, + ); + if m[current] < min[current] { + min = m; } + stack.pop(); } + min } } @@ -191,18 +199,26 @@ fn main() { full_deck.shuffle(&mut rng); - let knowledge = [ - Knowledge::Full(full_deck[0..10].to_vec()), - Knowledge::Full(full_deck[10..20].to_vec()), - Knowledge::Full(full_deck[20..30].to_vec()), - ]; + let cards = 4; + let player = 4; + + let mut knowledge = Vec::new(); + + for i in 0..player { + knowledge.push(Knowledge::Full( + full_deck[cards * i..cards * (i + 1)].to_vec(), + )); + } dbg!(&knowledge); let unseen = []; let mut stack = Vec::new(); - let mut played = HashSet::new(); - dbg!(solve(0, &knowledge, &unseen, &mut stack, 5, &mut played)); + let start = std::time::Instant::now(); + let r = solve(0, &knowledge, &unseen, &mut stack, cards); + + dbg!(start.elapsed()); + dbg!(r); }