diff --git a/Year2022/Day11.cs b/Year2022/Day11.cs new file mode 100644 index 0000000..a1ef506 --- /dev/null +++ b/Year2022/Day11.cs @@ -0,0 +1,171 @@ +using AdventOfCode.Utils.Extensions; + +namespace AdventOfCode.Year2022; + +public class Day11 +{ + private static readonly List Part1Monkeys = new(); + private static readonly List Part2Monkeys = new(); + + public Day11() + { + Console.WriteLine("Day11 Solution"); + + File.ReadAllText("inputs/day11.txt").Split("\n\n").ToList().ForEach(monkey => + { + string[] lines = monkey.Split("\n"); + + // Getting starting items + List items1 = new List(); + List items2 = new List(); + lines[1][(lines[1].IndexOf(':') + 2)..].Split(", ").ToList().ForEach(item => + { + items1.Add(new(Convert.ToInt32(item))); + items2.Add(new(Convert.ToInt32(item))); + }); + + // Getting operation + string op = lines[2][19..]; + + // Getting test info + int test = Convert.ToInt32(lines[3][21..]); + (int, int) testMonkeys = (Convert.ToInt32(lines[4][29..]), Convert.ToInt32(lines[5][30..])); + + Part1Monkeys.Add(new Monkey(items1, op, test, testMonkeys)); + Part2Monkeys.Add(new Monkey(items2, op, test, testMonkeys)); + }); + + Console.WriteLine($"Part1 Result: {Part1()}"); + Console.WriteLine($"Part2 Result: {Part2()}"); + Console.WriteLine("\n=============================\n"); + } + + private static ulong Part1() + { + ulong[] inspections = new ulong[Part1Monkeys.Count]; + + for (int round = 0; round < 20; round++) + foreach (Monkey monkey in Part1Monkeys) + { + foreach (Item item in monkey.Items) + { + 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 + ? monkey.TestMonkeys.Item1 + : monkey.TestMonkeys.Item2 + ].Items.Add(item); + inspections[Part1Monkeys.IndexOf(monkey)]++; + } + monkey.Items.Clear(); + } + + return new List(inspections).ProductOfMax(2); + } + + private static ulong Part2() + { + for (double round = 0; round < 10000; round++) + foreach (var monkey in Part2Monkeys) + { + monkey.UpdateItems(); + Dictionary> receiversAndItems = monkey.GetReceiversAndItems(); + foreach (int key in receiversAndItems.Keys) + Part2Monkeys[key].ReceiveItems(receiversAndItems[key]); + } + List topMonkeys = new List(); + Part2Monkeys.ForEach(monkey => topMonkeys.Add((ulong) monkey.TotalItemsChecked)); + return topMonkeys.ProductOfMax(2); + } + + private class Monkey + { + public List Items { get; set; } + public string Operation { get; } + public int DivisionTest { get; } + public (int, int) TestMonkeys { get; } + public int TotalItemsChecked { get; private set; } + + public Monkey(List items, string operation, int divisionTest, (int, int) testMonkeys) + { + Items = items; + Operation = operation; + DivisionTest = divisionTest; + TestMonkeys = testMonkeys; + TotalItemsChecked = 0; + } + + public void UpdateItems() + { + if (Operation.Contains('+')) + foreach (Item item in Items) + item.UpdateDivisibleBy(Operator.Add, Convert.ToInt32(Operation.Split(" ").Last())); + else if (Operation == "old * old") + foreach (Item item in Items) + item.UpdateDivisibleBy(Operator.Square); + else + foreach (Item item in Items) + item.UpdateDivisibleBy(Operator.Multiply, Convert.ToInt32(Operation.Split(" ").Last())); + TotalItemsChecked += Items.Count; + } + + public Dictionary> GetReceiversAndItems() + { + Dictionary> result = new Dictionary> + { + [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(); + return result; + } + + public void ReceiveItems(List items) + { + Items.AddRange(items); + } + } + + private class Item + { + public int Value { get; set; } + public Dictionary DivisibleBy { get; } = new(); + + public Item(int value) + { + Value = value; + foreach (int i in new[] { 2, 3, 5, 7, 11, 13, 17, 19, 23 }) + DivisibleBy.Add(i, value % i); + } + + public void UpdateDivisibleBy(Operator op, int value = default) + { + foreach (int key in DivisibleBy.Keys) + 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 + { + Add, Multiply, Square + } +} \ No newline at end of file diff --git a/Year2022/Loader2022.cs b/Year2022/Loader2022.cs index 5375877..7816b55 100644 --- a/Year2022/Loader2022.cs +++ b/Year2022/Loader2022.cs @@ -4,6 +4,12 @@ public static class Loader2022 { public static void Load() { + /* Year 2022 + * + * Solutions in C# for the 2022 Advent of Code + * Slower solutions are commented + */ + new Day1(); new Day2(); new Day3(); @@ -11,8 +17,9 @@ public static class Loader2022 new Day5(); new Day6(); new Day7(); - // new Day8(); -- Commented because it's a slow solution + // new Day8(); new Day9(); new Day10(); + // new Day11(); } } \ No newline at end of file