diff --git a/.aoc-cache/15.txt b/.aoc-cache/15.txt new file mode 100644 index 0000000..f7e996c --- /dev/null +++ b/.aoc-cache/15.txt @@ -0,0 +1,23 @@ +Sensor at x=325337, y=2568863: closest beacon is at x=-518661, y=2000000 +Sensor at x=3988825, y=837820: closest beacon is at x=4305648, y=2127118 +Sensor at x=1611311, y=2053174: closest beacon is at x=2827226, y=1579510 +Sensor at x=101890, y=3940049: closest beacon is at x=955472, y=3457514 +Sensor at x=3962702, y=2558425: closest beacon is at x=4226981, y=2604726 +Sensor at x=2957890, y=2160813: closest beacon is at x=2827226, y=1579510 +Sensor at x=3907456, y=3325610: closest beacon is at x=3696221, y=3226373 +Sensor at x=3354177, y=3435919: closest beacon is at x=3696221, y=3226373 +Sensor at x=3997379, y=3071868: closest beacon is at x=3696221, y=3226373 +Sensor at x=145143, y=1714962: closest beacon is at x=-518661, y=2000000 +Sensor at x=611563, y=3148864: closest beacon is at x=955472, y=3457514 +Sensor at x=3080405, y=3904777: closest beacon is at x=3696221, y=3226373 +Sensor at x=644383, y=10732: closest beacon is at x=364635, y=-294577 +Sensor at x=3229566, y=1694167: closest beacon is at x=2827226, y=1579510 +Sensor at x=1600637, y=3984884: closest beacon is at x=955472, y=3457514 +Sensor at x=2959765, y=2820860: closest beacon is at x=2491502, y=2897876 +Sensor at x=2235330, y=3427797: closest beacon is at x=2491502, y=2897876 +Sensor at x=2428996, y=210881: closest beacon is at x=2827226, y=1579510 +Sensor at x=369661, y=687805: closest beacon is at x=364635, y=-294577 +Sensor at x=3558476, y=2123614: closest beacon is at x=4305648, y=2127118 +Sensor at x=3551529, y=2825104: closest beacon is at x=3696221, y=3226373 +Sensor at x=64895, y=3577: closest beacon is at x=364635, y=-294577 +Sensor at x=3079531, y=1538659: closest beacon is at x=2827226, y=1579510 diff --git a/src/bin/day_15.rs b/src/bin/day_15.rs new file mode 100644 index 0000000..71050c9 --- /dev/null +++ b/src/bin/day_15.rs @@ -0,0 +1,137 @@ +use std::collections::{HashMap, HashSet}; + +use aoc_2022::prelude::*; + +type Coord = (isize, isize); +#[derive(Debug)] +struct Reading { + sensor: Coord, + beacon: Coord, +} + +type Input = Vec; + +fn parse(s: &str) -> Result { + let mut readings = vec![]; + + for line in s.lines() { + let ints = ints(line); + let sensor = ( + ints[0], + ints[1], + ); + let beacon = ( + ints[2], + ints[3], + ); + readings.push(Reading { sensor, beacon }); + } + + Ok(readings) +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +enum Node { + Sensor { + min_distance: isize, + }, + Beacon, +} + +fn manhatten(a: Coord, b: Coord) -> isize { + (a.0.abs_diff(b.0) + a.1.abs_diff(b.1)) as isize +} + +struct Sensor { + coord: Coord, + min_distance: isize, +} + +#[aoc(day = 15, parse = parse, test_cases = ["day_15.txt"])] +fn day_15(input: Input) -> Result<()> { + // Part 1 + let mut map = HashMap::::new(); + for reading in &input { + let min_distance = manhatten(reading.sensor, reading.beacon); + map.insert(reading.sensor, Node::Sensor { min_distance }); + map.insert(reading.beacon, Node::Beacon); + } + + for y in -2..=22 { + print!("{y: >2} "); + for x in -2..=25 { + if let Some(n) = map.get(&(x, y)) { + let c = match n { + Node::Sensor { .. } => 'S', + Node::Beacon => 'B', + }; + print!("{c}"); + } else { + print!("."); + } + } + println!(); + } + + let sensors = input.iter() + .map(|reading| { + let min_distance = manhatten(reading.sensor, reading.beacon); + Sensor { + coord: reading.sensor, + min_distance, + } + }).collect::>(); + + // const TARGET_Y: isize = 10; + const TARGET_Y: isize = 2_000_000; + + let empty_cells = sensors.iter() + .filter(|sensor| sensor.coord.1.abs_diff(TARGET_Y) as isize <= sensor.min_distance) + .flat_map(|sensor| { + let remaining_dist = sensor.min_distance - (sensor.coord.1.abs_diff(TARGET_Y) as isize); + (sensor.coord.0 - remaining_dist)..=(sensor.coord.0 + remaining_dist) + }) + .map(|x| (x, TARGET_Y)) + .filter(|c| map.get(c).is_none()) + .collect::>(); + + let empty_in_row = empty_cells.len(); + + println!("Part one: {empty_in_row}"); + + // Part 2 + + const RANGE_MIN: isize = 0; + // const RANGE_MAX: isize = 20; + const RANGE_MAX: isize = 4_000_000; + + let location = sensors + .iter() + .flat_map(|sensor| { + let dist = sensor.min_distance + 1; + ((sensor.coord.0 - dist)..=(sensor.coord.1 + dist)) + .flat_map(move |x| { + let remaining_dist = dist - (sensor.coord.0.abs_diff(x) as isize); + [sensor.coord.1 + remaining_dist, sensor.coord.1 - remaining_dist].into_iter() + .map(move |y| (x, y)) + }) + }) + .filter(|c| { + c.0 >= RANGE_MIN && c.0 <= RANGE_MAX + }) + .filter(|c| { + c.1 >= RANGE_MIN && c.1 <= RANGE_MAX + }) + .filter(|c| { + sensors.iter().all(|sensor| { + manhatten(*c, sensor.coord) > sensor.min_distance + }) + }) + .next().unwrap(); + + let tuning_frequency = location.0 * 4000000 + location.1; + + println!("Part two: {tuning_frequency}"); + + Ok(()) +} diff --git a/test_cases/day_15.txt b/test_cases/day_15.txt new file mode 100644 index 0000000..652e631 --- /dev/null +++ b/test_cases/day_15.txt @@ -0,0 +1,14 @@ +Sensor at x=2, y=18: closest beacon is at x=-2, y=15 +Sensor at x=9, y=16: closest beacon is at x=10, y=16 +Sensor at x=13, y=2: closest beacon is at x=15, y=3 +Sensor at x=12, y=14: closest beacon is at x=10, y=16 +Sensor at x=10, y=20: closest beacon is at x=10, y=16 +Sensor at x=14, y=17: closest beacon is at x=10, y=16 +Sensor at x=8, y=7: closest beacon is at x=2, y=10 +Sensor at x=2, y=0: closest beacon is at x=2, y=10 +Sensor at x=0, y=11: closest beacon is at x=2, y=10 +Sensor at x=20, y=14: closest beacon is at x=25, y=17 +Sensor at x=17, y=20: closest beacon is at x=21, y=22 +Sensor at x=16, y=7: closest beacon is at x=15, y=3 +Sensor at x=14, y=3: closest beacon is at x=15, y=3 +Sensor at x=20, y=1: closest beacon is at x=15, y=3 \ No newline at end of file