AdventOfCode/Year2022/Day11.cs

175 lines
5.7 KiB
C#
Raw Normal View History

2023-06-11 22:28:47 +00:00
using AdventOfCode.Utils.Extensions;
namespace AdventOfCode.Year2022;
public class Day11
{
private static readonly List<Monkey> Part1Monkeys = new();
private static readonly List<Monkey> Part2Monkeys = new();
public Day11()
{
File.ReadAllText("inputs/day11.txt").Split("\n\n").ToList().ForEach(monkey =>
{
2023-06-24 21:26:39 +00:00
var lines = monkey.Split("\n");
2023-06-11 22:28:47 +00:00
// Getting starting items
2023-06-24 21:26:39 +00:00
var items1 = new List<Item>();
var items2 = new List<Item>();
2023-06-11 22:28:47 +00:00
lines[1][(lines[1].IndexOf(':') + 2)..].Split(", ").ToList().ForEach(item =>
{
2023-06-24 21:26:39 +00:00
items1.Add(new Item(Convert.ToInt32(item)));
items2.Add(new Item(Convert.ToInt32(item)));
2023-06-11 22:28:47 +00:00
});
2023-06-24 21:26:39 +00:00
2023-06-11 22:28:47 +00:00
// Getting operation
2023-06-24 21:26:39 +00:00
var op = lines[2][19..];
2023-06-11 22:28:47 +00:00
// Getting test info
2023-06-24 21:26:39 +00:00
var test = Convert.ToInt32(lines[3][21..]);
var testMonkeys = (Convert.ToInt32(lines[4][29..]), Convert.ToInt32(lines[5][30..]));
2023-06-11 22:28:47 +00:00
Part1Monkeys.Add(new Monkey(items1, op, test, testMonkeys));
Part2Monkeys.Add(new Monkey(items2, op, test, testMonkeys));
});
2023-06-24 21:26:39 +00:00
Console.WriteLine($@"
Day11 Solution
Part1 Result: {Part1()}
Part2 Result: {Part2()}
=============================");
2023-06-11 22:28:47 +00:00
}
private static ulong Part1()
{
2023-06-24 21:26:39 +00:00
var inspections = new ulong[Part1Monkeys.Count];
for (var round = 0; round < 20; round++)
foreach (var monkey in Part1Monkeys)
2023-06-11 22:28:47 +00:00
{
2023-06-24 21:26:39 +00:00
foreach (var item in monkey.Items)
2023-06-11 22:28:47 +00:00
{
if (monkey.Operation.Contains('+'))
item.Value += Convert.ToInt32(monkey.Operation.Split(" ").Last());
else if (monkey.Operation == "old * old")
item.Value *= item.Value;
else
item.Value *= Convert.ToInt32(monkey.Operation.Split(" ").Last());
item.Value /= 3;
Part1Monkeys[
item.Value % monkey.DivisionTest == 0
2023-06-24 21:26:39 +00:00
? monkey.TestMonkeys.Item1
: monkey.TestMonkeys.Item2
2023-06-11 22:28:47 +00:00
].Items.Add(item);
inspections[Part1Monkeys.IndexOf(monkey)]++;
}
2023-06-24 21:26:39 +00:00
2023-06-11 22:28:47 +00:00
monkey.Items.Clear();
}
return new List<ulong>(inspections).ProductOfMax(2);
}
private static ulong Part2()
{
for (double round = 0; round < 10000; round++)
foreach (var monkey in Part2Monkeys)
{
monkey.UpdateItems();
2023-06-24 21:26:39 +00:00
var receiversAndItems = monkey.GetReceiversAndItems();
foreach (var key in receiversAndItems.Keys)
2023-06-11 22:28:47 +00:00
Part2Monkeys[key].ReceiveItems(receiversAndItems[key]);
}
2023-06-24 21:26:39 +00:00
var topMonkeys = new List<ulong>();
Part2Monkeys.ForEach(monkey => topMonkeys.Add((ulong)monkey.TotalItemsChecked));
2023-06-11 22:28:47 +00:00
return topMonkeys.ProductOfMax(2);
}
private class Monkey
{
public Monkey(List<Item> items, string operation, int divisionTest, (int, int) testMonkeys)
{
Items = items;
Operation = operation;
DivisionTest = divisionTest;
TestMonkeys = testMonkeys;
TotalItemsChecked = 0;
}
2023-06-24 21:26:39 +00:00
public List<Item> Items { get; private set; }
public string Operation { get; }
public int DivisionTest { get; }
public (int, int) TestMonkeys { get; }
public int TotalItemsChecked { get; private set; }
2023-06-11 22:28:47 +00:00
public void UpdateItems()
{
if (Operation.Contains('+'))
2023-06-24 21:26:39 +00:00
foreach (var item in Items)
2023-06-11 22:28:47 +00:00
item.UpdateDivisibleBy(Operator.Add, Convert.ToInt32(Operation.Split(" ").Last()));
else if (Operation == "old * old")
2023-06-24 21:26:39 +00:00
foreach (var item in Items)
2023-06-11 22:28:47 +00:00
item.UpdateDivisibleBy(Operator.Square);
else
2023-06-24 21:26:39 +00:00
foreach (var item in Items)
2023-06-11 22:28:47 +00:00
item.UpdateDivisibleBy(Operator.Multiply, Convert.ToInt32(Operation.Split(" ").Last()));
TotalItemsChecked += Items.Count;
}
public Dictionary<int, List<Item>> GetReceiversAndItems()
{
2023-06-24 21:26:39 +00:00
var result = new Dictionary<int, List<Item>>
2023-06-11 22:28:47 +00:00
{
[TestMonkeys.Item1] = new(),
[TestMonkeys.Item2] = new()
};
Items.ForEach(item =>
{
if (item.DivisibleBy[DivisionTest] == 0)
result[TestMonkeys.Item1].Add(item);
else
result[TestMonkeys.Item2].Add(item);
});
Items = new List<Item>();
return result;
}
public void ReceiveItems(List<Item> items)
{
Items.AddRange(items);
}
}
private class Item
{
public Item(int value)
{
Value = value;
2023-06-24 21:26:39 +00:00
foreach (var i in new[] { 2, 3, 5, 7, 11, 13, 17, 19, 23 })
2023-06-11 22:28:47 +00:00
DivisibleBy.Add(i, value % i);
}
2023-06-24 21:26:39 +00:00
public int Value { get; set; }
public Dictionary<int, int> DivisibleBy { get; } = new();
2023-06-11 22:28:47 +00:00
public void UpdateDivisibleBy(Operator op, int value = default)
{
2023-06-24 21:26:39 +00:00
foreach (var key in DivisibleBy.Keys)
2023-06-11 22:28:47 +00:00
DivisibleBy[key] = op switch
{
Operator.Add => (DivisibleBy[key] + value) % key,
Operator.Multiply => DivisibleBy[key] * value % key,
Operator.Square => DivisibleBy[key] * DivisibleBy[key] % key,
_ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
};
}
}
private enum Operator
{
2023-06-24 21:26:39 +00:00
Add,
Multiply,
Square
2023-06-11 22:28:47 +00:00
}
}