From d34dcb5957830178f8d13e79f5bb1989324ffbea Mon Sep 17 00:00:00 2001 From: Sebastian Knackstedt Date: Fri, 16 Dec 2022 00:05:06 +0100 Subject: [PATCH] Add day 15 --- Cargo.toml | 4 ++ day15.txt | 26 +++++++++ day15_test.txt | 14 +++++ src/day15/main.rs | 137 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 181 insertions(+) create mode 100644 day15.txt create mode 100644 day15_test.txt create mode 100644 src/day15/main.rs diff --git a/Cargo.toml b/Cargo.toml index 1a04e6a..e0da8ac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,4 +65,8 @@ path = "src/day13/main.rs" name = "day14" path = "src/day14/main.rs" +[[bin]] +name = "day15" +path = "src/day15/main.rs" + [dependencies] diff --git a/day15.txt b/day15.txt new file mode 100644 index 0000000..4fedadd --- /dev/null +++ b/day15.txt @@ -0,0 +1,26 @@ +Sensor at x=3772068, y=2853720: closest beacon is at x=4068389, y=2345925 +Sensor at x=78607, y=2544104: closest beacon is at x=-152196, y=4183739 +Sensor at x=3239531, y=3939220: closest beacon is at x=3568548, y=4206192 +Sensor at x=339124, y=989831: closest beacon is at x=570292, y=1048239 +Sensor at x=3957534, y=2132743: closest beacon is at x=3897332, y=2000000 +Sensor at x=1882965, y=3426126: closest beacon is at x=2580484, y=3654136 +Sensor at x=1159443, y=3861139: closest beacon is at x=2580484, y=3654136 +Sensor at x=2433461, y=287013: closest beacon is at x=2088099, y=-190228 +Sensor at x=3004122, y=3483833: closest beacon is at x=2580484, y=3654136 +Sensor at x=3571821, y=799602: closest beacon is at x=3897332, y=2000000 +Sensor at x=2376562, y=1539540: closest beacon is at x=2700909, y=2519581 +Sensor at x=785113, y=1273008: closest beacon is at x=570292, y=1048239 +Sensor at x=1990787, y=38164: closest beacon is at x=2088099, y=-190228 +Sensor at x=3993778, y=3482849: closest beacon is at x=4247709, y=3561264 +Sensor at x=3821391, y=3986080: closest beacon is at x=3568548, y=4206192 +Sensor at x=2703294, y=3999015: closest beacon is at x=2580484, y=3654136 +Sensor at x=1448314, y=2210094: closest beacon is at x=2700909, y=2519581 +Sensor at x=3351224, y=2364892: closest beacon is at x=4068389, y=2345925 +Sensor at x=196419, y=3491556: closest beacon is at x=-152196, y=4183739 +Sensor at x=175004, y=138614: closest beacon is at x=570292, y=1048239 +Sensor at x=1618460, y=806488: closest beacon is at x=570292, y=1048239 +Sensor at x=3974730, y=1940193: closest beacon is at x=3897332, y=2000000 +Sensor at x=2995314, y=2961775: closest beacon is at x=2700909, y=2519581 +Sensor at x=105378, y=1513086: closest beacon is at x=570292, y=1048239 +Sensor at x=3576958, y=3665667: closest beacon is at x=3568548, y=4206192 +Sensor at x=2712265, y=2155055: closest beacon is at x=2700909, y=2519581 \ No newline at end of file diff --git a/day15_test.txt b/day15_test.txt new file mode 100644 index 0000000..652e631 --- /dev/null +++ b/day15_test.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 diff --git a/src/day15/main.rs b/src/day15/main.rs new file mode 100644 index 0000000..a5a395b --- /dev/null +++ b/src/day15/main.rs @@ -0,0 +1,137 @@ +use std::cmp::max; +use std::collections::HashSet; +use base::read_file; + +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] +struct Pos(i32, i32); + +#[derive(Debug, Clone)] +struct Beacon { + pos: Pos, + beacon: Pos, +} + +#[derive(Copy, Clone, Debug)] +struct Range { + start: i32, + end: i32, +} + +impl Range { + fn new(start: i32, end: i32) -> Self { + Range { start, end } + } + + fn contains(&self, number: i32) -> bool { + number >= self.start && number <= self.end + } + + fn fully_overlap(&self, other: &Range) -> bool { + self.contains(other.start) && self.contains(other.end) + } + + fn partly_overlap(&self, other: &Range) -> bool { + self.contains(other.start) || self.contains(other.end) + } +} + +struct YLine { + y: i32, + start_x: i32, + start_y: i32, +} + +impl Beacon { + fn possible_positions_into_of(&self, positions: &mut HashSet, y: i32) { + let distance = self.get_distance(); + for x in -distance..=distance { + if x.abs() + (self.pos.1 - y).abs() <= distance { + positions.insert(Pos(self.pos.0 + x, y)); + } + } + } + + fn get_distance(&self) -> i32 { + let Pos(px, py) = self.pos; + let Pos(bx, by) = self.beacon; + (px - bx).abs() + (py - by).abs() + } +} + +fn main() { + let lines = read_file("day15.txt"); + let mut beacons = vec![]; + + for line in lines { + beacons.push(line.split([' ', '=', ':', ',']).filter_map(|tok| tok.parse::().ok()).collect::>().chunks_exact(4).map(|positions| Beacon { pos: Pos(positions[0], positions[1]), beacon: Pos(positions[2], positions[3]) }).next().unwrap()); + } + + let mut possible_positions = HashSet::new(); + + println!("Found {} beacons", beacons.len()); + + println!("Inserting possible positions"); + let y = 2000000; + + for (idx, beacon) in beacons.iter().enumerate() { + println!("Generating positions for beacon {}", idx); + beacon.possible_positions_into_of(&mut possible_positions, y); + } + + println!("Inserting beacons"); + + for beacon in &beacons { + possible_positions.remove(&beacon.pos); + possible_positions.remove(&beacon.beacon); + } + + + println!("Searching for possible positions"); + + let count = possible_positions.iter().filter(|pos| pos.1 == y).count(); + + println!("Found {} at {}", count, y); + + let max = 4000001; + for y in 0..max { + if y % 1000 == 0 { + println!("Y is {}/{}", y, max); + } + let mut beacon_radiation = vec![]; + for beacon in &beacons { + let distance = (beacon.pos.1 - y as i32).abs(); + let max_distance = beacon.get_distance(); + if distance <= max_distance { + let start_x = beacon.pos.0 - (max_distance - distance); + let end_x = beacon.pos.0 + (max_distance - distance); + beacon_radiation.push(Range::new(start_x, end_x)); + } + } + + beacon_radiation.sort_by(|r1, r2| r1.start.cmp(&r2.start)); + + let mut start: Option = None; + for range in beacon_radiation { + match start { + None => { + start = Some(range); + } + Some(before) => { + if range.partly_overlap(&before) || (range.start - before.end) == 1 { + if range.end > before.end { + start = Some(Range::new(before.start, range.end)); + } + } + } + } + } + + if let Some(sol) = start { + if sol.end < max { + let x = sol.end + 1; + println!("Possible solution: {}/{} Distress: {}", x, y, (x as i64) * 4000000 + (y as i64)); + break; + } + } + } +} \ No newline at end of file