use std::error::Error;
use std::path::Path;
+use std::collections::{HashMap, HashSet};
fn mix(value: u64, secret: u64) -> u64 {
value ^ secret
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<isize> {
+ let mut seq: Vec<u64> = 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<isize> {
+ (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::<HashMap<_, _>>();
+
+ 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<u64, Box<dyn Error>> {
println!("Running {} - part 1", get_day());
let res: u64 = input.lines()
.map(|l| l.parse::<u64>().unwrap())
- .map(|secret| new_secret(secret, 2000))
+ .map(|secret| new_secret_steps(secret, 2000))
.sum();
Ok(res)
fn run_part2(input: &str) -> Result<u64, Box<dyn Error>> {
println!("Running {} - part 2", get_day());
- Ok(0)
+ // for each buyer, compute compute all its secrets
+ let buyer_secrets: Vec<u64> = input.lines()
+ .map(|l| l.parse::<u64>().unwrap())
+ .collect();
+
+ // for each buyer, extract its prices
+ let prices: Vec<Vec<isize>> = buyer_secrets.iter()
+ .map(|secret| buyer_prices(*secret, 2000))
+ .collect();
+
+ // for each buyer, compute the sequence of price changes
+ let seqs: Vec<Vec<isize>> = 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<HashMap<&[isize], isize>> = 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<dyn Error>> {
use super::*;
static TEXT_INPUT: &str = "\
-";
+1
+2
+3
+2024";
#[test]
fn test_part1() {
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());
}
}