struct Number { value: usize, } enum Symbol { Asterisk, Other, } enum Tile<'a> { Number(&'a Number), Symbol(Symbol), Period, } fn main() { let stdin = std::io::stdin(); let mut map: Vec> = Vec::new(); for line in stdin.lines() { let line = line.unwrap(); let mut num = Vec::new(); let mut v = Vec::new(); for char in line.chars() { if !char.is_digit(10) && num.len() > 0 { let s: String = num.iter().collect(); let number = Box::leak(Box::new(Number { value: s.parse().unwrap(), })); for _ in 0..s.len() { v.push(Tile::Number(number)); } num.clear(); } if char == '.' { v.push(Tile::Period); } else if char == '*' { v.push(Tile::Symbol(Symbol::Asterisk)); } else if char.is_digit(10) { num.push(char); } else { v.push(Tile::Symbol(Symbol::Other)); } } if num.len() > 0 { let s: String = num.iter().collect(); let number = Box::leak(Box::new(Number { value: s.parse().unwrap(), })); for _ in 0..s.len() { v.push(Tile::Number(number)); } } map.push(v); } // Part 1 let mut part1 = 0; for (x, row) in map.iter().enumerate() { let mut already_added = false; for (y, tile) in row.iter().enumerate() { match tile { Tile::Number(number) => { if already_added { continue; }; for dx in -1i32..=1 { for dy in -1i32..=1 { let ix = x.wrapping_add(dx as usize); let iy = y.wrapping_add(dy as usize); if let Some(v) = map.get(ix) { if let Some(Tile::Symbol(_)) = v.get(iy) { already_added = true; part1 += number.value; } } if already_added { break; }; } if already_added { break; }; } } _ => { if already_added { already_added = false; } } } } } println!("{}", part1); // Part 2 let mut part2 = 0; for (x, row) in map.iter().enumerate() { for (y, tile) in row.iter().enumerate() { if let Tile::Symbol(Symbol::Asterisk) = tile { let mut gears = [None; 2]; let mut gear_num = 0; let mut skip = false; for dx in -1i32..=1 { for dy in -1i32..=1 { let ix = x.wrapping_add(dx as usize); let iy = y.wrapping_add(dy as usize); if let Some(v) = map.get(ix) { if let Some(Tile::Number(number)) = v.get(iy) { if let Some(gear) = gears[0] { if std::ptr::eq(gear, *number) { continue; } } if let Some(gear) = gears[1] { if std::ptr::eq(gear, *number) { continue; } } if gear_num == 2 { skip = true; break; } gears[gear_num] = Some(*number); gear_num += 1; } } } if skip { break; } } if gear_num == 2 { unsafe { part2 += (*gears[0].unwrap()).value * (*gears[1].unwrap()).value; } } } } } println!("{}", part2); }