1
1
package aoc2021 ;
2
2
3
- import java .util .Arrays ;
4
3
import java .util .HashMap ;
5
4
import java .util .Map ;
6
5
@@ -11,39 +10,55 @@ public class D21 {
11
10
12
11
record Player (int pos , int score ) {
13
12
Player move (int m ) {
14
- int newPos = (this .pos + m - 1 ) % 10 + 1 ;
13
+ int newPos = (this .pos + m - 1 ) % 10 + 1 ; // calculate new position
15
14
return new Player (newPos , score + newPos );
16
15
}
17
16
}
18
17
19
- record State (int totalRolls , int prev , int prev2 , Player p1 , Player p2 ) {}
18
+ record State (int totalRolls , int prevRoll , int prevRoll2 , Player p1 , Player p2 ) {
19
+ boolean gameOver (int score ) {
20
+ return p1 .score >= score || p2 .score >= score ;
21
+ }
22
+ int playerInTurn () {
23
+ return (totalRolls / 3 ) % 2 ;
24
+ }
25
+ State roll (int currentRoll ) {
26
+ int playerRollNumber = totalRolls % 3 ; // number of roll for current player
27
+ Player p1 = this .p1 ;
28
+ Player p2 = this .p2 ;
29
+ if (playerRollNumber == 2 ) { // third roll for the player, move it
30
+ int totalRollSum = currentRoll + prevRoll + prevRoll2 ; // rolls sum
31
+ if (playerInTurn () == 0 ) {
32
+ p1 = this .p1 .move (totalRollSum );
33
+ } else {
34
+ p2 = this .p2 .move (totalRollSum );
35
+ }
36
+ }
37
+ return new State (totalRolls +1 , currentRoll , prevRoll , p1 , p2 );
38
+ }
39
+ }
20
40
21
- static int rollPracticeDice (int rolls ) {
22
- return (rolls + 1 ) % 100 - 1 ;
41
+ static State rollPracticeDice (State state ) {
42
+ int currentRoll = (state .totalRolls ) %100 + 1 ;
43
+ return state .roll (currentRoll );
23
44
}
24
45
25
46
public static void main (String ... args )
26
47
{
27
- Player [] players = {new Player (8 ,0 ), new Player (6 ,0 )};
28
- int totalRolls = 0 ;
29
- while (players [0 ].score < 1000 && players [1 ].score < 1000 ) { // until wins
30
- int player = (totalRolls / 3 ) % 2 ; // player in turn, index to players table
31
- int roll = 0 ;
32
- roll += rollPracticeDice (++totalRolls ); // roll 1
33
- roll += rollPracticeDice (++totalRolls ); // roll 2
34
- roll += rollPracticeDice (++totalRolls ); // roll 3
35
- players [player ] = players [player ].move (roll ); // move player and update players table
48
+ State state = new State (0 , 0 , 0 , new Player (8 ,0 ), new Player (6 ,0 ));
49
+ while (!state .gameOver (1000 )) { // until wins
50
+ state = rollPracticeDice (state );
36
51
}
37
- int losingScore = Arrays . stream ( players ). mapToInt ( p -> p .score ). min (). getAsInt ( );
38
- System .out .printf ("part 1: %s\n " , losingScore * totalRolls );
52
+ int losingScore = Math . min ( state . p1 .score , state . p2 . score );
53
+ System .out .printf ("part 1: %s\n " , losingScore * state . totalRolls );
39
54
40
55
Map <State , long []> cache = new HashMap <>();
41
- State s = new State (0 , 0 , 0 ,new Player (8 ,0 ), new Player (6 ,0 ));
42
- var res = play (s , cache );
56
+ state = new State (0 , 0 , 0 , new Player (8 ,0 ), new Player (6 ,0 ));
57
+ var res = play (state , cache );
43
58
System .out .printf ("part 2: %s\n " , Math .max (res [0 ], res [1 ]));
44
59
}
45
60
46
- // play state, return table of two, player 1 wins and player 2 wins
61
+ // play state, return array of two, player 1 wins and player 2 wins
47
62
static long [] play (State state , Map <State , long []> cache ) {
48
63
long [] cached = cache .get (state );
49
64
if (cached == null ) {
@@ -58,29 +73,12 @@ static long[] play(State state, Map<State, long[]> cache) {
58
73
return cached ;
59
74
}
60
75
61
- // play state with dice rolling given value, return table of two, player 1 wins and player 2 wins
76
+ // play state with dice rolling given value, return array of two, player 1 wins and player 2 wins
62
77
static long [] playRound (int currentRoll , State state , Map <State , long []> cache ) {
63
- boolean firstPlayer = (state .totalRolls / 3 ) % 2 == 0 ; // get the player based on dice rolls
64
- int playerRollNumber = state .totalRolls % 3 ; // number of rolls for current player
65
-
66
- Player p1 = state .p1 ;
67
- Player p2 = state .p2 ;
68
- if (playerRollNumber == 2 ) {
69
- // third roll for the player
70
- int totalRollSum = currentRoll + state .prev + state .prev2 ; // rolls sum
71
- Player moved = (firstPlayer ? state .p1 : state .p2 ).move (totalRollSum );
72
-
73
- if (moved .score >= 21 ) {
74
- return firstPlayer ? new long []{1 , 0 } : new long []{ 0 , 1 };
75
- }
76
-
77
- if (firstPlayer ) {
78
- p1 = moved ;
79
- } else {
80
- p2 = moved ;
81
- }
78
+ state = state .roll (currentRoll );
79
+ if (state .gameOver (21 )) {
80
+ return state .playerInTurn () == 0 ? new long []{1 ,0 } : new long []{0 ,1 };
82
81
}
83
- var newState = new State (state .totalRolls +1 , currentRoll , state .prev , p1 , p2 );
84
- return play (newState , cache );
82
+ return play (state , cache );
85
83
}
86
84
}
0 commit comments