From a985d2e00c0260a5e569dd2a5cfc2fc3f9545325 Mon Sep 17 00:00:00 2001 From: Eveldee Date: Wed, 14 Dec 2022 13:39:01 +0100 Subject: [PATCH] Add day 11 part 1 --- Days/Day11.cs | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 Days/Day11.cs diff --git a/Days/Day11.cs b/Days/Day11.cs new file mode 100644 index 0000000..a25c214 --- /dev/null +++ b/Days/Day11.cs @@ -0,0 +1,204 @@ +using System.Collections.Immutable; +using Spectre.Console; + +namespace AdventOfCode.Days; + +public class Monkey +{ + public int Number { get; } + public int InspectionCount { get; private set; } + + private readonly Queue _items; + private readonly Func _operation; + private readonly int _testDivider; + private readonly int _testFailMonkey; + private readonly int _testSuccessMonkey; + + public Monkey(int number, IEnumerable items, Func operation, int testDivider, int testFailMonkey, int testSuccessMonkey) + { + Number = number; + _operation = operation; + _testDivider = testDivider; + _testFailMonkey = testFailMonkey; + _testSuccessMonkey = testSuccessMonkey; + + InspectionCount = 0; + _items = new Queue(items); + } + + public void AddItem(int item) + { + _items.Enqueue(item); + } + + public bool ThrowItem(IImmutableList monkeys) + { + // Return false if there's no item to throw + if (_items.Count < 1) + { + return false; + } + + // Increment inspection count + InspectionCount++; + + // Take next item to throw + var item = _items.Dequeue(); + + // Apply the operation on worry level + var newValue = _operation(item); + + // Divide worry level by 3 before test + newValue = newValue / 3; + + // Test is a success + if (newValue % _testDivider == 0) + { + monkeys[_testSuccessMonkey].AddItem(newValue); + } + // Test is a fail + else + { + monkeys[_testFailMonkey].AddItem(newValue); + } + + return true; + } +} + +public class Day11 : Day +{ + public override int Number => 11; + public override string Name => "Monkey in the Middle"; + public override void RunPart1() + { + const int roundsCount = 20; + + var monkeys = ParseMonkeys(); + + // Do 20 rounds + for (int round = 0; round < roundsCount; round++) + { + foreach (var monkey in monkeys) + { + // Throw items while there's some + while (monkey.ThrowItem(monkeys)) { } + } + } + + var topMonkeys = monkeys.OrderByDescending(m => m.InspectionCount).Take(2).ToList(); + + AnsiConsole.MarkupLine($"[green]Monkey business: [yellow]{topMonkeys[0].InspectionCount * topMonkeys[1].InspectionCount}[/][/]"); + } + + public override void RunPart2() + { + throw new NotImplementedException(); + } + + private static IImmutableList ParseMonkeys() + { + var monkeys = new List(); + + // Split by monkey description + foreach (var monkey in Input.ReplaceLineEndings("\n").Split("\n\n")) + { + var split = monkey.Split('\n'); + var numberLine = split[0]; + var itemsLine = split[1]; + var operationLine = split[2]; + var testDividerLine = split[3]; + var testSuccessLine = split[4]; + var testFailLine = split[5]; + + // Monkey attributes + var number = int.Parse(numberLine[numberLine.LastIndexOf(' ')..^1]); + var items = itemsLine[(itemsLine.IndexOf(':') + 2)..].Split(", ").Select(int.Parse); + + // Read operation + operationLine = operationLine[(operationLine.IndexOf('=') + 2)..]; + int? rightOperand = operationLine.EndsWith("old") ? null : int.Parse(operationLine.Split('+', '*')[1].Trim()); + + Func operation = operationLine.Contains('+') switch + { + true => rightOperand is null + ? old => old + old + : old => old + (int)rightOperand, + false => rightOperand is null + ? old => old * old + : old => old * (int)rightOperand + }; + + var testDivider = int.Parse(testDividerLine[testDividerLine.LastIndexOf(' ')..]); + var testSuccessMonkey = int.Parse(testSuccessLine[testSuccessLine.LastIndexOf(' ')..]); + var testFailMonkey = int.Parse(testFailLine[testFailLine.LastIndexOf(' ')..]); + + monkeys.Add(new Monkey(number, items, operation, testDivider, testFailMonkey, testSuccessMonkey)); + } + + return monkeys.ToImmutableList(); + } + + #region Input + + public const string Input = + """ + Monkey 0: + Starting items: 89, 95, 92, 64, 87, 68 + Operation: new = old * 11 + Test: divisible by 2 + If true: throw to monkey 7 + If false: throw to monkey 4 + + Monkey 1: + Starting items: 87, 67 + Operation: new = old + 1 + Test: divisible by 13 + If true: throw to monkey 3 + If false: throw to monkey 6 + + Monkey 2: + Starting items: 95, 79, 92, 82, 60 + Operation: new = old + 6 + Test: divisible by 3 + If true: throw to monkey 1 + If false: throw to monkey 6 + + Monkey 3: + Starting items: 67, 97, 56 + Operation: new = old * old + Test: divisible by 17 + If true: throw to monkey 7 + If false: throw to monkey 0 + + Monkey 4: + Starting items: 80, 68, 87, 94, 61, 59, 50, 68 + Operation: new = old * 7 + Test: divisible by 19 + If true: throw to monkey 5 + If false: throw to monkey 2 + + Monkey 5: + Starting items: 73, 51, 76, 59 + Operation: new = old + 8 + Test: divisible by 7 + If true: throw to monkey 2 + If false: throw to monkey 1 + + Monkey 6: + Starting items: 92 + Operation: new = old + 5 + Test: divisible by 11 + If true: throw to monkey 3 + If false: throw to monkey 0 + + Monkey 7: + Starting items: 99, 76, 78, 76, 79, 90, 89 + Operation: new = old + 7 + Test: divisible by 5 + If true: throw to monkey 4 + If false: throw to monkey 5 + """; + + #endregion +} \ No newline at end of file