As you're all teleported deep into the jungle, a monkey steals The Historians' device! You'll need get it back while The Historians are looking for the Chief.
The monkey that stole the device seems willing to trade it, but only in exchange for an absurd number of bananas. Your only option is to buy bananas on the Monkey Exchange Market.
Visit the website for the full story and full puzzle description.
A refreshing challenge after yesterday's hard one. I created a secret number generator function that returns the 2001 numbers for each seller (the initial one and the 2000 additional). This is enough for Part 1.
For Part 2 I maintain the dictionary of buying options for each potential sequence the monkey can recognize with the combined amount of bananas this would generate from all sellers.
namespace AdventOfCode.Y2024.Day22;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
[ProblemName("Monkey Market")]
class Solution : Solver {
public object PartOne(string input) {
return GetNums(input).Select(x => (long)SecretNumbers(x).Last()).Sum();
}
public object PartTwo(string input) {
// create a dictionary of all buying options then select the one with the most banana:
var buyingOptions = new Dictionary<(int,int,int,int), int>();
foreach (var num in GetNums(input)) {
var optionsBySeller = BuyingOptions(num);
foreach (var seq in optionsBySeller.Keys) {
buyingOptions[seq] = buyingOptions.GetValueOrDefault(seq) + optionsBySeller[seq];
}
}
return buyingOptions.Values.Max();
}
Dictionary<(int,int,int,int), int> BuyingOptions(int seed) {
var bananasSold = Bananas(seed).ToArray();
var buyingOptions = new Dictionary<(int,int,int,int), int>();
// 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 buyingOptions dictionary
// with the corresponding banana count
var diff = Diff(bananasSold);
for (var i = 0; i < bananasSold.Length - 4; i++) {
var seq = (diff[i], diff[i+1], diff[i+2], diff[i+3]);
if (!buyingOptions.ContainsKey(seq)) {
buyingOptions[seq] = bananasSold[i+4];
}
}
return buyingOptions;
}
int[] Bananas(int seed) => SecretNumbers(seed).Select(n => n % 10).ToArray();
int[] Diff(IEnumerable<int> x) => x.Zip(x.Skip(1)).Select(p => p.Second - p.First).ToArray();
IEnumerable<int> SecretNumbers(int seed) {
var mixAndPrune = (int a, int b) => (a ^ b) & 0xffffff;
yield return seed;
for (var i = 0; i < 2000; i++) {
seed = mixAndPrune(seed, seed << 6);
seed = mixAndPrune(seed, seed >> 5);
seed = mixAndPrune(seed, seed << 11);
yield return seed;
}
}
IEnumerable<int> GetNums(string input) => input.Split("\n").Select(int.Parse);
}
Please ☆ my repo if you like it!