From: alex <> Date: Sun, 22 Dec 2024 13:27:36 +0000 (+0100) Subject: Day22 - part 2 X-Git-Url: https://aoc.elinar.fr/?a=commitdiff_plain;h=99252de446f8c6d7f57694a5790126225adec990;p=aoc_2024 Day22 - part 2 --- diff --git a/src/day22.rs b/src/day22.rs index c30a8d0..ee13fc7 100644 --- a/src/day22.rs +++ b/src/day22.rs @@ -1,5 +1,6 @@ use std::error::Error; use std::path::Path; +use std::collections::{HashMap, HashSet}; fn mix(value: u64, secret: u64) -> u64 { value ^ secret @@ -9,22 +10,60 @@ fn prune(value: u64) -> u64 { value % 16777216 } -fn new_secret(secret: u64, steps: usize) -> u64 { +fn new_secret_steps(secret: u64, steps: usize) -> u64 { let mut s = secret; - for i in 0..steps { + (0..steps).for_each(|_| { s = prune(mix(s * 64, s)); s = prune(mix(s / 32, s)); s = prune(mix(s * 2048, s)); - } + }); s } +fn new_secret(secret: u64) -> u64 { + let s = secret; + let s = prune(mix(s * 64, s)); + let s = prune(mix(s / 32, s)); + prune(mix(s * 2048, s)) +} + +fn buyer_prices(secret: u64, steps: usize) -> Vec { + let mut seq: Vec = Vec::new(); + seq.push(secret); + (1..steps).for_each(|_| { + let last_secret = *seq.last().unwrap(); + seq.push(new_secret(last_secret)); + }); + seq.into_iter().map(|s| (s % 10) as isize).collect() +} + +fn buyer_seq(buyer_prices: &[isize]) -> Vec { + (1..buyer_prices.len()).zip(0..(buyer_prices.len()-1)) + .map(|(i, j)| buyer_prices[i] - buyer_prices[j]) + .collect() +} + +fn buyer_windows(buyer_seq: &[isize]) -> HashMap<&[isize], isize> { + let windows = buyer_seq.windows(4).enumerate() + //.filter(|(i, w)| *w == vec![-2, 1, -1, 3]) + .collect::>(); + + let mut bw: HashMap<&[isize], isize> = HashMap::new(); + for (idx, w) in windows { + match bw.get_mut(w) { + Some(i) => { *i = (*i).min(idx as isize); } , + None => { bw.insert(w, idx as isize); } , + } + } + bw +} + fn run_part1(input: &str) -> Result> { println!("Running {} - part 1", get_day()); let res: u64 = input.lines() .map(|l| l.parse::().unwrap()) - .map(|secret| new_secret(secret, 2000)) + .map(|secret| new_secret_steps(secret, 2000)) .sum(); Ok(res) @@ -33,7 +72,56 @@ fn run_part1(input: &str) -> Result> { fn run_part2(input: &str) -> Result> { println!("Running {} - part 2", get_day()); - Ok(0) + // for each buyer, compute compute all its secrets + let buyer_secrets: Vec = input.lines() + .map(|l| l.parse::().unwrap()) + .collect(); + + // for each buyer, extract its prices + let prices: Vec> = buyer_secrets.iter() + .map(|secret| buyer_prices(*secret, 2000)) + .collect(); + + // for each buyer, compute the sequence of price changes + let seqs: Vec> = prices.iter() + .map(|p| buyer_seq(p)) + .collect(); + + // for each buyer, extract all windows of 4 price changes with its associated index + let mut seqs_w: Vec> = seqs.iter() + .map(|s| buyer_windows(s)) + .collect(); + + // for each buyer, associate the current price to each window + for (i, seq) in seqs_w.iter_mut().enumerate() { + seq.iter_mut() + .for_each(|(_, j)| { *j = prices[i][(*j+4) as usize]; }); + } + + // store all windows + let mut windows: HashSet<&[isize]> = HashSet::new(); + seqs_w.iter() + .for_each(|s| { + s.iter().for_each(|(w, _)| { windows.insert(w); }); + }); + + // search for the best window + let mut max: u64 = 0; + windows.iter() + .for_each(|w| { + let mut m: u64 = 0; + seqs_w.iter() + .for_each(|s| { + if let Some(v) = s.get(w) { + m += *v as u64; + } + }); + if m > max { + max = m; + } + }); + + Ok(max) } pub fn run(input: &str) -> Result<(), Box> { @@ -56,7 +144,10 @@ mod tests { use super::*; static TEXT_INPUT: &str = "\ -"; +1 +2 +3 +2024"; #[test] fn test_part1() { @@ -65,16 +156,21 @@ mod tests { 12683156, 11100544, 12249484, 7753432, 5908254, ]; for step in 0..secret_123_steps.len() { - assert_eq!(new_secret(123, step + 1), secret_123_steps[step]); + assert_eq!(new_secret_steps(123, step + 1), secret_123_steps[step]); } - assert_eq!(new_secret(1, 2000), 8685429); - assert_eq!(new_secret(10, 2000), 4700978); - assert_eq!(new_secret(100, 2000), 15273692); - assert_eq!(new_secret(2024, 2000), 8667524); + assert_eq!(new_secret_steps(1, 2000), 8685429); + assert_eq!(new_secret_steps(10, 2000), 4700978); + assert_eq!(new_secret_steps(100, 2000), 15273692); + assert_eq!(new_secret_steps(2024, 2000), 8667524); } #[test] fn test_part2() { - assert_eq!(0, run_part2(TEXT_INPUT).unwrap()); + let buyer_123_prices = buyer_prices(123, 10); + assert_eq!(buyer_123_prices, vec![3, 0, 6, 5, 4, 4, 6, 4, 4, 2]); + let buyer_123_seq = buyer_seq(&buyer_123_prices); + assert_eq!(buyer_123_seq, vec![-3, 6, -1, -1, 0, 2, -2, 0, -2]); + + assert_eq!(23, run_part2(TEXT_INPUT).unwrap()); } }