use std::{collections::HashSet, hash::Hash}; use nom::{ IResult, character::complete::{self,multispace1}, multi::separated_list1, sequence::{preceded, separated_pair}, bytes::streaming::tag, }; fn parse_input(input: &str) -> IResult<&str, Vec<((i32, i32), (i32, i32))>> { let (input, coords) = separated_list1( multispace1, preceded( tag("Sensor at x="), separated_pair( separated_pair( complete::i32, tag(", y="), complete::i32, ), tag(": closest beacon is at x="), separated_pair( complete::i32, tag(", y="), complete::i32, )) ) )(input)?; Ok((input, coords)) } fn manhattan_dist(a: (i32, i32), b: (i32, i32)) -> i32 { return (a.0 - b.0).abs() + (a.1 - b.1).abs(); } fn fill_map(beacon_map: &mut HashSet<(i32, i32)>, sensor_coord: (i32, i32), beacon_coord: (i32, i32)) { let dist = manhattan_dist(sensor_coord, beacon_coord); let (sx, sy) = sensor_coord; for i in 0..=dist { for j in 0..=i { beacon_map.insert((sx + i, sy + j)); beacon_map.insert((sx - i, sy + j)); beacon_map.insert((sx + i, sy - j)); beacon_map.insert((sx - i, sy - j)); } } } fn fill_line(beacon_line: &mut HashSet, sensor_coord: (i32, i32), beacon_coord: (i32, i32), test_line: i32) { let dist = manhattan_dist(sensor_coord, beacon_coord); let (sx, sy) = sensor_coord; let cross_section_len = dist - (test_line - sy).abs(); if cross_section_len >= 0 { for i in 0..=cross_section_len { beacon_line.insert(sx + i); beacon_line.insert(sx - i); } } } fn main() { let test_y = 2000000; let input_text = include_str!("../input.txt"); let (_rest, coord_list) = parse_input(input_text).unwrap(); // Testing the parsing // for ((sx, sy), (bx, by)) in coord_list { // println!("Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}"); // } // Naive method // let mut beacon_map = HashSet::new(); // for (sensor, beacon) in coord_list { // fill_map(&mut beacon_map, sensor, beacon); // } // let positions = beacon_map.into_iter().filter(|(_, y)| *y == test_y).count(); // println!("Number of positions with y={test_y}: {positions}"); // A slightly less naive approach let mut beacon_line = HashSet::new(); for (sensor, beacon) in coord_list { fill_line(&mut beacon_line, sensor, beacon, test_y); } println!("Number of positions with y={test_y}: {}", beacon_line.len() - 1); }