#![allow(dead_code)] use std::collections::HashMap; use std::fs::File; use std::io::Read; #[derive(Hash, Eq, Debug, PartialEq, Clone, Copy)] enum Spc { Rol, Fix, Non, } fn new_north_y(x: usize, y: usize, m: &Vec>) -> usize { for yi in (0..y).rev() { if m[yi][x] != Spc::Non { return yi + 1; } } // reached the end of map return 0; } fn rotate_negative(m: Vec>) -> Vec> { let mut out: Vec> = Vec::new(); for i in 0..m[0].len() { let mut r: Vec = Vec::new(); for j in (0..m.len()).rev() { r.push(m[j][i]); } out.push(r); } out } fn print_m(m: &Vec>) { for i in 0..m.len() { for j in 0..m[0].len() { let a = match m[i][j] { Spc::Rol => 'O', Spc::Fix => '#', Spc::Non => '.', }; print!("{}", a); } println!(); } println!(); } fn calc_load(m: &Vec>) -> usize { let mut load = 0; for i in 0..m[0].len() { for j in 0..m.len() { if m[j][i] == Spc::Rol { load += m.len() - j; } } } load } fn main() { // let filename = "in/day14.ref"; let filename = "in/day14.pzl"; let mut f = File::open(filename).expect("cannot open file"); let mut content = String::new(); f.read_to_string(&mut content).expect("cannot read file"); let lines = content.trim_end().split('\n'); let mut m: Vec> = Vec::new(); for line in lines { let mut r: Vec = Vec::new(); for c in line.chars() { let s = match c { 'O' => Spc::Rol, '#' => Spc::Fix, '.' => Spc::Non, _ => panic!(), }; r.push(s); } m.push(r); } let mut m2 = m.clone(); for i in 0..m[0].len() { for j in 0..m.len() { if m[j][i] == Spc::Rol { let new_y = new_north_y(i, j, &m); m[j][i] = Spc::Non; m[new_y][i] = Spc::Rol; } } } let res1 = calc_load(&m); let mut mm: HashMap>, u64> = HashMap::new(); let mut cm: HashMap = HashMap::new(); let mut c0 = 0; let mut c1 = 0; for cycle in 1.. { for _ in 0..4 { for i in 0..m2[0].len() { for j in 0..m2.len() { if m2[j][i] == Spc::Rol { let new_y = new_north_y(i, j, &m2); m2[j][i] = Spc::Non; m2[new_y][i] = Spc::Rol; } } } m2 = rotate_negative(m2); } cm.insert(cycle, calc_load(&m2)); if let Some(cycle_start) = mm.insert(m2.clone(), cycle) { c0 = cycle_start; c1 = cycle; break; } } let res2 = cm[&((1000000000 - c0) % (c1 - c0) + c0)]; println!("res1: {}", res1); println!("res2: {}", res2); assert_eq!(res1, 103333); assert_eq!(res2, 97241); }