Skip to content

Commit 7214977

Browse files
committed
Advent of Code 2021 - Day 21
1 parent b6437e4 commit 7214977

File tree

6 files changed

+167
-2
lines changed

6 files changed

+167
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ Last year I ran a [cruise log for my 25 days competing in the Advent of Code](ht
3636
- [The Advent of Code 2021 Day 16, Technical K.O.](https://www.codingnagger.com/2021/12/16/the-advent-of-code-2021-day-16-technical-k-o/)
3737
- [The Advent of Code 2021 Day 17, Deep Probing](https://www.codingnagger.com/2021/12/20/the-advent-of-code-2021-day-17-deep-probing/)
3838
- [The Advent of Code 2021 Day 20, Bruteforce McBruteface](https://www.codingnagger.com/2021/12/20/the-advent-of-code-2021-day-20-bruteforce-mcbruteface/)
39+
- [The Advent of Code 2021 Day 21, Late Night Finish](https://www.codingnagger.com/2021/12/22/the-advent-of-code-2021-day-21-late-night-finish/)

src/main/java/com/codingnagger/App.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.codingnagger.days.Day;
44
import com.codingnagger.days.Day16;
55
import com.codingnagger.days.Day20;
6+
import com.codingnagger.days.Day21;
67
import com.codingnagger.utils.InputLoader;
78

89
import java.io.IOException;
@@ -15,9 +16,9 @@ public class App {
1516
public static void main(String[] args) throws IOException {
1617
System.out.println("Advent of Code 2021");
1718

18-
List<String> input = InputLoader.Load("day20.txt");
19+
List<String> input = InputLoader.Load("day21.txt");
1920

20-
Day day = new Day20();
21+
Day day = new Day21();
2122

2223
System.out.println("Part 1:");
2324
System.out.println(day.partOne(input));
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.codingnagger.days;
2+
3+
import java.math.BigInteger;
4+
import java.util.HashMap;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
public class Day21 implements Day {
9+
10+
public static final int PART_2VICTORY = 21;
11+
12+
@Override
13+
public String partOne(List<String> input) {
14+
int[] diceRoll = new int[] {1,2,3};
15+
16+
int p1Score = 0, p2Score = 0;
17+
int p1Position = Integer.parseInt(input.get(0).split("starting position: ")[1]);
18+
int p2Position = Integer.parseInt(input.get(1).split("starting position: ")[1]);
19+
20+
boolean p1Turn = true;
21+
int turns = 0;
22+
23+
while (p1Score < 1000 && p2Score < 1000) {
24+
if (p1Turn) {
25+
p1Position = endPosition(p1Position, diceRoll);
26+
p1Score += p1Position;
27+
} else {
28+
p2Position = endPosition(p2Position, diceRoll);
29+
p2Score += p2Position;
30+
}
31+
32+
diceRoll[0] = roll(diceRoll[0]);
33+
diceRoll[1] = roll(diceRoll[1]);
34+
diceRoll[2] = roll(diceRoll[2]);
35+
36+
turns += 3;
37+
p1Turn = !p1Turn;
38+
}
39+
return String.valueOf(turns * Math.min(p1Score, p2Score));
40+
}
41+
42+
private int roll(int value) {
43+
if (value + 3 > 100) {
44+
return value + 3 - 100;
45+
}
46+
47+
return value + 3;
48+
}
49+
50+
private int endPosition(int position, int[] diceRoll) {
51+
return ((position-1 + diceRoll[0] + diceRoll[1] + diceRoll[2]) % 10) + 1;
52+
}
53+
54+
private int endPosition(int position, int diceRoll) {
55+
return ((position-1 + diceRoll) % 10) + 1;
56+
}
57+
58+
private static final Map<String, UniverseResult> UNIVERSE_RESULTS = new HashMap<>();
59+
60+
@Override
61+
public String partTwo(List<String> input) {
62+
int p1Position = Integer.parseInt(input.get(0).split("starting position: ")[1]);
63+
int p2Position = Integer.parseInt(input.get(1).split("starting position: ")[1]);
64+
65+
UniverseResult result = playGame(0, 0, p1Position, p2Position, 0, 0);
66+
67+
return String.valueOf(Math.max(result.getP1Wins().longValue(), result.getP2Wins().longValue()));
68+
}
69+
70+
public UniverseResult playGame(int p1Score, int p2Score, int p1Position, int p2Position, int turn, int throwSum) {
71+
boolean isP1Turn = turn < 3;
72+
boolean lastP1Throw = turn == 2;
73+
boolean lastP2Throw = turn == 5;
74+
75+
String cacheKey = String.format("%d-%d-%d-%d-%d-%d", p1Position, p1Score, p2Position, p2Score, turn, throwSum);
76+
77+
UniverseResult res;
78+
79+
if (p1Score >= PART_2VICTORY) {
80+
res = new UniverseResult(BigInteger.ONE, BigInteger.ZERO);
81+
} else if (p2Score >= PART_2VICTORY) {
82+
res = new UniverseResult(BigInteger.ZERO, BigInteger.ONE);
83+
} else {
84+
if (UNIVERSE_RESULTS.containsKey(cacheKey)) {
85+
return UNIVERSE_RESULTS.get(cacheKey);
86+
}
87+
88+
int nextTurn = (turn + 1) % 6;
89+
90+
BigInteger p1Wins = BigInteger.ZERO;
91+
BigInteger p2Wins = BigInteger.ZERO;
92+
93+
for (int roll = 1; roll <= 3; roll++) {
94+
UniverseResult result = playGame(
95+
isP1Turn ? p1Score + (lastP1Throw ? endPosition(p1Position, roll) : 0) : p1Score,
96+
!isP1Turn ? p2Score + (lastP2Throw ? endPosition(p2Position, roll) : 0) : p2Score,
97+
isP1Turn ? endPosition(p1Position, roll) : p1Position,
98+
!isP1Turn ? endPosition(p2Position, roll) : p2Position,
99+
nextTurn,
100+
turn % 3 == 0 ? 0 : throwSum + roll
101+
);
102+
103+
p1Wins = p1Wins.add(result.getP1Wins());
104+
p2Wins = p2Wins.add(result.getP2Wins());
105+
}
106+
107+
res = new UniverseResult(p1Wins, p2Wins);
108+
}
109+
110+
UNIVERSE_RESULTS.put(cacheKey, res);
111+
return res;
112+
}
113+
114+
class UniverseResult {
115+
private final BigInteger p1Wins;
116+
private final BigInteger p2Wins;
117+
118+
public UniverseResult(BigInteger p1Wins, BigInteger p2Wins) {
119+
this.p1Wins = p1Wins;
120+
this.p2Wins = p2Wins;
121+
}
122+
123+
public BigInteger getP1Wins() {
124+
return p1Wins;
125+
}
126+
127+
public BigInteger getP2Wins() {
128+
return p2Wins;
129+
}
130+
}
131+
}

src/main/resources/day21.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Player 1 starting position: 2
2+
Player 2 starting position: 7
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
package com.codingnagger.days;
3+
4+
import com.codingnagger.utils.InputLoader;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.util.List;
8+
9+
import static org.assertj.core.api.Assertions.assertThat;
10+
11+
public class Day21Test {
12+
private static final List<String> INPUT = InputLoader.LoadTest("day21.txt");
13+
private static final Day DAY = new Day21();
14+
15+
@Test
16+
public void partOne_shoudlYieldCorrectResult() {
17+
String result = DAY.partOne(INPUT);
18+
19+
assertThat(result).isEqualTo("739785");
20+
}
21+
22+
@Test
23+
public void partTwo_shoudlYieldCorrectResult() {
24+
String result = DAY.partTwo(INPUT);
25+
26+
assertThat(result).isEqualTo("444356092776315"); // test answer too low, real input answer too high 343042929017714
27+
}
28+
}

src/test/resources/day21.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Player 1 starting position: 4
2+
Player 2 starting position: 8

0 commit comments

Comments
 (0)