Day 22: Monkey Market
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Rust
Part 2 is crazy slow, but it works, so thats cool :D
Edit: Gonna fix this, because pt2 is stupid.
#[cfg(test)] mod tests { use std::collections::HashMap; use std::iter::zip; fn step(start: usize) -> usize { let mut next = start; next = ((next * 64) ^ next) % 16777216; next = ((next / 32) ^ next) % 16777216; next = ((next * 2048) ^ next) % 16777216; next } fn simulate(initial: usize) -> usize { let mut next = initial; for _ in 0..2000 { next = step(next); } next } #[test] fn test_step() { assert_eq!(15887950, step(123)); } #[test] fn test_simulate() { assert_eq!(8685429, simulate(1)); } #[test] fn day22_part1_test() { let input = std::fs::read_to_string("src/input/day_22.txt").unwrap(); let initial_values = input .split("\n") .map(|s| s.parse::<usize>().unwrap()) .collect::<Vec<usize>>(); let mut total = 0; for value in initial_values { total += simulate(value); } println!("{}", total); } fn count_bananas(p0: &str, p1: &[String], p2: &[Vec<usize>]) -> usize { let mut total = 0; for (delta, value) in zip(p1, p2) { match delta.find(p0) { None => continue, Some(i) => total += value[i + 3], } } total } #[test] fn day22_part2_test() { let input = std::fs::read_to_string("src/input/day_22.txt").unwrap(); let initial_values = input .split("\n") .map(|s| s.parse::<usize>().unwrap()) .collect::<Vec<usize>>(); let mut all_deltas = vec![]; let mut all_values = vec![]; for value in initial_values { let mut deltas = String::with_capacity(2000); let mut values = vec![]; let mut prev = value; for _ in 0..2000 { let next = step(prev); values.push(next % 10); deltas.push((10u8 + b'A' + ((prev % 10) as u8) - ((next % 10) as u8)) as char); prev = next; } all_deltas.push(deltas); all_values.push(values); } let mut cache = HashMap::new(); for (i, delta) in all_deltas.iter().enumerate() { for j in 0..delta.len() - 3 { let seq = &delta[j..j + 4]; if cache.contains_key(seq) { continue; } let bananas = count_bananas(seq, &all_deltas[i..], &all_values[i..]); cache.insert(seq, bananas); } } let max_bananas = cache.values().max().unwrap(); println!("{}", max_bananas); } }
Six minutes? 😅 I was feeling crappy about my 30 seconds (my naive big O cubed(?) logic means my code spends most of its time testing array equalities - 72 billion samples in the flamegraph!)
Most of my time is wasted on hashmap stuff. And the processing into the string, which really isnt needed anymore. :/
Have you tried gxhash or one of the other non-cryptographic hashers?
I probably should give that a try. Looks like it can just drop in, so might try it later. I see FxHash is pretty popular here as well.