102 lines
1.8 KiB
Rust
102 lines
1.8 KiB
Rust
use std::io::{self, Read};
|
|
use std::collections::HashSet;
|
|
|
|
|
|
fn parse(input: &str) -> Vec<u16> {
|
|
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<u16>) -> (Vec<u16>, 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);
|
|
}
|
|
}
|