use std::io::{self, BufRead}; fn get_diff_bits_count(a: u32, b: u32) -> usize { // return 0 if equal, 1 if 1 bit is different, else 2 let diff = a ^ b; if diff == 0 { return 0 } if (diff & diff.overflowing_sub(1).0) == 0 { return 1 } return 2; } fn find_reflection_axis(pattern: &Vec, has_smack: bool) -> Option { for i in 1..pattern.len() { let mut found_smack = false; let diff = get_diff_bits_count(pattern[i-1], pattern[i]); if has_smack && diff == 1 { found_smack = true; } if diff == 0 || found_smack { // find two identical neighbors (or differing by 1 for task 2 let mut matching = true; for j in 1..i.min(pattern.len() - i) { // check top and bottom if equal (or diff by 1 bit if has_smack) let diff = get_diff_bits_count(pattern[i-1-j], pattern[i+j]); if diff == 0 { continue; } if has_smack && diff == 1 && !found_smack { // allow only one smack found_smack = true; continue; } matching = false; break; } if matching && (!has_smack || (has_smack && found_smack)) { // require smack for task 2 return Some(i); } } } return None; } fn do_task(horizontal: &Vec, vertical: &Vec, has_smack: bool) -> usize { let mut mirror_sum: usize = 0; if let Some(x) = find_reflection_axis(&horizontal, has_smack) { mirror_sum += x * 100; } if let Some(x) = find_reflection_axis(&vertical, has_smack) { mirror_sum += x; } return mirror_sum; } fn main() { // let input = "example.txt"; let input = "input.txt"; let lines = read_lines(&input); let mut horizontal: Vec = Vec::new(); let mut vertical: Vec = Vec::new(); horizontal.reserve(20); vertical.reserve(20); let mut mirror_sum1: usize = 0; let mut mirror_sum2: usize = 0; let convert = |c| -> u32 { if c == '#' { 1 } else { 0 } }; for line in lines.map(|r| r.ok().unwrap()) { if line.len() == 0 { if horizontal.len() != 0 { // skip first time mirror_sum1 += do_task(&horizontal, &vertical, false); mirror_sum2 += do_task(&horizontal, &vertical, true); } horizontal.clear(); vertical.clear(); continue; } if horizontal.len() == 0 { // 0 for each column (0..line.len()).for_each(|_| vertical.push(0)); } horizontal.push(0); for (i, n) in line.chars().map(|c| convert(c)).enumerate() { *horizontal.last_mut().unwrap() |= (n << i); vertical[i] |= (n << (horizontal.len()-1)); } } mirror_sum1 += do_task(&horizontal, &vertical, false); mirror_sum2 += do_task(&horizontal, &vertical, true); println!("Sum: (1): {}", mirror_sum1); println!("Sum: (2): {}", mirror_sum2); } fn read_lines

(filename: P) -> io::Lines> where P: AsRef, { return match std::fs::File::open(filename) { Err(why) => panic!("Could not open file. {}", why), Ok(file) => std::io::BufReader::new(file).lines() }; }