summaryrefslogtreecommitdiff
path: root/2018/src/bin/day_17.rs
diff options
context:
space:
mode:
Diffstat (limited to '2018/src/bin/day_17.rs')
-rw-r--r--2018/src/bin/day_17.rs175
1 files changed, 175 insertions, 0 deletions
diff --git a/2018/src/bin/day_17.rs b/2018/src/bin/day_17.rs
new file mode 100644
index 0000000..f479c3a
--- /dev/null
+++ b/2018/src/bin/day_17.rs
@@ -0,0 +1,175 @@
+extern crate advent_of_code_2018;
+use advent_of_code_2018::*;
+
+use std::error::Error;
+use std::path::PathBuf;
+
+// cargo watch -cs "cargo run --release --bin day_17"
+
+struct CoordBuilder {
+ xmin: Option<usize>,
+ xmax: Option<usize>,
+ ymin: Option<usize>,
+ ymax: Option<usize>
+}
+
+#[derive(Debug)]
+struct Coord {
+ xmin: usize,
+ xmax: usize,
+ ymin: usize,
+ ymax: usize
+}
+
+impl CoordBuilder {
+ fn new() -> CoordBuilder {
+ CoordBuilder {
+ xmin: None,
+ xmax: None,
+ ymin: None,
+ ymax: None
+ }
+ }
+
+ fn build(&self) -> Coord {
+ Coord {
+ xmin: self.xmin.unwrap(),
+ xmax: self.xmax.unwrap(),
+ ymin: self.ymin.unwrap(),
+ ymax: self.ymax.unwrap(),
+ }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Tile {
+ Clay,
+ RunningWater,
+ HalfSettledWater,
+ SettledWater,
+ Sand
+}
+
+fn main() -> Result<(), Box<Error>> {
+ let input = read_file(&PathBuf::from("inputs/17.txt"))?;
+
+ let clay_coords = input.iter().map(|line| {
+ let mut builder = CoordBuilder::new();
+ for split in line.split(", ") {
+ if split.starts_with("x=") {
+ let mut range_split = split
+ .trim_matches(|c: char| !c.is_numeric())
+ .split("..")
+ .map(|s| s.parse().unwrap());
+ if let Some(min) = range_split.next() {
+ builder.xmin = Some(min);
+ builder.xmax = Some(min+1);
+ }
+ if let Some(max) = range_split.next() {
+ builder.xmax = Some(max+1);
+ }
+ } else {
+ let mut range_split = split
+ .trim_matches(|c: char| !c.is_numeric())
+ .split("..")
+ .map(|s| s.parse().unwrap());
+ if let Some(min) = range_split.next() {
+ builder.ymin = Some(min);
+ builder.ymax = Some(min+1);
+ }
+ if let Some(max) = range_split.next() {
+ builder.ymax = Some(max+1);
+ }
+ }
+ }
+ builder.build()
+ }).collect::<Vec<_>>();
+
+ let range = CoordinateSystem {
+ xmin: clay_coords.iter().min_by_key(|coord| coord.xmin).unwrap().xmin-2,
+ xmax: clay_coords.iter().max_by_key(|coord| coord.xmax).unwrap().xmax+2,
+ ymin: clay_coords.iter().min_by_key(|coord| coord.ymin).unwrap().ymin,
+ ymax: clay_coords.iter().max_by_key(|coord| coord.ymax).unwrap().ymax
+ };
+
+ debug!(range);
+
+
+ let mut map = vec!(Tile::Sand; range.vector_size());
+ for coord in clay_coords {
+ for y in coord.ymin..coord.ymax {
+ for x in coord.xmin..coord.xmax {
+ map[range.to_vec(x, y)] = Tile::Clay;
+ }
+ }
+ }
+
+ debug!(map[range.to_vec(500, range.ymin)]);
+ map[range.to_vec(500, range.ymin)] = Tile::RunningWater;
+
+ let mut last_iter = Vec::new();
+ while last_iter != map {
+ last_iter = map.clone();
+ for y in range.ymin..range.ymax-1 {
+ for x in range.xmin..range.xmax {
+ match map[range.to_vec(x, y)] {
+ Tile::RunningWater => {
+ if map[range.to_vec(x, y+1)] == Tile::Sand {
+ map[range.to_vec(x, y+1)] = Tile::RunningWater;
+ }
+ if map[range.to_vec(x-1, y)] == Tile::Sand && (map[range.to_vec(x, y+1)] == Tile::Clay || map[range.to_vec(x, y+1)] == Tile::SettledWater) {
+ map[range.to_vec(x-1, y)] = Tile::RunningWater;
+ }
+ if map[range.to_vec(x+1, y)] == Tile::Sand && (map[range.to_vec(x, y+1)] == Tile::Clay || map[range.to_vec(x, y+1)] == Tile::SettledWater) {
+ map[range.to_vec(x+1, y)] = Tile::RunningWater;
+ }
+ if (map[range.to_vec(x-1, y)] == Tile::Clay || map[range.to_vec(x-1, y)] == Tile::HalfSettledWater) && (map[range.to_vec(x, y+1)] == Tile::Clay || map[range.to_vec(x, y+1)] == Tile::SettledWater) {
+ map[range.to_vec(x, y)] = Tile::HalfSettledWater;
+ }
+ },
+ Tile::HalfSettledWater => {
+ if map[range.to_vec(x+1, y)] == Tile::Clay {
+ for xleft in 0.. {
+ if map[range.to_vec(x-xleft, y)] == Tile::HalfSettledWater {
+ map[range.to_vec(x-xleft, y)] = Tile::SettledWater;
+ } else {
+ break;
+ }
+ }
+ }
+ },
+ _ => {}
+ }
+ }
+ }
+ }
+
+ let water_tiles = map.iter()
+ .filter(|&&t| t == Tile::RunningWater || t == Tile::SettledWater || t == Tile::HalfSettledWater)
+ .count();
+ debug!(water_tiles);
+
+ let settled_water_tiles = map.iter()
+ .filter(|&&t| t == Tile::SettledWater)
+ .count();
+ debug!(settled_water_tiles);
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct CoordinateSystem {
+ xmin: usize,
+ xmax: usize,
+ ymin: usize,
+ ymax: usize
+}
+
+impl CoordinateSystem {
+ fn vector_size(&self) -> usize {
+ (self.xmax - self.xmin) * (self.ymax - self.ymin)
+ }
+ fn to_vec(&self, x: usize, y: usize) -> usize {
+ ((y - self.ymin) * (self.xmax - self.xmin)) + (x - self.xmin)
+ }
+}