Solve 22
This commit is contained in:
parent
51a2a71716
commit
20be794e88
1 changed files with 84 additions and 0 deletions
84
src/bin/22.rs
Normal file
84
src/bin/22.rs
Normal file
|
@ -0,0 +1,84 @@
|
|||
use aoc::*;
|
||||
use itertools::Itertools;
|
||||
use std::collections::HashMap;
|
||||
use std::iter;
|
||||
|
||||
const INPUT: &str = include_str!("../../input/22");
|
||||
|
||||
fn main() {
|
||||
assert_example!(part1, "22-test", 37327623);
|
||||
println!("Part 1: {}", part1(INPUT));
|
||||
assert_example!(part2, "22-test", 24);
|
||||
println!("Part 2: {}", part2(INPUT));
|
||||
}
|
||||
|
||||
fn part1(input: &str) -> usize {
|
||||
parse(input)
|
||||
.map(|secret| secret_numbers(secret).last().unwrap())
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part2(input: &str) -> usize {
|
||||
let buyers = parse(input);
|
||||
let possible_sales = buyers.flat_map(possible_sales);
|
||||
|
||||
let mut sequences = HashMap::new();
|
||||
for (seq, price) in possible_sales {
|
||||
let price = price as usize;
|
||||
let entry = sequences.entry(seq).or_insert(0);
|
||||
*entry += price;
|
||||
}
|
||||
|
||||
sequences.into_values().max().unwrap()
|
||||
}
|
||||
|
||||
fn possible_sales(secret: usize) -> HashMap<[i8; 4], u8> {
|
||||
let mut sales = HashMap::new();
|
||||
for (a, b, c, d) in price_changes(secret).tuple_windows() {
|
||||
let seq = [a.change, b.change, c.change, d.change];
|
||||
sales.entry(seq).or_insert(d.price);
|
||||
}
|
||||
sales
|
||||
}
|
||||
|
||||
fn price_changes(secret: usize) -> impl Iterator<Item = PriceChange> {
|
||||
let prices = secret_numbers(secret).map(|s| (s % 10) as u8);
|
||||
prices.tuple_windows().map(|(a, b)| PriceChange {
|
||||
price: b,
|
||||
change: b as i8 - a as i8,
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct PriceChange {
|
||||
price: u8,
|
||||
change: i8,
|
||||
}
|
||||
|
||||
fn secret_numbers(mut secret: usize) -> impl Iterator<Item = usize> {
|
||||
iter::from_fn(move || {
|
||||
let s = secret;
|
||||
secret = mix_prune(secret);
|
||||
Some(s)
|
||||
})
|
||||
.take(2001)
|
||||
}
|
||||
|
||||
fn mix_prune(mut secret: usize) -> usize {
|
||||
const MOD: usize = 16777216;
|
||||
|
||||
let n = secret * 64;
|
||||
secret = (secret ^ n) % MOD;
|
||||
|
||||
let n = secret / 32;
|
||||
secret = (secret ^ n) % MOD;
|
||||
|
||||
let n = secret * 2048;
|
||||
secret = (secret ^ n) % MOD;
|
||||
|
||||
secret
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> impl Iterator<Item = usize> + use<'_> {
|
||||
input.lines().map(|line| line.parse().unwrap())
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue