AoC2020/src/day15.rs

89 lines
2.5 KiB
Rust

use std::io::Read;
use std::collections::HashMap;
fn init_memory<F: Read> (mut input: F) -> (HashMap<usize, usize>, usize) {
let mut buffer = String::new();
input.read_to_string(&mut buffer).unwrap();
let mut init: Vec<usize> = buffer.trim().split(',').map(|s| s.parse().unwrap()).collect();
let last = init.pop().unwrap();
let memory = init.iter().cloned().enumerate().map(|(turn, nb)| (nb, turn)).collect();
(memory, last)
}
fn play(mut memory: HashMap<usize, usize>, last_number: usize, max_turns: usize) -> usize {
let start = memory.len();
let end = max_turns - 1;
let mut last_number = last_number;
let mut current_number;
for turn in start..end {
current_number = memory.get(&last_number).map(|last_turn| turn - last_turn).unwrap_or(0);
memory.insert(last_number, turn);
last_number = current_number;
}
last_number
}
pub fn part1<F: Read> (input: F) {
let (memory, last) = init_memory(input);
println!("{}", play(memory, last, 2020));
}
// slow (~1min in debug mode / ~4s release mode) but working
pub fn part2<F: Read> (input: F) {
let (memory, last) = init_memory(input);
println!("{}", play(memory, last, 30000000));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
pub fn test_parse() {
let input = "0,3,6\n".as_bytes();
let memory: HashMap<usize, usize> = [(0, 0), (3, 1)].iter().cloned().collect();
assert_eq!((memory, 6), init_memory(input));
}
#[test]
pub fn test_play() {
let mut test_cases = vec![
("0,3,6", 436),
("1,3,2", 1),
("2,1,3", 10),
("1,2,3", 27),
("2,3,1", 78),
("3,2,1", 438),
("3,1,2", 1836),
];
for (input, res) in test_cases.drain(..) {
let (memory, last) = init_memory(input.as_bytes());
assert_eq!(res, play(memory, last, 2020));
}
}
/* Too slow to run each time (~1min / iteration)
#[test]
pub fn test_play_again() {
let mut test_cases = vec![
("0,3,6", 175594),
("1,3,2", 2578),
("2,1,3", 3544142),
("1,2,3", 261214),
("2,3,1", 6895259),
("3,2,1", 18),
("3,1,2", 362),
];
for (input, res) in test_cases.drain(..) {
let (memory, last) = init_memory(input.as_bytes());
assert_eq!(res, play(memory, last, 30000000));
println!("passed")
}
}
*/
}