@@ -62,8 +62,8 @@ type Input = (Deck, Deck);
6262type Cache = Vec < FastSet < ( usize , usize ) > > ;
6363
6464enum Winner {
65- Player1 ,
66- Player2 ,
65+ Player1 ( Deck ) ,
66+ Player2 ( Deck ) ,
6767}
6868
6969#[ derive( Clone , Copy ) ]
@@ -72,33 +72,33 @@ pub struct Deck {
7272 score : usize ,
7373 start : usize ,
7474 end : usize ,
75- cards : [ u8 ; 50 ] ,
75+ cards : [ u8 ; 64 ] ,
7676}
7777
7878impl Deck {
7979 fn new ( ) -> Deck {
80- Deck { sum : 0 , score : 0 , start : 0 , end : 0 , cards : [ 0 ; 50 ] }
80+ Deck { sum : 0 , score : 0 , start : 0 , end : 0 , cards : [ 0 ; 64 ] }
8181 }
8282
8383 // To make things easier, `start` and `end` never wrap around, so that `end` is always
8484 // greater than or equal to `start`.
8585 fn pop_front ( & mut self ) -> usize {
86- let card = self . cards [ self . start % 50 ] as usize ;
86+ let card = self . cards [ self . start % 64 ] as usize ;
8787 self . sum -= card;
8888 self . score -= self . size ( ) * card;
8989 self . start += 1 ;
9090 card
9191 }
9292
9393 fn push_back ( & mut self , card : usize ) {
94- self . cards [ self . end % 50 ] = card as u8 ;
94+ self . cards [ self . end % 64 ] = card as u8 ;
9595 self . sum += card;
9696 self . score += self . sum ;
9797 self . end += 1 ;
9898 }
9999
100100 fn max ( & self ) -> u8 {
101- ( self . start ..self . end ) . map ( |i| self . cards [ i % 50 ] ) . max ( ) . unwrap ( )
101+ ( self . start ..self . end ) . map ( |i| self . cards [ i % 64 ] ) . max ( ) . unwrap ( )
102102 }
103103
104104 fn non_empty ( & self ) -> bool {
@@ -109,17 +109,15 @@ impl Deck {
109109 self . end - self . start
110110 }
111111
112- // Sneaky trick here to speed things up a little. We don't recalculate the score properly,
113- // so it will be too high by a constant amount. This doesn't matter for recursive games as
114- // we only need the winner, not the exact score.
115112 fn copy ( & self , amount : usize ) -> Deck {
116- let mut copy = * self ;
117- copy. end = copy. start + amount;
118- copy. sum = 0 ;
113+ let mut copy = Deck :: new ( ) ;
114+ copy. end = amount;
119115
120116 for i in 0 ..amount {
121- let card = copy. cards [ ( copy. start + i) % 50 ] as usize ;
122- copy. sum += card;
117+ let card = self . cards [ ( self . start + i) % 64 ] ;
118+ copy. cards [ i] = card;
119+ copy. sum += card as usize ;
120+ copy. score += copy. sum ;
123121 }
124122
125123 copy
@@ -155,18 +153,17 @@ pub fn part1(input: &Input) -> usize {
155153}
156154
157155pub fn part2 ( input : & Input ) -> usize {
158- let ( mut deck1, mut deck2) = * input;
156+ let ( deck1, deck2) = * input;
159157
160- match combat ( & mut deck1, & mut deck2, & mut Vec :: new ( ) , 0 ) {
161- Winner :: Player1 => deck1. score ,
162- Winner :: Player2 => deck2. score ,
158+ match combat ( deck1, deck2, & mut Vec :: new ( ) , 0 ) {
159+ Winner :: Player1 ( deck) | Winner :: Player2 ( deck) => deck. score ,
163160 }
164161}
165162
166- fn combat ( deck1 : & mut Deck , deck2 : & mut Deck , cache : & mut Cache , depth : usize ) -> Winner {
163+ fn combat ( mut deck1 : Deck , mut deck2 : Deck , cache : & mut Cache , depth : usize ) -> Winner {
167164 // Player 1 always wins recursive games if they have the high card.
168165 if depth > 0 && deck1. max ( ) > deck2. max ( ) {
169- return Winner :: Player1 ;
166+ return Winner :: Player1 ( deck1 ) ;
170167 }
171168
172169 // Speed things up by re-using previously created caches, avoiding slow extra heap allocations.
@@ -179,7 +176,7 @@ fn combat(deck1: &mut Deck, deck2: &mut Deck, cache: &mut Cache, depth: usize) -
179176 while deck1. non_empty ( ) && deck2. non_empty ( ) {
180177 // This will *very probably* work! Not 100% deterministic.
181178 if !cache[ depth] . insert ( ( deck1. score , deck2. score ) ) {
182- return Winner :: Player1 ;
179+ return Winner :: Player1 ( deck1 ) ;
183180 }
184181
185182 let ( card1, card2) = ( deck1. pop_front ( ) , deck2. pop_front ( ) ) ;
@@ -193,18 +190,18 @@ fn combat(deck1: &mut Deck, deck2: &mut Deck, cache: &mut Cache, depth: usize) -
193190 deck2. push_back ( card1) ;
194191 }
195192 } else {
196- match combat ( & mut deck1. copy ( card1) , & mut deck2. copy ( card2) , cache, depth + 1 ) {
197- Winner :: Player1 => {
193+ match combat ( deck1. copy ( card1) , deck2. copy ( card2) , cache, depth + 1 ) {
194+ Winner :: Player1 ( _ ) => {
198195 deck1. push_back ( card1) ;
199196 deck1. push_back ( card2) ;
200197 }
201- Winner :: Player2 => {
198+ Winner :: Player2 ( _ ) => {
202199 deck2. push_back ( card2) ;
203200 deck2. push_back ( card1) ;
204201 }
205202 }
206203 }
207204 }
208205
209- if deck1. non_empty ( ) { Winner :: Player1 } else { Winner :: Player2 }
206+ if deck1. non_empty ( ) { Winner :: Player1 ( deck1 ) } else { Winner :: Player2 ( deck2 ) }
210207}
0 commit comments