diff options
Diffstat (limited to '2018/src/bin/day_17.rs')
-rw-r--r-- | 2018/src/bin/day_17.rs | 175 |
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) + } +} |