diff --git a/2024/Day22/Solution.cs b/2024/Day22/Solution.cs index 52934a0a..889eda8f 100644 --- a/2024/Day22/Solution.cs +++ b/2024/Day22/Solution.cs @@ -1,82 +1,60 @@ namespace AdventOfCode.Y2024.Day22; -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Text.RegularExpressions; -using System.Text; -using System.Numerics; [ProblemName("Monkey Market")] class Solution : Solver { public object PartOne(string input) { - return GetNums(input).Select(x => (long)Step(x).Last()).Sum(); + return GetNums(input).Select(x => (long)SecretNumbers(x).Last()).Sum(); } public object PartTwo(string input) { - var mainDict = new Dictionary<(int a, int b, int c, int d), int>(); - foreach(var num in GetNums(input)) { - var banana = GetBanana(num); - foreach(var k in banana.Keys){ - mainDict[k] = mainDict.GetValueOrDefault(k) + banana[k]; + // create a dictionary of all buying options then select the one with the most banana: + + var buyingOptions = new Dictionary(); + foreach (var num in GetNums(input)) { + var optionsBySeller = BuyingOptions(num); + foreach(var seq in optionsBySeller.Keys){ + buyingOptions[seq] = buyingOptions.GetValueOrDefault(seq) + optionsBySeller[seq]; } } - return mainDict.Values.Max(); + return buyingOptions.Values.Max(); } - Dictionary<(int a, int b, int c, int d), int> GetBanana(int num) { - var res = new Dictionary<(int a, int b, int c, int d), int>(); + Dictionary BuyingOptions(int seed) { + var bananasSold = Bananas(seed).ToArray(); + + var buyOptions = new Dictionary(); - var prices = Step(num).Select(n => n % 10).ToArray(); - for(var i = 5;i < prices.Length; i++) { - var slice = prices[(i-5) .. i]; - var diff = Diff(slice); - var key = (diff[0], diff[1], diff[2], diff[3]); - if (!res.ContainsKey(key)) { - res[key] = slice.Last(); + // a sliding window of 5 elements over the sold bananas defines the sequence the monkey + // will recognize. add the first occurrence of each sequence to the buyOptions dictionary + // with the corresponding banana count + for (var i = 5;i < bananasSold.Length; i++) { + var slice = bananasSold[(i-5) .. i]; + var seq = string.Join(",", Diff(slice)); + if (!buyOptions.ContainsKey(seq)) { + buyOptions[seq] = slice.Last(); } } - return res; - // var diff = Diff(steps).ToArray(); - - // var res = 0; - // for(var i = seq.Length-1; i Quads(int[] nums) { - for(var i = 4;i<=nums.Length;i++) { - yield return nums[(i-4) .. i]; - } - + return buyOptions; } + int[] Bananas(int seed) => SecretNumbers(seed).Select(n => n % 10).ToArray(); + int[] Diff(IEnumerable x) => x.Zip(x.Skip(1)).Select(p => p.Second - p.First).ToArray(); - int[] Diff(IEnumerable x) { - return x.Zip(x.Skip(1)).Select(p => p.Second - p.First).ToArray(); - } - IEnumerable Step(int a) { - yield return a; + IEnumerable SecretNumbers(int seed) { + var mixAndPrune = (int a, long b) => (int)((a ^ b) % 16777216); + + yield return seed; for(var i = 0;i< 2000;i++) { - var b = (long)a; - b = Mix(b, b * 64); - b = Prune(b); - b = Mix(b, b/32); - b = Prune(b); - b = Mix(b, b*2048); - b = Prune(b); - a = (int)b; - yield return a; + seed = mixAndPrune(seed, seed * 64L); + seed = mixAndPrune(seed, seed / 32L); + seed = mixAndPrune(seed, seed * 2048L); + yield return seed; } } - long Mix(long a, long b) => a ^ b; - long Prune(long a) => a % 16777216; - - IEnumerable GetNums(string input) => - input.Split("\n").Select(int.Parse); + IEnumerable GetNums(string input) => input.Split("\n").Select(int.Parse); } \ No newline at end of file