From 22c71dc3f5c51a8a2b8dcaedab4d95ebdfb07b7f Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Tue, 25 Dec 2018 11:28:58 +0100 Subject: [PATCH] Implement day 25. Part 2 was bonkers. --- 2018/benches/days.rs | 3 +- 2018/src/common.rs | 15 ++++++ 2018/src/day23.rs | 3 -- 2018/src/day25.rs | 98 +++++++++++++++++++++++++++++++++++++-- 2018/src/samples/25.1.txt | 8 ++++ 2018/src/samples/25.2.txt | 10 ++++ 2018/src/samples/25.3.txt | 10 ++++ 2018/src/samples/25.4.txt | 10 ++++ 8 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 2018/src/samples/25.1.txt create mode 100644 2018/src/samples/25.2.txt create mode 100644 2018/src/samples/25.3.txt create mode 100644 2018/src/samples/25.4.txt diff --git a/2018/benches/days.rs b/2018/benches/days.rs index e8e4018..4fcfb09 100644 --- a/2018/benches/days.rs +++ b/2018/benches/days.rs @@ -74,9 +74,10 @@ day_bench!(day19, 19); day_bench!(day20, 20); day_bench!(day21, 21); day_bench!(day22, 22); +day_bench!(day25, 25); benchmark_main!(day01, day02, day03, day04, day05, day06, day07, day08, day09, day10, day11, day12, day13, day14, day15, day16, day17, day18, day19, day20, - day21, day22); + day21, day22, day25); diff --git a/2018/src/common.rs b/2018/src/common.rs index e65e0f7..31cdb96 100644 --- a/2018/src/common.rs +++ b/2018/src/common.rs @@ -43,6 +43,21 @@ impl Point for (T, T, T) } } +impl Point for [T; 4] +where T: Default + Add + Sub + Copy + Ord +{ + type CoordType = T; + + fn manhattan(self, other: Self) -> T { + let mut dist = T::default(); + + for (&a, b) in self.iter().zip(other.iter()) { + dist = dist + a.max(*b) - a.min(*b); + } + dist + } +} + /// Apply Erathostenes's sieve to the supplied array /// diff --git a/2018/src/day23.rs b/2018/src/day23.rs index 868dfba..7b82660 100644 --- a/2018/src/day23.rs +++ b/2018/src/day23.rs @@ -5,9 +5,6 @@ use regex::Regex; use std::io::BufReader; use std::io::BufRead; use common::Point; -use std::collections::VecDeque; -use std::collections::HashSet; -use std::collections::HashMap; type Coordinate = (i64, i64, i64); diff --git a/2018/src/day25.rs b/2018/src/day25.rs index ca9402e..271ccbf 100644 --- a/2018/src/day25.rs +++ b/2018/src/day25.rs @@ -1,25 +1,113 @@ use std::io::Read; +use regex::Regex; + use common::Solution; +use std::io::BufReader; +use std::io::BufRead; +use common::Point; #[derive(Default)] -pub struct Day25 {} +pub struct Day25 { + edges: Vec>, +} impl Day25 { pub fn new() -> Self { Default::default() } + + fn read_input(&mut self, input: &mut Read) { + let matcher = Regex::new(r"-?\d+").unwrap(); + let reader = BufReader::new(input); + + let mut points = Vec::new(); + + for line in reader.lines() { + let line = line.unwrap(); + + let mut coords = [0; 4]; + for (dest, coord) in coords.iter_mut().zip(matcher.find_iter(&line)) { + *dest = coord.as_str().parse().unwrap(); + } + + points.push(coords); + } + + let points = points; + self.edges.resize(points.len(), Vec::new()); + + for (x, a) in points.iter().enumerate() { + for (y, b) in points.iter().enumerate() { + if y >= x { + break; + } + + if a.manhattan(*b) <= 3 { + self.edges[x].push(y); + self.edges[y].push(x); + } + } + } + } + + fn connected_components(&self) -> usize { + let mut components = 0; + + let mut visited = vec![false; self.edges.len()]; + let mut todo = Vec::new(); + + for i in 0..visited.len() { + if !visited[i] { + components += 1; + todo.push(i); + visited[i] = true; + + while let Some(i) = todo.pop() { + for &neighbour in &self.edges[i] { + if !visited[neighbour] { + visited[neighbour] = true; + todo.push(neighbour); + } + } + } + } + } + + components + } } impl Solution for Day25 { - fn part1(&mut self, _input: &mut Read) -> String { - unimplemented!() + fn part1(&mut self, input: &mut Read) -> String { + self.read_input(input); + self.connected_components().to_string() } fn part2(&mut self, _input: &mut Read) -> String { - unimplemented!() + // As always, no part 2 for day 25. + String::new() } } #[cfg(test)] -mod tests {} +mod tests { + use common::Solution; + use day25::Day25; + + #[test] + fn sample_part1() { + let inputs: [&[u8]; 4] = [ + include_bytes!("samples/25.1.txt"), + include_bytes!("samples/25.2.txt"), + include_bytes!("samples/25.3.txt"), + include_bytes!("samples/25.4.txt"), + ]; + let outputs = ["2", "4", "3", "8"]; + + for (&input, &output) in inputs.iter().zip(outputs.iter()) { + let mut instance = Day25::new(); + assert_eq!(output, instance.part1(&mut input.as_ref())); + } + } +} diff --git a/2018/src/samples/25.1.txt b/2018/src/samples/25.1.txt new file mode 100644 index 0000000..ebb54aa --- /dev/null +++ b/2018/src/samples/25.1.txt @@ -0,0 +1,8 @@ + 0,0,0,0 + 3,0,0,0 + 0,3,0,0 + 0,0,3,0 + 0,0,0,3 + 0,0,0,6 + 9,0,0,0 +12,0,0,0 diff --git a/2018/src/samples/25.2.txt b/2018/src/samples/25.2.txt new file mode 100644 index 0000000..3a97e16 --- /dev/null +++ b/2018/src/samples/25.2.txt @@ -0,0 +1,10 @@ +-1,2,2,0 +0,0,2,-2 +0,0,0,-2 +-1,2,0,0 +-2,-2,-2,2 +3,0,2,-1 +-1,3,2,2 +-1,0,-1,0 +0,2,1,-2 +3,0,0,0 diff --git a/2018/src/samples/25.3.txt b/2018/src/samples/25.3.txt new file mode 100644 index 0000000..bf5c2b9 --- /dev/null +++ b/2018/src/samples/25.3.txt @@ -0,0 +1,10 @@ +1,-1,0,1 +2,0,-1,0 +3,2,-1,0 +0,0,3,1 +0,0,-1,-1 +2,3,-2,0 +-2,2,0,0 +2,-2,0,-1 +1,-1,0,-1 +3,2,0,2 diff --git a/2018/src/samples/25.4.txt b/2018/src/samples/25.4.txt new file mode 100644 index 0000000..1147af7 --- /dev/null +++ b/2018/src/samples/25.4.txt @@ -0,0 +1,10 @@ +1,-1,-1,-2 +-2,-2,0,1 +0,2,1,3 +-2,3,-2,1 +0,2,3,-2 +-1,-1,1,-2 +0,-2,-1,0 +-2,2,3,-1 +1,2,2,0 +-1,-2,0,-2