use std::io::{self, Read}; use std::collections::HashSet; fn parse(input: &str) -> Vec { input.split_whitespace().flat_map(str::parse).collect() } fn cycle(input: &mut [u16]) { let (index, blocks) = input .iter() .enumerate() .fold((0, 0), |acc, (index, blocks)| { if *blocks > acc.1 { (index, *blocks) } else { acc } }); input[index] = 0; let len = input.len(); for i in 0..blocks as usize { input[(index + i + 1) % len] += 1; } } fn infinit_loop(mut memory: Vec) -> (Vec, usize) { let mut states = HashSet::new(); states.insert(memory.clone()); let mut i = 0; loop { i += 1; cycle(&mut memory); if states.contains(&memory) { break; } states.insert(memory.clone()); } (memory, i) } fn main() { let mut input = String::new(); io::stdin() .read_to_string(&mut input) .expect("faild to read input"); for entry in input.lines().filter(|line| !line.is_empty()).map(parse) { let (state, cycle) = infinit_loop(entry); println!("part_one={}", cycle); let (_, cycle) = infinit_loop(state); println!("part_two={}", cycle); } } #[cfg(test)] mod tests { use super::*; #[test] fn test_parse() { assert_eq!(parse("0 2 7 0"), vec![0, 2, 7, 0]); } #[test] fn test_cycle() { let mut data = vec![0, 2, 7, 0]; cycle(&mut data); assert_eq!(data, vec![2, 4, 1, 2]); } #[test] fn test_infinit_loop() { let data = vec![0, 2, 7, 0]; let (state, cycle) = infinit_loop(data); assert_eq!(cycle, 5); let (_, cycle) = infinit_loop(state); assert_eq!(cycle, 4); } }