-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day11.cs
134 lines (122 loc) · 5.42 KB
/
Day11.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
namespace Advent_of_Code_2022
{
internal class Day11 : ISolver
{
public string Title => "Monkey in the Middle";
public string PartOne(string input) => Solve(input, worryLevelDivisor: true, rounds: 20).ToString();
public string PartTwo(string input) => Solve(input, worryLevelDivisor: false, rounds: 10000).ToString();
private static ulong Solve(string input, bool worryLevelDivisor, int rounds)
{
var lines = input.Split("\n", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
var monkeys = new List<Monkey>();
var monkeyInspections = new Dictionary<int, ulong>();
for (int i = 0; i < lines.Length; i += 6)
{
var monkeyLine = lines[i];
var startingItemsLine = lines[i + 1];
var operationLine = lines[i + 2];
var testLine = lines[i + 3];
var ifTrueLine = lines[i + 4];
var ifFalseLine = lines[i + 5];
var monkeyId = int.Parse(monkeyLine.Replace("Monkey ", "").Replace(":", ""));
var startingItems = startingItemsLine.Replace("Starting items: ", "").Split(", ").Select(ulong.Parse).ToList();
var operation = operationLine.Replace("Operation: new = ", "");
var test = ulong.Parse(testLine.Replace("Test: ", "").Replace("divisible by ", ""));
var ifTrue = int.Parse(ifTrueLine.Replace("If true: throw to monkey ", ""));
var ifFalse = int.Parse(ifFalseLine.Replace("If false: throw to monkey ", ""));
monkeys.Add(new Monkey
{
Number = monkeyId,
StartingItems = startingItems,
Operation = operation,
Test = test,
TrueMonkey = ifTrue,
FalseMonkey = ifFalse
});
}
ulong lowestCommonDivisor = 1;
foreach (var monkey in monkeys)
{
lowestCommonDivisor *= monkey.Test;
}
for (int i = 1; i <= rounds; i++)
{
foreach (var monkey in monkeys.OrderBy(m => m.Number))
{
for (int j = 0; j < monkey.StartingItems.Count; j++)
{
ulong item = monkey.StartingItems[j];
if (!monkeyInspections.ContainsKey(monkey.Number))
{
monkeyInspections.Add(monkey.Number, 0);
}
monkeyInspections[monkey.Number]++;
// The order of operations doesn't matter when worryLevelDivisor = true
var worryLevel = PerformOperation(item, monkey.Operation);
var (bored, testResult) = PerformTest(worryLevelDivisor, worryLevel, monkey.Test, lowestCommonDivisor);
monkey.StartingItems.RemoveAt(j);
j--; // Since we have just removed an item
var monkeyToThrowTo = monkeys.Find(m => m.Number == (testResult ? monkey.TrueMonkey : monkey.FalseMonkey));
monkeyToThrowTo?.StartingItems.Add(bored);
}
}
}
var twoMostActiveMonkeys = monkeyInspections.OrderByDescending(m => m.Value).Take(2).ToList();
return (twoMostActiveMonkeys[0].Value * twoMostActiveMonkeys[1].Value);
}
private static ulong PerformOperation(ulong old, string? operation)
{
ulong n = 0;
if (!string.IsNullOrWhiteSpace(operation))
{
if (operation.StartsWith("old * "))
{
var multiplier = operation.Replace("old * ", "");
if (multiplier == "old")
{
n = old * old;
}
else if (ulong.TryParse(multiplier, out ulong m))
{
n = old * m;
}
}
else if (operation.StartsWith("old + "))
{
var add = operation.Replace("old + ", "");
if (add == "old")
{
n = old + old;
}
else if (ulong.TryParse(add, out ulong m))
{
n = old + m;
}
}
}
return n;
}
private static (ulong, bool) PerformTest(bool worryLevelDivisor, ulong worryLevel, ulong divisor, ulong lowestCommonDivisor)
{
if (worryLevelDivisor)
{
var bored = (ulong)Math.Floor(worryLevel / 3.0);
return (bored, bored % divisor == 0);
}
else
{
var bored = worryLevel % lowestCommonDivisor;
return (bored, bored % divisor == 0);
}
}
public class Monkey
{
public int Number { get; set; }
public List<ulong> StartingItems { get; set; } = new();
public string? Operation { get; set; }
public ulong Test { get; set; }
public int TrueMonkey { get; set; }
public int FalseMonkey { get; set; }
}
}
}