diff --git a/example/day15.txt b/example/day15.txt new file mode 100644 index 0000000..a612424 --- /dev/null +++ b/example/day15.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 diff --git a/input/day15.txt b/input/day15.txt new file mode 100644 index 0000000..fb23c15 --- /dev/null +++ b/input/day15.txt @@ -0,0 +1,38 @@ +Sensor at x=2793338, y=1910659: closest beacon is at x=2504930, y=2301197 +Sensor at x=2887961, y=129550: closest beacon is at x=2745008, y=-872454 +Sensor at x=3887055, y=2785942: closest beacon is at x=4322327, y=2605441 +Sensor at x=3957399, y=2164042: closest beacon is at x=3651713, y=1889668 +Sensor at x=1268095, y=1265989: closest beacon is at x=1144814, y=2000000 +Sensor at x=2093967, y=2103436: closest beacon is at x=2504930, y=2301197 +Sensor at x=2980126, y=1348046: closest beacon is at x=3651713, y=1889668 +Sensor at x=508134, y=3998686: closest beacon is at x=1123963, y=4608563 +Sensor at x=2982740, y=3604350: closest beacon is at x=2756683, y=3240616 +Sensor at x=2372671, y=3929034: closest beacon is at x=2756683, y=3240616 +Sensor at x=437628, y=1124644: closest beacon is at x=570063, y=959065 +Sensor at x=3271179, y=3268845: closest beacon is at x=3444757, y=3373782 +Sensor at x=1899932, y=730465: closest beacon is at x=570063, y=959065 +Sensor at x=1390358, y=3881569: closest beacon is at x=1123963, y=4608563 +Sensor at x=554365, y=989190: closest beacon is at x=570063, y=959065 +Sensor at x=2225893, y=2703661: closest beacon is at x=2504930, y=2301197 +Sensor at x=3755905, y=1346206: closest beacon is at x=3651713, y=1889668 +Sensor at x=3967103, y=3930797: closest beacon is at x=3444757, y=3373782 +Sensor at x=3534099, y=2371166: closest beacon is at x=3651713, y=1889668 +Sensor at x=3420789, y=1720583: closest beacon is at x=3651713, y=1889668 +Sensor at x=2222479, y=3278186: closest beacon is at x=2756683, y=3240616 +Sensor at x=100457, y=871319: closest beacon is at x=570063, y=959065 +Sensor at x=1330699, y=2091946: closest beacon is at x=1144814, y=2000000 +Sensor at x=598586, y=99571: closest beacon is at x=570063, y=959065 +Sensor at x=3436099, y=3392932: closest beacon is at x=3444757, y=3373782 +Sensor at x=3338431, y=3346334: closest beacon is at x=3444757, y=3373782 +Sensor at x=3892283, y=688090: closest beacon is at x=3651713, y=1889668 +Sensor at x=1485577, y=1929020: closest beacon is at x=1144814, y=2000000 +Sensor at x=2991003, y=2951060: closest beacon is at x=2756683, y=3240616 +Sensor at x=2855486, y=2533468: closest beacon is at x=2504930, y=2301197 +Sensor at x=750865, y=1619637: closest beacon is at x=1144814, y=2000000 +Sensor at x=3378101, y=3402212: closest beacon is at x=3444757, y=3373782 +Sensor at x=3515528, y=2950404: closest beacon is at x=3444757, y=3373782 +Sensor at x=163133, y=2640553: closest beacon is at x=-1016402, y=3057364 +Sensor at x=1765550, y=3021994: closest beacon is at x=2756683, y=3240616 +Sensor at x=534625, y=1056421: closest beacon is at x=570063, y=959065 +Sensor at x=3418549, y=3380980: closest beacon is at x=3444757, y=3373782 +Sensor at x=29, y=389033: closest beacon is at x=570063, y=959065 diff --git a/src/day15.rs b/src/day15.rs new file mode 100644 index 0000000..90c6d02 --- /dev/null +++ b/src/day15.rs @@ -0,0 +1,132 @@ +//! Day 15: Beacon Exclusion Zone + +use std::collections::HashSet; + +use once_cell::sync::Lazy; +use regex::Regex; + +type Coord = (i32, i32); + +fn parse_input(input: &[String]) -> Vec<(Coord, Coord)> { + static LINE_REGEX: Lazy = Lazy::new(|| { + Regex::new("Sensor at x=(-?\\d+), y=(-?\\d+): closest beacon is at x=(-?\\d+), y=(-?\\d+)") + .unwrap() + }); + + input + .iter() + .map(|line| { + let cap = LINE_REGEX.captures(line).unwrap(); + ( + ( + cap.get(1).unwrap().as_str().parse().unwrap(), + cap.get(2).unwrap().as_str().parse().unwrap(), + ), + ( + cap.get(3).unwrap().as_str().parse().unwrap(), + cap.get(4).unwrap().as_str().parse().unwrap(), + ), + ) + }) + .collect() +} + +fn mdist(p1: Coord, p2: Coord) -> i32 { + (p1.0.abs_diff(p2.0) + p1.1.abs_diff(p2.1)) as i32 +} + +fn beacon_exclude(pos: Coord, closest: Coord, excluded: &mut HashSet, row: i32) { + let dist = mdist(pos, closest); + + for x in pos.0 - dist..pos.0 + dist { + let point = (x, row); + if point != closest && mdist(pos, point) <= dist { + excluded.insert(point); + } + } +} + +fn beacon_exclude_section(pos: Coord, closest: Coord, excluded: &mut HashSet, limit: i32) { + let dist = mdist(pos, closest); + + for y in 0..=limit { + for x in 0..=limit { + let point = (x, y); + if mdist(pos, point) <= dist { + excluded.insert(point); + } + } + } +} + +fn _part1(input: Vec, row: i32) -> String { + let sensors = parse_input(&input); + let mut excluded = HashSet::new(); + + sensors + .iter() + .for_each(|(pos, closest)| beacon_exclude(*pos, *closest, &mut excluded, row)); + + excluded.len().to_string() +} + +fn _part2(input: Vec, limit: i32) -> String { + let sensors = parse_input(&input); + let mut excluded = HashSet::new(); + + sensors + .iter() + .enumerate() + .for_each(|(i, (pos, closest))| { + println!("bc {}", i); + beacon_exclude_section(*pos, *closest, &mut excluded, limit); + }); + + for y in 0..limit { + for x in 0..limit { + let point = (x, y); + if !excluded.contains(&point) { + dbg!(&point); + let f = point.0 * 4000000 + point.1; + return f.to_string(); + } + } + } + + panic!("not found") +} + +pub fn part1(input: Vec) -> String { + _part1(input, 2000000) +} + +pub fn part2(input: Vec) -> String { + _part2(input, 4000000) +} + +#[cfg(test)] +mod tests { + use super::*; + + const DAY: u8 = 15; + + #[test] + fn t_example1() { + assert_eq!(_part1(crate::read_example(DAY), 10), "26"); + } + + #[test] + fn t_example2() { + assert_eq!(_part2(crate::read_example(DAY), 20), "56000011"); + } + + #[test] + fn t_part1() { + assert_eq!(part1(crate::read_input(DAY)), ""); + } + + #[test] + fn t_part2() { + assert_eq!(part2(crate::read_input(DAY)), ""); + } +} diff --git a/src/main.rs b/src/main.rs index 4b34779..3f47343 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ mod day11; mod day12; mod day13; mod day14; +mod day15; pub(crate) fn read_input(day: u8) -> Vec { read_input_file(path!("input" / format!("day{}.txt", day))) @@ -77,6 +78,7 @@ days! { 12, day12, 13, day13, 14, day14, + 15, day15, } fn main() {