diff --git a/2018/loc.svg b/2018/loc.svg
index 9666dd1..263055b 100644
--- a/2018/loc.svg
+++ b/2018/loc.svg
@@ -32,10 +32,10 @@ z
+" id="m7d08bf4d8b" style="stroke:#000000;stroke-width:0.8;"/>
-
+
@@ -71,7 +71,7 @@ z
-
+
@@ -110,7 +110,7 @@ z
-
+
@@ -139,7 +139,7 @@ z
-
+
@@ -153,7 +153,7 @@ z
-
+
@@ -193,7 +193,7 @@ z
-
+
@@ -286,10 +286,10 @@ z
+" id="mbcaa2d2acc" style="stroke:#000000;stroke-width:0.8;"/>
-
+
@@ -302,7 +302,7 @@ L -3.5 0
-
+
@@ -316,7 +316,7 @@ L -3.5 0
-
+
@@ -331,7 +331,7 @@ L -3.5 0
-
+
@@ -346,7 +346,7 @@ L -3.5 0
-
+
@@ -361,7 +361,7 @@ L -3.5 0
-
+
@@ -577,7 +577,7 @@ z
-
-
-
+
diff --git a/2018/src/day17.rs b/2018/src/day17.rs
index dd484b7..666d642 100644
--- a/2018/src/day17.rs
+++ b/2018/src/day17.rs
@@ -1,12 +1,13 @@
+use std::collections::HashSet;
+use std::io::BufRead;
+use std::io::BufReader;
use std::io::Read;
-use common::Solution;
-use std::collections::HashSet;
-use regex::Regex;
-use std::io::BufReader;
-use std::io::BufRead;
use itertools::Itertools;
use itertools::MinMaxResult;
+use regex::Regex;
+
+use common::Solution;
type Coordinate = (usize, usize);
@@ -41,7 +42,7 @@ impl Day17 {
for y in a..=b {
self.clays.insert((fixed, y));
}
- },
+ }
"y" => {
for x in a..=b {
self.clays.insert((x, fixed));
@@ -55,11 +56,35 @@ impl Day17 {
MinMaxResult::MinMax(a, b) => {
self.ymin = *a;
self.ymax = *b;
- },
+ }
_ => panic!(),
};
}
+ fn support_end(&mut self, center: usize, range: T, y: usize) -> (usize, bool)
+ where T: Iterator-
+ {
+ let mut prev = center;
+ for x in range {
+ let pos = (x, y);
+ if self.clays.contains(&pos) {
+ return (prev, true);
+ }
+
+ prev = x;
+ let below = (x, y + 1);
+ self.descend(below);
+ if !self.is_supported(&below) {
+ return (x, false);
+ }
+ }
+ unreachable!();
+ }
+
+ fn is_supported(&self, pos: &Coordinate) -> bool {
+ self.clays.contains(pos) || self.contained.contains(pos)
+ }
+
fn descend(&mut self, pos: Coordinate) {
let (x, y) = pos;
@@ -71,49 +96,16 @@ impl Day17 {
self.descend(below);
- if self.clays.contains(&below) || self.contained.contains(&below) {
- let mut contained = true;
+ if self.is_supported(&below) {
+ let (right, right_contained) = self.support_end(x, (x + 1).., y);
+ let (left, left_contained) = self.support_end(x, (0..x).rev(), y);
- let mut layer = vec![pos];
+ let range = (left..=right).map(|x| (x, y));
- let mut nx = x + 1;
- loop {
- let npos = (nx, y);
- if self.clays.contains(&npos) {
- break;
- }
- layer.push(npos);
-
- let nbelow = (nx, y + 1);
- self.descend(nbelow);
- if !self.clays.contains(&nbelow) && !self.contained.contains(&nbelow) {
- contained = false;
- break;
- }
-
- nx += 1;
- }
- let mut nx = x - 1;
- loop {
- let npos = (nx, y);
- if self.clays.contains(&npos) {
- break;
- }
- layer.push(npos);
-
- let nbelow = (nx, y + 1);
- self.descend(nbelow);
- if !self.clays.contains(&nbelow) && !self.contained.contains(&nbelow) {
- contained = false;
- break;
- }
- nx -= 1;
- }
-
- if contained {
- self.contained.extend(layer);
+ if left_contained && right_contained {
+ self.contained.extend(range);
} else {
- self.flowing.extend(layer);
+ self.flowing.extend(range);
}
} else {
self.flowing.insert(pos);
@@ -127,9 +119,8 @@ impl Solution for Day17 {
self.descend((500, 0));
- let result = self.contained.iter()
- .chain(self.flowing.iter())
- .filter(|&&(_, y)| y >= self.ymin && y <= self.ymax).count();
+ let result = self.contained.len()
+ + self.flowing.len() - self.ymin;
format!("{}", result)
}
@@ -138,16 +129,14 @@ impl Solution for Day17 {
self.descend((500, 0));
- let result = self.contained.iter()
- .filter(|&&(_, y)| y >= self.ymin && y <= self.ymax).count();
- format!("{}", result)
+ format!("{}", self.contained.len())
}
}
#[cfg(test)]
mod tests {
- use day17::Day17;
use common::Solution;
+ use day17::Day17;
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/17.txt");
@@ -162,5 +151,4 @@ mod tests {
let mut instance = Day17::new();
assert_eq!("29", instance.part2(&mut SAMPLE_INPUT));
}
-
}