diff --git a/src/day22.rs b/src/day22.rs index 043f0d4..d102ff2 100644 --- a/src/day22.rs +++ b/src/day22.rs @@ -1,4 +1,6 @@ -use std::{fs::read_to_string, ops::BitXor}; +use std::{collections::HashSet, fs::read_to_string, ops::BitXor}; + +use itertools::Itertools; pub fn day_main() { let input = read_to_string("input/day22.txt").unwrap(); @@ -16,13 +18,17 @@ fn part1(input: &str) -> RiddleResult { fn solution(initial_secret: i64) -> i64 { let mut secret = initial_secret; for _ in 0..2000 { - secret = prune(mix(secret * 64, secret)); - secret = prune(mix(secret / 32, secret)); - secret = prune(mix(secret * 2048, secret)) + secret = fun_name(secret); } secret } +fn fun_name(secret: i64) -> i64 { + let secret = prune(mix(secret * 64, secret)); + let secret = prune(mix(secret / 32, secret)); + prune(mix(secret * 2048, secret)) +} + fn mix(value: i64, secret: i64) -> i64 { value.bitxor(secret) } @@ -31,15 +37,89 @@ fn prune(value: i64) -> i64 { value % 16777216 } -fn part2(_input: &str) -> RiddleResult { - 0 +fn part2(input: &str) -> RiddleResult { + let deltas = input + .trim() + .lines() + .map(|is| is.parse().unwrap()) + .map(|s| generate(s)) + .collect_vec(); + + let all_quadruples = sequences(&deltas); + println!( + "we have {} different sequences to check", + all_quadruples.len() + ); + + all_quadruples + .into_iter() + .enumerate() + .map(|(n, seq)| { + if n % 100 == 0 { + println!("{n}"); + } + + deltas + .iter() + .map(|monkey| find_first(seq, monkey)) + .flat_map(|first| first.map(|f| f.3.price).or(Some(0))) + .sum() + }) + .max() + .unwrap() +} + +fn sequences(deltas: &Vec>) -> HashSet<(i64, i64, i64, i64)> { + let mut all_quadruples = HashSet::new(); + for monkey in deltas { + monkey + .iter() + .skip(1) + .tuple_windows() + .for_each(|(a, b, c, d)| { + all_quadruples.insert((a.delta, b.delta, c.delta, d.delta)); + }); + } + all_quadruples +} + +fn find_first(seq: (i64, i64, i64, i64), monkey: &Vec) -> Option<(&Foo, &Foo, &Foo, &Foo)> { + monkey.iter().tuple_windows().find(|(a, b, c, d)| { + a.delta == seq.0 && b.delta == seq.1 && c.delta == seq.2 && d.delta == seq.3 + }) +} + +fn generate(start: i64) -> Vec { + let mut result = Vec::with_capacity(2000); + result.push(Foo { + secret: start, + price: start % 10, + delta: -999999, + }); + for i in 1..=2000 { + let prev = result[i - 1].secret; + let next = fun_name(prev); + let price = next % 10; + let delta = price - result[i - 1].price; + result.push(Foo { + secret: next, + price, + delta, + }); + } + result +} + +#[derive(Debug, PartialEq, Eq)] +struct Foo { + secret: i64, + price: i64, + delta: i64, } #[cfg(test)] mod test { - use super::{part1, part2}; - - const TEST_INPUT: &str = r""; + use super::*; #[test] fn test1() { @@ -57,6 +137,25 @@ mod test { #[test] fn test2() { - assert_eq!(part2(TEST_INPUT), 0); + let input = "1 +2 +3 +2024 + "; + assert_eq!(part2(input), 23); + } + + #[test] + fn finds_first() { + let monkey = generate(123); + let f = find_first((-1, -1, 0, 2), &monkey); + assert_eq!( + &Foo { + secret: 12683156, + price: 6, + delta: 2, + }, + f.unwrap().3 + ); } } diff --git a/src/day24.rs b/src/day24.rs index 94064e4..64681fd 100644 --- a/src/day24.rs +++ b/src/day24.rs @@ -169,7 +169,7 @@ where #[cfg(test)] mod test { - use super::{part1, part2}; + use super::part1; const TEST_INPUT: &str = r"x00: 1 x01: 0 @@ -222,9 +222,4 @@ tnw OR pbm -> gnj"; fn test1() { assert_eq!(part1(TEST_INPUT), 2024); } - - #[test] - fn test2() { - assert_eq!(part2(TEST_INPUT), 0); - } }