#![allow(dead_code)] #![allow(unused_variables)] #![allow(unused_mut)] use itertools::Itertools; use std::collections::HashMap; use std::collections::HashSet; use std::env; use std::fs::File; use std::io::Read; fn get_antinodes(a: (i32, i32), b: (i32, i32)) -> Vec<(i32, i32)> { let mut ans = Vec::new(); let (ax, ay) = (a.0, a.1); let (bx, by) = (b.0, b.1); let dx = bx - ax; let dy = by - ay; ans.push((bx + dx, by + dy)); ans.push((ax - dx, ay - dy)); return ans; } fn bounded(min: i32, max: i32, val: i32) -> bool { min <= val && val < max } fn get_antinodes2(xmax: i32, ymax: i32, a: (i32, i32), b: (i32, i32)) -> Vec<(i32, i32)> { let mut ans = Vec::new(); let (ax, ay) = (a.0, a.1); let (bx, by) = (b.0, b.1); let dx = bx - ax; let dy = by - ay; ans.push((ax, ay)); ans.push((bx, by)); for n in 1.. { let (ux, uy) = (bx + n * dx, by + n * dy); if !bounded(0, xmax, ux) || !bounded(0, ymax, uy) { break; } ans.push((ux, uy)); } for n in 1.. { let (ux, uy) = (ax - n * dx, ay - n * dy); if !bounded(0, xmax, ux) || !bounded(0, ymax, uy) { break; } ans.push((ux, uy)); } return ans; } fn main() { let args: Vec = env::args().collect(); let filename = if args.len() == 1 { "in/".to_owned() + args[0].split('/').last().unwrap() + ".pzl" } else { args[1].clone() }; 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: Vec<_> = content.trim_end().split("\n").collect(); let ymax = lines.len() as i32; let xmax = lines[0].len() as i32; let mut hm: HashMap> = HashMap::new(); for (y, line) in lines.iter().enumerate() { for (x, c) in line.chars().enumerate() { if c != '.' { hm.entry(c).or_default().push((x as i32, y as i32)); } } } let mut antinodes: HashSet<(i32, i32)> = HashSet::new(); let mut antinodes2: HashSet<(i32, i32)> = HashSet::new(); for (key, val) in hm.clone().into_iter() { for (a, b) in val.clone().into_iter().tuple_combinations() { for (x, y) in get_antinodes(a, b) { if bounded(0, xmax, x) && bounded(0, ymax, y) { antinodes.insert((x, y)); } } for (x, y) in get_antinodes2(xmax, ymax, a, b) { antinodes2.insert((x, y)); } } } let res1 = antinodes.len(); let res2 = antinodes2.len(); println!("res1: {}", res1); println!("res2: {}", res2); assert_eq!(res1, 293); assert_eq!(res2, 934); }