Make solver unfaileable
This commit is contained in:
		
							parent
							
								
									d12c69200b
								
							
						
					
					
						commit
						b289b18030
					
				
					 1 changed files with 86 additions and 70 deletions
				
			
		
							
								
								
									
										142
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										142
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,5 +1,3 @@ | ||||||
| use std::collections::HashSet; |  | ||||||
| 
 |  | ||||||
| use rand::seq::SliceRandom; | use rand::seq::SliceRandom; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Copy, Hash, PartialEq, Eq)] | #[derive(Clone, Copy, Hash, PartialEq, Eq)] | ||||||
|  | @ -10,7 +8,7 @@ struct Card { | ||||||
| 
 | 
 | ||||||
| impl std::fmt::Debug for Card { | impl std::fmt::Debug for Card { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     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 { |     fn cost(&self) -> u8 { | ||||||
|         match self.color { |         match self.color { | ||||||
|             Color::Spades => { |             Color::Spades => { | ||||||
|                 if self.value == 5 { |                 if self.value == 6 { | ||||||
|                     4 |                     4 | ||||||
|                 } else { |                 } else { | ||||||
|                     0 |                     0 | ||||||
|  | @ -32,6 +30,20 @@ impl Card { | ||||||
|             _ => 0, |             _ => 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)] | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | ||||||
|  | @ -53,7 +65,7 @@ impl Color { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, Clone)] | ||||||
| enum Knowledge { | enum Knowledge { | ||||||
|     Full(Vec<Card>), |     Full(Vec<Card>), | ||||||
|     Partial([bool; 4]), |     Partial([bool; 4]), | ||||||
|  | @ -65,11 +77,10 @@ fn solve( | ||||||
|     unseen: &[Card], |     unseen: &[Card], | ||||||
|     stack: &mut Vec<Card>, |     stack: &mut Vec<Card>, | ||||||
|     remaining: usize, |     remaining: usize, | ||||||
|     played: &mut HashSet<Card>, | ) -> Vec<f64> { | ||||||
| ) -> Option<(Option<Card>, Vec<f64>)> { |  | ||||||
|     let num_player = knowledge.len(); |     let num_player = knowledge.len(); | ||||||
|     if remaining == 0 { |     if remaining == 0 { | ||||||
|         Some((None, vec![0.0; num_player])) |         vec![0.0; num_player] | ||||||
|     } else if stack.len() == num_player { |     } else if stack.len() == num_player { | ||||||
|         let first_card = stack.first().unwrap(); |         let first_card = stack.first().unwrap(); | ||||||
| 
 | 
 | ||||||
|  | @ -90,82 +101,79 @@ fn solve( | ||||||
|         let cost = stack.iter().map(|c| c.cost()).sum::<u8>(); |         let cost = stack.iter().map(|c| c.cost()).sum::<u8>(); | ||||||
| 
 | 
 | ||||||
|         let mut new_stack = Vec::new(); |         let mut new_stack = Vec::new(); | ||||||
|         if let Some(mut s) = solve( |         let mut s = solve( | ||||||
|             winning_player, |             winning_player, | ||||||
|             knowledge, |             knowledge, | ||||||
|             unseen, |             unseen, | ||||||
|             &mut new_stack, |             &mut new_stack, | ||||||
|             remaining - 1, |             remaining - 1, | ||||||
|             played, |         ); | ||||||
|         ) { |         s[winning_player] += cost as f64; | ||||||
|             s.1[winning_player] += cost as f64; |         s | ||||||
|             Some(s) |  | ||||||
|         } else { |  | ||||||
|             None |  | ||||||
|         } |  | ||||||
|     } else { |     } else { | ||||||
|         match &knowledge[current] { |         match &knowledge[current] { | ||||||
|             Knowledge::Full(cards) => { |             Knowledge::Full(cards) => { | ||||||
|                 if let Some(f) = stack |                 let mut min: Option<Vec<f64>> = None; | ||||||
|                     .first() |                 let mut own_knowledge = knowledge.to_vec(); | ||||||
|                     .copied() |                 if let Some(first_card) = stack.first().copied() { | ||||||
|                     .filter(|&f| cards.iter().any(|&c| f.color == c.color)) |                     for i in 0..cards.len() { | ||||||
|                 { |                         if cards[i].color == first_card.color { | ||||||
|                     let mut min: Option<(Option<Card>, Vec<f64>)> = None; |                             stack.push(cards[i]); | ||||||
|                     for &c in cards.iter().filter(|&&c| c.color == f.color) { | 
 | ||||||
|                         if !played.contains(&c) { |                             own_knowledge[current] = Knowledge::Full( | ||||||
|                             stack.push(c); |                                 cards | ||||||
|                             played.insert(c); |                                     .iter() | ||||||
|                             if let Some(m) = solve( |                                     .enumerate() | ||||||
|  |                                     .filter(|(j, _)| j != &i) | ||||||
|  |                                     .map(|(_, &c)| c) | ||||||
|  |                                     .collect(), | ||||||
|  |                             ); | ||||||
|  |                             let m = solve( | ||||||
|                                 (current + 1) % num_player, |                                 (current + 1) % num_player, | ||||||
|                                 knowledge, |                                 &own_knowledge, | ||||||
|                                 unseen, |                                 unseen, | ||||||
|                                 stack, |                                 stack, | ||||||
|                                 remaining, |                                 remaining, | ||||||
|                                 played, |                             ); | ||||||
|                             ) { |  | ||||||
|                             if let Some(min) = &mut min { |                             if let Some(min) = &mut min { | ||||||
|                                     if m.1[current] < min.1[current] { |                                 if m[current] < min[current] { | ||||||
|                                         *min = (Some(c), m.1); |                                     *min = m; | ||||||
|                                 } |                                 } | ||||||
|                             } else { |                             } else { | ||||||
|                                     min = Some((Some(c), m.1)); |                                 min = Some(m); | ||||||
|                             } |                             } | ||||||
|                             } |  | ||||||
| 
 |  | ||||||
|                             stack.pop(); |                             stack.pop(); | ||||||
|                             played.remove(&c); |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     min |                 } | ||||||
|  |                 if let Some(m) = min { | ||||||
|  |                     m | ||||||
|                 } else { |                 } else { | ||||||
|                     let mut min: Option<(Option<Card>, Vec<f64>)> = None; |                     let mut min = vec![f64::INFINITY; num_player]; | ||||||
|                     for &c in cards { |                     for i in 0..cards.len() { | ||||||
|                         if !played.contains(&c) { |                         stack.push(cards[i]); | ||||||
|                             stack.push(c); |                         own_knowledge[current] = Knowledge::Full( | ||||||
|                             played.insert(c); |                             cards | ||||||
|  |                                 .iter() | ||||||
|  |                                 .enumerate() | ||||||
|  |                                 .filter(|(j, _)| j != &i) | ||||||
|  |                                 .map(|(_, &c)| c) | ||||||
|  |                                 .collect(), | ||||||
|  |                         ); | ||||||
| 
 | 
 | ||||||
|                             if let Some(m) = solve( |                         let m = solve( | ||||||
|                             (current + 1) % num_player, |                             (current + 1) % num_player, | ||||||
|                                 knowledge, |                             &own_knowledge, | ||||||
|                             unseen, |                             unseen, | ||||||
|                             stack, |                             stack, | ||||||
|                             remaining, |                             remaining, | ||||||
|                                 played, |                         ); | ||||||
|                             ) { |                         if m[current] < min[current] { | ||||||
|                                 if let Some(min) = &mut min { |                             min = m; | ||||||
|                                     if m.1[current] < min.1[current] { |  | ||||||
|                                         *min = (Some(c), m.1); |  | ||||||
|                                     } |  | ||||||
|                                 } else { |  | ||||||
|                                     min = Some((Some(c), m.1)); |  | ||||||
|                         } |                         } | ||||||
|  |                         stack.pop(); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                             stack.pop(); |  | ||||||
|                             played.remove(&c); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     min |                     min | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -191,18 +199,26 @@ fn main() { | ||||||
| 
 | 
 | ||||||
|     full_deck.shuffle(&mut rng); |     full_deck.shuffle(&mut rng); | ||||||
| 
 | 
 | ||||||
|     let knowledge = [ |     let cards = 4; | ||||||
|         Knowledge::Full(full_deck[0..10].to_vec()), |     let player = 4; | ||||||
|         Knowledge::Full(full_deck[10..20].to_vec()), | 
 | ||||||
|         Knowledge::Full(full_deck[20..30].to_vec()), |     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); |     dbg!(&knowledge); | ||||||
| 
 | 
 | ||||||
|     let unseen = []; |     let unseen = []; | ||||||
| 
 | 
 | ||||||
|     let mut stack = Vec::new(); |     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); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue