use std::convert::TryFrom; #[path = "../lib.rs"] mod lib; fn get_input() -> Vec { return lib::iter_input().map(|s| s.parse().unwrap()).collect(); } fn mod_add(a: usize, b: i64, n: usize) -> usize { let ri = (a as i64 + b).rem_euclid(n as i64); return usize::try_from(ri).unwrap(); } fn index(a: &Vec, value: T) -> usize { return a.iter().position(|v| *v == value).unwrap(); } fn mix(input: &Vec, factor: i64, rounds: usize) -> i64 { let n = input.len(); let mut indices: Vec = (0..n).collect(); for _ in 0..rounds { for i in 0..n { let a = indices[i]; // in the example, 0 is mapped to n - 1. // However, because this is circular, it doesn't make a difference. let b = mod_add(a, input[i] * factor, n - 1); for v in indices.iter_mut() { if *v > a { *v -= 1; } if *v >= b { *v += 1; } } indices[i] = b; } } let offset = indices[index(input, 0)]; return ( input[index(&indices, (offset + 1000) % n)] + input[index(&indices, (offset + 2000) % n)] + input[index(&indices, (offset + 3000) % n)] ) * factor; } fn main() { let input = get_input(); println!("part1: {}", mix(&input, 1, 1)); println!("part2: {}", mix(&input, 811589153, 10)); }