Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/advent-of-code-2021
Path: blob/main/src/day21.rs
97 views
1
pub fn run() {
2
// Doesn't make sense to parse the input on this one really.
3
let p1_pos = 6;
4
let p2_pos = 7;
5
6
part1(p1_pos, p2_pos);
7
part2(p1_pos, p2_pos);
8
}
9
10
fn part1(p1_pos: i32, p2_pos: i32) {
11
let mut positions = [p1_pos, p2_pos];
12
let mut scores = [0, 0];
13
let mut player = 0;
14
let mut roll = 1;
15
16
loop {
17
for _ in 0..3 {
18
positions[player] = (positions[player] + roll - 1) % 10 + 1;
19
roll += 1;
20
}
21
scores[player] += positions[player];
22
if scores[player] >= 1000 {
23
break;
24
}
25
26
player = (player + 1) % 2;
27
}
28
29
println!("{}", scores[0].min(scores[1]) * (roll - 1))
30
}
31
32
fn part2(p1_pos: i32, p2_pos: i32) {
33
let (p1_wins, p2_wins) = dirac_dice_wins(p1_pos, p2_pos, 0, 0);
34
println!("{}", p1_wins.max(p2_wins));
35
}
36
37
// For 3 rolls of a Dirac dice there is only one chance for them to add up to 3,
38
// 3 chances of adding up to 4, and so on...
39
const DIRAC_DICE_3_ROLL_CHANCES: [(i32, usize); 7] =
40
[(3, 1), (4, 3), (5, 6), (6, 7), (7, 6), (8, 3), (9, 1)];
41
42
// Calculates the number of universes in which player 1 and 2 win.
43
fn dirac_dice_wins(p1_pos: i32, p2_pos: i32, p1_score: i32, p2_score: i32) -> (usize, usize) {
44
let (mut p1_wins, mut p2_wins) = (0, 0);
45
for (die_roll, chance) in DIRAC_DICE_3_ROLL_CHANCES {
46
let p1_sub_pos = (p1_pos + die_roll - 1) % 10 + 1;
47
let p1_sub_score = p1_score + p1_sub_pos;
48
if p1_sub_score >= 21 {
49
p1_wins += chance
50
} else {
51
let (p2_sub_wins, p1_sub_wins) = dirac_dice_wins(p2_pos, p1_sub_pos, p2_score, p1_sub_score);
52
p1_wins += chance * p1_sub_wins;
53
p2_wins += chance * p2_sub_wins;
54
}
55
}
56
(p1_wins, p2_wins)
57
}
58
59