Skip to content

Commit 9aaa89a

Browse files
committed
day 21
1 parent 71501c3 commit 9aaa89a

File tree

6 files changed

+214
-54
lines changed

6 files changed

+214
-54
lines changed

2021/Day21/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
original source: [https://adventofcode.com/2021/day/21](https://adventofcode.com/2021/day/21)
2+
## --- Day 21: Dirac Dice ---
3+
There's not much to do as you slowly descend to the bottom of the ocean. The submarine computer challenges you to a nice game of <em>Dirac Dice</em>.
4+
5+
This game consists of a single [die](https://en.wikipedia.org/wiki/Dice), two [pawns](https://en.wikipedia.org/wiki/Glossary_of_board_games#piece), and a game board with a circular track containing ten spaces marked <code>1</code> through <code>10</code> clockwise. Each player's <em>starting space</em> is chosen randomly (your puzzle input). Player 1 goes first.
6+
7+
Players take turns moving. On each player's turn, the player rolls the die <em>three times</em> and adds up the results. Then, the player moves their pawn that many times <em>forward</em> around the track (that is, moving clockwise on spaces in order of increasing value, wrapping back around to <code>1</code> after <code>10</code>). So, if a player is on space <code>7</code> and they roll <code>2</code>, <code>2</code>, and <code>1</code>, they would move forward 5 times, to spaces <code>8</code>, <code>9</code>, <code>10</code>, <code>1</code>, and finally stopping on <code>2</code>.
8+
9+
After each player moves, they increase their <em>score</em> by the value of the space their pawn stopped on. Players' scores start at <code>0</code>. So, if the first player starts on space <code>7</code> and rolls a total of <code>5</code>, they would stop on space <code>2</code> and add <code>2</code> to their score (for a total score of <code>2</code>). The game immediately ends as a win for any player whose score reaches <em>at least <code>1000</code></em>.
10+
11+
Since the first game is a practice game, the submarine opens a compartment labeled <em>deterministic dice</em> and a 100-sided die falls out. This die always rolls <code>1</code> first, then <code>2</code>, then <code>3</code>, and so on up to <code>100</code>, after which it starts over at <code>1</code> again. Play using this die.
12+
13+
For example, given these starting positions:
14+
15+
<pre>
16+
<code>Player 1 starting position: 4
17+
Player 2 starting position: 8
18+
</code>
19+
</pre>
20+
21+
This is how the game would go:
22+
23+
24+
- Player 1 rolls <code>1</code>+<code>2</code>+<code>3</code> and moves to space <code>10</code> for a total score of <code>10</code>.
25+
- Player 2 rolls <code>4</code>+<code>5</code>+<code>6</code> and moves to space <code>3</code> for a total score of <code>3</code>.
26+
- Player 1 rolls <code>7</code>+<code>8</code>+<code>9</code> and moves to space <code>4</code> for a total score of <code>14</code>.
27+
- Player 2 rolls <code>10</code>+<code>11</code>+<code>12</code> and moves to space <code>6</code> for a total score of <code>9</code>.
28+
- Player 1 rolls <code>13</code>+<code>14</code>+<code>15</code> and moves to space <code>6</code> for a total score of <code>20</code>.
29+
- Player 2 rolls <code>16</code>+<code>17</code>+<code>18</code> and moves to space <code>7</code> for a total score of <code>16</code>.
30+
- Player 1 rolls <code>19</code>+<code>20</code>+<code>21</code> and moves to space <code>6</code> for a total score of <code>26</code>.
31+
- Player 2 rolls <code>22</code>+<code>23</code>+<code>24</code> and moves to space <code>6</code> for a total score of <code>22</code>.
32+
33+
...after many turns...
34+
35+
36+
- Player 2 rolls <code>82</code>+<code>83</code>+<code>84</code> and moves to space <code>6</code> for a total score of <code>742</code>.
37+
- Player 1 rolls <code>85</code>+<code>86</code>+<code>87</code> and moves to space <code>4</code> for a total score of <code>990</code>.
38+
- Player 2 rolls <code>88</code>+<code>89</code>+<code>90</code> and moves to space <code>3</code> for a total score of <code>745</code>.
39+
- Player 1 rolls <code>91</code>+<code>92</code>+<code>93</code> and moves to space <code>10</code> for a final score, <code>1000</code>.
40+
41+
Since player 1 has at least <code>1000</code> points, player 1 wins and the game ends. At this point, the losing player had <code>745</code> points and the die had been rolled a total of <code>993</code> times; <code>745 * 993 = <em>739785</em></code>.
42+
43+
Play a practice game using the deterministic 100-sided die. The moment either player wins, <em>what do you get if you multiply the score of the losing player by the number of times the die was rolled during the game?</em>
44+
45+
46+
## --- Part Two ---
47+
Now that you're warmed up, it's time to play the real game.
48+
49+
A second compartment opens, this time labeled <em>Dirac dice</em>. Out of it falls a single three-sided die.
50+
51+
As you experiment with the die, you feel a little strange. An informational brochure in the compartment explains that this is a <em>quantum die</em>: when you roll it, the universe <em>splits into multiple copies</em>, one copy for each possible outcome of the die. In this case, rolling the die always splits the universe into <em>three copies</em>: one where the outcome of the roll was <code>1</code>, one where it was <code>2</code>, and one where it was <code>3</code>.
52+
53+
The game is played the same as before, although to prevent things from getting too far out of hand, the game now ends when either player's score reaches at least <code><em>21</em></code>.
54+
55+
Using the same starting positions as in the example above, player 1 wins in <code><em>444356092776315</em></code> universes, while player 2 merely wins in <code>341960390180808</code> universes.
56+
57+
Using your given starting positions, determine every possible outcome. <em>Find the player that wins in more universes; in how many universes does that player win?</em>
58+
59+

2021/Day21/Solution.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Collections.Immutable;
4+
using System.Linq;
5+
using System.Text.RegularExpressions;
6+
using System.Text;
7+
8+
namespace AdventOfCode.Y2021.Day21;
9+
10+
[ProblemName("Dirac Dice")]
11+
class Solution : Solver {
12+
13+
public object PartOne(string input) {
14+
var die = Die();
15+
16+
var pos = Parse(input);
17+
var point = new int[] { 0, 0 };
18+
var roll = 0;
19+
while (true) {
20+
foreach (var i in new[] { 0, 1 }) {
21+
var s = 0;
22+
for (var k = 0; k < 3; k++) {
23+
die.MoveNext();
24+
roll++;
25+
s += die.Current;
26+
}
27+
pos[i] = (pos[i] - 1 + s) % 10 + 1;
28+
point[i] += pos[i];
29+
if (point[i] >= 1000) {
30+
return point[1 - i] * roll;
31+
}
32+
}
33+
}
34+
}
35+
36+
public object PartTwo(string input) {
37+
38+
var cache = new Dictionary<(Player, Player), (long, long)>();
39+
40+
(long win1, long win2) winner(Player player1, Player player2) {
41+
if (player2.score >= 21) {
42+
return (1, 0);
43+
}
44+
45+
var key = (player1, player2);
46+
if (!cache.ContainsKey(key)) {
47+
var res = (win1: 0L, win2: 0L);
48+
foreach (var steps in DiracThrows()) {
49+
var w = winner(player2, player1.Move(steps));
50+
res = (win1: res.win1 + w.win2, win2: res.win2 + w.win1);
51+
}
52+
cache[key] = res;
53+
}
54+
return cache[key];
55+
}
56+
57+
var foo = Parse(input);
58+
var player1 = new Player(0, foo[0]);
59+
var player2 = new Player(0, foo[1]);
60+
61+
var wins = winner(player1, player2);
62+
return Math.Max(wins.win1, wins.win2);
63+
}
64+
65+
IEnumerator<int> Die() {
66+
var i = 1;
67+
while (true) {
68+
yield return i;
69+
i++;
70+
if (i > 100) {
71+
i = 1;
72+
}
73+
}
74+
}
75+
76+
IEnumerable<int> DiracThrows() =>
77+
from i in new[] { 1, 2, 3 }
78+
from j in new[] { 1, 2, 3 }
79+
from k in new[] { 1, 2, 3 }
80+
select i + j + k;
81+
82+
int[] Parse(string input) => (
83+
from line in input.Split("\n")
84+
let parts = line.Split(": ")
85+
select int.Parse(parts[1])
86+
).ToArray();
87+
}
88+
89+
record Player(int score, int pos) {
90+
public Player Move(int steps) {
91+
var newPos = (this.pos - 1 + steps) % 10 + 1;
92+
return new Player(this.score + newPos, newPos);
93+
}
94+
}

2021/Day21/input.in

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

2021/Day21/input.refout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
720750
2+
275067741811212

2021/SplashScreen.cs

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@ public void Show() {
99

1010
var color = Console.ForegroundColor;
1111
Write(0xcc00, false, " ▄█▄ ▄▄█ ▄ ▄ ▄▄▄ ▄▄ ▄█▄ ▄▄▄ ▄█ ▄▄ ▄▄▄ ▄▄█ ▄▄▄\n █▄█ █ █ █ █ █▄█ █ █ █ █ █ █▄ ");
12-
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ λy.2021\n \n ");
13-
Write(0xcc00, false, " ");
12+
Write(0xcc00, false, " █ █ █ █ █ █▄█\n █ █ █▄█ ▀▄▀ █▄▄ █ █ █▄ █▄█ █ █▄ █▄█ █▄█ █▄▄ 0x0000 | 2021\n ");
13+
Write(0xcc00, false, " \n ");
1414
Write(0xc8ff, false, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ");
1515
Write(0xcccccc, false, " 1 ");
1616
Write(0xffff66, false, "**\n ");
17-
Write(0xb5ed, false, " .. . ~ . . . ' ");
17+
Write(0xb5ed, false, ". . . .. . ' . . ");
1818
Write(0xffffff, false, ". ");
19-
Write(0xb5ed, false, ". ' ");
19+
Write(0xb5ed, false, " . ");
2020
Write(0xa47a4d, false, "..'''' ");
2121
Write(0xcccccc, false, " 2 ");
2222
Write(0xffff66, false, "**\n ");
23-
Write(0xa2db, false, " . . . ' . . . ");
23+
Write(0xa2db, false, ".. . . ' ");
2424
Write(0xffffff, false, ". ");
25-
Write(0xa2db, false, " . ");
25+
Write(0xa2db, false, " . ");
2626
Write(0xa47a4d, false, ": ");
2727
Write(0xcccccc, false, " 3 ");
2828
Write(0xffff66, false, "**\n ");
29-
Write(0x91cc, false, " . .' . ' . .. ");
29+
Write(0x91cc, false, ". .. . . ~' ");
3030
Write(0xffffff, false, ".' ");
31-
Write(0x91cc, false, ". ");
31+
Write(0x91cc, false, " . ");
3232
Write(0xa47a4d, false, "....' ");
3333
Write(0xcccccc, false, " 4 ");
3434
Write(0xffff66, false, "**\n ");
35-
Write(0x85c0, false, " ~.. .' ");
35+
Write(0x85c0, false, ". . . . . .' ");
3636
Write(0xc74c30, false, ".");
3737
Write(0xff0000, false, ".");
3838
Write(0xffffff, false, "|\\");
@@ -41,83 +41,86 @@ public void Show() {
4141
Write(0xa47a4d, false, "'' ");
4242
Write(0xcccccc, false, " 5 ");
4343
Write(0xffff66, false, "**\n ");
44-
Write(0x79b5, false, " .. . . ");
44+
Write(0x79b5, false, " . . . . . . ");
4545
Write(0xa47a4d, false, ": ");
4646
Write(0xcccccc, false, " 6 ");
4747
Write(0xffff66, false, "**\n ");
48-
Write(0x6daa, false, ". . . ~ ");
48+
Write(0x6daa, false, " . . .'. . ");
4949
Write(0xa47a4d, false, ":' ");
5050
Write(0xcccccc, false, " 7 ");
5151
Write(0xffff66, false, "**\n ");
52-
Write(0x619f, false, " . . ' ' ");
52+
Write(0x619f, false, " . '~ . ");
5353
Write(0xa47a4d, false, "'''''..... ..");
5454
Write(0xc74c30, false, ".");
5555
Write(0xff0000, false, ". ");
5656
Write(0xcccccc, false, " 8 ");
5757
Write(0xffff66, false, "**\n ");
58-
Write(0x5a98, false, " . . . . ");
58+
Write(0x5a98, false, ". . . . . ");
5959
Write(0xa47a4d, false, ":'.. .. '' ");
6060
Write(0xff0000, false, "': ");
6161
Write(0xcccccc, false, " 9 ");
6262
Write(0xffff66, false, "**\n ");
63-
Write(0x5291, false, " . ' . .' . ' . ");
63+
Write(0x5291, false, " ~ . . ");
6464
Write(0xa47a4d, false, ": '' ''''.. ");
6565
Write(0xc74c30, false, "'");
6666
Write(0xa47a4d, false, ". ");
6767
Write(0xcccccc, false, "10 ");
6868
Write(0xffff66, false, "**\n ");
69-
Write(0x4a8a, false, ". . ");
69+
Write(0x4a8a, false, " . . . ~ ");
7070
Write(0xa47a4d, false, ": '..'. : ");
7171
Write(0xcccccc, false, "11 ");
7272
Write(0xffff66, false, "**\n ");
73-
Write(0x4282, false, " . . . . ");
73+
Write(0x4282, false, " .. ");
7474
Write(0xa47a4d, false, ": :'''.. ..' : ");
7575
Write(0xcccccc, false, "12 ");
7676
Write(0xffff66, false, "**\n ");
77-
Write(0x3b7b, false, " .. . ' ' ");
77+
Write(0x3b7b, false, ". . ... ");
7878
Write(0xa47a4d, false, ".' ..'' ''' ...: ");
7979
Write(0xcccccc, false, "13 ");
8080
Write(0xffff66, false, "**\n ");
81-
Write(0x3374, false, ". . . . ");
81+
Write(0x3374, false, " ..' . . ");
8282
Write(0xa47a4d, false, ": ...'' ..': ");
8383
Write(0xff0000, false, ".");
8484
Write(0xc74c30, false, ".");
8585
Write(0xa47a4d, false, "..' ");
8686
Write(0xcccccc, false, "14 ");
8787
Write(0xffff66, false, "**\n ");
88-
Write(0x2e6f, false, " ' .. . ");
88+
Write(0x2e6f, false, ". . . .. ' ");
8989
Write(0xa47a4d, false, ":' ...''' ");
9090
Write(0xc74c30, false, "'");
9191
Write(0xff0000, false, "'' ");
9292
Write(0xcccccc, false, "15 ");
9393
Write(0xffff66, false, "**\n ");
9494
Write(0xa47a4d, false, "'.'. ");
95-
Write(0x296b, false, ". . . ");
95+
Write(0x296b, false, " ' ");
9696
Write(0xa47a4d, false, ":'. ....' ");
9797
Write(0xcccccc, false, "16 ");
9898
Write(0xffff66, false, "**\n ");
99-
Write(0xa47a4d, false, ": : ' ");
99+
Write(0xa47a4d, false, ": ");
100+
Write(0x2566, false, " ' .. ");
101+
Write(0xa47a4d, false, ": ' ");
100102
Write(0xcccccc, false, "17 ");
101103
Write(0xffff66, false, "**\n ");
102-
Write(0x584338, false, ": ");
103-
Write(0x2062, false, " . . ");
104-
Write(0x584338, false, "..' ");
104+
Write(0x584338, false, ": ..' ");
105105
Write(0xcccccc, false, "18 ");
106106
Write(0xffff66, false, "**\n ");
107107
Write(0x584338, false, "'. ");
108-
Write(0x1b5e, false, "... ");
108+
Write(0x1b5e, false, " ' ");
109109
Write(0x584338, false, ": ");
110110
Write(0xcccccc, false, "19 ");
111111
Write(0xffff66, false, "**\n ");
112112
Write(0x584338, false, "'. ");
113-
Write(0x1759, false, " . ");
113+
Write(0x1759, false, " '. ");
114114
Write(0x584338, false, ": ");
115115
Write(0xcccccc, false, "20 ");
116-
Write(0xffff66, false, "**\n ");
117-
Write(0x333333, false, " : ' . : ");
118-
Write(0x666666, false, "21\n 22\n ");
119-
Write(0x666666, false, " 23\n 24\n ");
120-
Write(0x666666, false, " 25\n \n");
116+
Write(0xffff66, false, "**\n ");
117+
Write(0x584338, false, ": : ");
118+
Write(0xcccccc, false, "21 ");
119+
Write(0xffff66, false, "**\n ");
120+
Write(0x333333, false, " '. ' : ");
121+
Write(0x666666, false, "22\n 23\n ");
122+
Write(0x666666, false, " 24\n 25\n ");
123+
Write(0x666666, false, " \n");
121124

122125
Console.ForegroundColor = color;
123126
Console.WriteLine();

0 commit comments

Comments
 (0)