Add day 11 part 2

This commit is contained in:
2022-12-15 09:03:11 +01:00
parent a985d2e00c
commit fd794bab16

View File

@@ -6,15 +6,15 @@ namespace AdventOfCode.Days;
public class Monkey public class Monkey
{ {
public int Number { get; } public int Number { get; }
public int InspectionCount { get; private set; } public long InspectionCount { get; private set; }
private readonly Queue<int> _items; private readonly Queue<long> _items;
private readonly Func<int, int> _operation; private readonly Func<long, long> _operation;
private readonly int _testDivider; private readonly long _testDivider;
private readonly int _testFailMonkey; private readonly int _testFailMonkey;
private readonly int _testSuccessMonkey; private readonly int _testSuccessMonkey;
public Monkey(int number, IEnumerable<int> items, Func<int, int> operation, int testDivider, int testFailMonkey, int testSuccessMonkey) public Monkey(int number, IEnumerable<long> items, Func<long, long> operation, long testDivider, int testFailMonkey, int testSuccessMonkey)
{ {
Number = number; Number = number;
_operation = operation; _operation = operation;
@@ -23,15 +23,15 @@ public class Monkey
_testSuccessMonkey = testSuccessMonkey; _testSuccessMonkey = testSuccessMonkey;
InspectionCount = 0; InspectionCount = 0;
_items = new Queue<int>(items); _items = new Queue<long>(items);
} }
public void AddItem(int item) public void AddItem(long item)
{ {
_items.Enqueue(item); _items.Enqueue(item);
} }
public bool ThrowItem(IImmutableList<Monkey> monkeys) public bool ThrowItem(IImmutableList<Monkey> monkeys, bool divideWorry = true)
{ {
// Return false if there's no item to throw // Return false if there's no item to throw
if (_items.Count < 1) if (_items.Count < 1)
@@ -49,7 +49,14 @@ public class Monkey
var newValue = _operation(item); var newValue = _operation(item);
// Divide worry level by 3 before test // Divide worry level by 3 before test
newValue = newValue / 3; if (divideWorry)
{
newValue = newValue / 3;
}
// Even using this simplification, it's still needed to use longs because
// they sometime overflow before being simplified in part 2
newValue = newValue % (2*3*5*7*11*13*17*19);
// Test is a success // Test is a success
if (newValue % _testDivider == 0) if (newValue % _testDivider == 0)
@@ -93,7 +100,23 @@ public class Day11 : Day
public override void RunPart2() public override void RunPart2()
{ {
throw new NotImplementedException(); const int roundsCount = 10_000;
var monkeys = ParseMonkeys();
// Do 10 000 rounds
for (int round = 0; round < roundsCount; round++)
{
foreach (var monkey in monkeys)
{
// Throw items while there's some
while (monkey.ThrowItem(monkeys, false)) { }
}
}
var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList();
AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]");
} }
private static IImmutableList<Monkey> ParseMonkeys() private static IImmutableList<Monkey> ParseMonkeys()
@@ -113,13 +136,13 @@ public class Day11 : Day
// Monkey attributes // Monkey attributes
var number = int.Parse(numberLine[numberLine.LastIndexOf(' ')..^1]); var number = int.Parse(numberLine[numberLine.LastIndexOf(' ')..^1]);
var items = itemsLine[(itemsLine.IndexOf(':') + 2)..].Split(", ").Select(int.Parse); var items = itemsLine[(itemsLine.IndexOf(':') + 2)..].Split(", ").Select(long.Parse);
// Read operation // Read operation
operationLine = operationLine[(operationLine.IndexOf('=') + 2)..]; operationLine = operationLine[(operationLine.IndexOf('=') + 2)..];
int? rightOperand = operationLine.EndsWith("old") ? null : int.Parse(operationLine.Split('+', '*')[1].Trim()); long? rightOperand = operationLine.EndsWith("old") ? null : long.Parse(operationLine.Split('+', '*')[1].Trim());
Func<int, int> operation = operationLine.Contains('+') switch Func<long, long> operation = operationLine.Contains('+') switch
{ {
true => rightOperand is null true => rightOperand is null
? old => old + old ? old => old + old
@@ -129,7 +152,7 @@ public class Day11 : Day
: old => old * (int)rightOperand : old => old * (int)rightOperand
}; };
var testDivider = int.Parse(testDividerLine[testDividerLine.LastIndexOf(' ')..]); var testDivider = long.Parse(testDividerLine[testDividerLine.LastIndexOf(' ')..]);
var testSuccessMonkey = int.Parse(testSuccessLine[testSuccessLine.LastIndexOf(' ')..]); var testSuccessMonkey = int.Parse(testSuccessLine[testSuccessLine.LastIndexOf(' ')..]);
var testFailMonkey = int.Parse(testFailLine[testFailLine.LastIndexOf(' ')..]); var testFailMonkey = int.Parse(testFailLine[testFailLine.LastIndexOf(' ')..]);