Add day 11 part 1
This commit is contained in:
204
Days/Day11.cs
Normal file
204
Days/Day11.cs
Normal file
@@ -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<int> _items;
|
||||
private readonly Func<int, int> _operation;
|
||||
private readonly int _testDivider;
|
||||
private readonly int _testFailMonkey;
|
||||
private readonly int _testSuccessMonkey;
|
||||
|
||||
public Monkey(int number, IEnumerable<int> items, Func<int, int> operation, int testDivider, int testFailMonkey, int testSuccessMonkey)
|
||||
{
|
||||
Number = number;
|
||||
_operation = operation;
|
||||
_testDivider = testDivider;
|
||||
_testFailMonkey = testFailMonkey;
|
||||
_testSuccessMonkey = testSuccessMonkey;
|
||||
|
||||
InspectionCount = 0;
|
||||
_items = new Queue<int>(items);
|
||||
}
|
||||
|
||||
public void AddItem(int item)
|
||||
{
|
||||
_items.Enqueue(item);
|
||||
}
|
||||
|
||||
public bool ThrowItem(IImmutableList<Monkey> 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<Monkey> ParseMonkeys()
|
||||
{
|
||||
var monkeys = new List<Monkey>();
|
||||
|
||||
// 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<int, int> 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
|
||||
}
|
||||
Reference in New Issue
Block a user