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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy