mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 17.
Today was a nice exercise, and I got to be somewhat fast too. Number 328/314.
This commit is contained in:
1884
2018/inputs/17.txt
Normal file
1884
2018/inputs/17.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1,197 @@
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use common::Solution;
|
use common::Solution;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use regex::Regex;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::io::BufRead;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use itertools::MinMaxResult;
|
||||||
|
|
||||||
|
type Coordinate = (usize, usize);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Day17 {}
|
pub struct Day17 {
|
||||||
|
clays: HashSet<Coordinate>,
|
||||||
|
flowing: HashSet<Coordinate>,
|
||||||
|
contained: HashSet<Coordinate>,
|
||||||
|
ymin: usize,
|
||||||
|
ymax: usize,
|
||||||
|
}
|
||||||
|
|
||||||
impl Day17 {
|
impl Day17 {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_input(&mut self, input: &mut Read) {
|
||||||
|
let matcher = Regex::new(r"(.)=(\d+), (.)=(\d+)\.\.(\d+)").unwrap();
|
||||||
|
let reader = BufReader::new(input);
|
||||||
|
|
||||||
|
for line in reader.lines() {
|
||||||
|
let line = line.unwrap();
|
||||||
|
let captures = matcher.captures(&line).unwrap();
|
||||||
|
|
||||||
|
let fixed: usize = captures[2].parse().unwrap();
|
||||||
|
let a: usize = captures[4].parse().unwrap();
|
||||||
|
let b: usize = captures[5].parse().unwrap();
|
||||||
|
|
||||||
|
match &captures[1] {
|
||||||
|
"x" => {
|
||||||
|
for y in a..=b {
|
||||||
|
self.clays.insert((fixed, y));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"y" => {
|
||||||
|
for x in a..=b {
|
||||||
|
self.clays.insert((x, fixed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.clays.iter().map(|(_, y)| y).minmax() {
|
||||||
|
MinMaxResult::MinMax(a, b) => {
|
||||||
|
self.ymin = *a;
|
||||||
|
self.ymax = *b;
|
||||||
|
},
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn map(&self) {
|
||||||
|
let (xmin, xmax) = match self.clays.iter().map(|(x, _)| *x).minmax() {
|
||||||
|
MinMaxResult::MinMax(a, b) => (a, b),
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("{}, {} to {}, {}", xmin, self.ymin, xmax, self.ymax);
|
||||||
|
|
||||||
|
for y in self.ymin..=self.ymax {
|
||||||
|
let mut buf = String::with_capacity(xmax - xmin + 1);
|
||||||
|
for x in xmin..=xmax {
|
||||||
|
let pos = (x, y);
|
||||||
|
if self.clays.contains(&pos) {
|
||||||
|
buf.push('#');
|
||||||
|
} else if self.contained.contains(&pos) {
|
||||||
|
buf.push('~');
|
||||||
|
} else if self.flowing.contains(&pos) {
|
||||||
|
buf.push('|');
|
||||||
|
} else {
|
||||||
|
buf.push(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn descend(&mut self, pos: Coordinate) {
|
||||||
|
let (x, y) = pos;
|
||||||
|
|
||||||
|
if y > self.ymax || self.clays.contains(&pos) || self.flowing.contains(&pos) || self.contained.contains(&pos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let below = (x, y + 1);
|
||||||
|
|
||||||
|
self.descend(below);
|
||||||
|
|
||||||
|
if self.clays.contains(&below) || self.contained.contains(&below) {
|
||||||
|
let mut contained = true;
|
||||||
|
|
||||||
|
let mut layer = vec![pos];
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
self.flowing.extend(layer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.flowing.insert(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Solution for Day17 {
|
impl Solution for Day17 {
|
||||||
fn part1(&mut self, _input: &mut Read) -> String {
|
fn part1(&mut self, input: &mut Read) -> String {
|
||||||
unimplemented!()
|
self.read_input(input);
|
||||||
|
|
||||||
|
|
||||||
|
self.descend((500, 0));
|
||||||
|
|
||||||
|
let range_filter = |&&(_, y): &&(usize, usize)| y >= self.ymin && y <= self.ymax;
|
||||||
|
|
||||||
|
let result = self.contained.iter().filter(range_filter).count()
|
||||||
|
+ self.flowing.iter().filter(range_filter).count();
|
||||||
|
format!("{}", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(&mut self, _input: &mut Read) -> String {
|
fn part2(&mut self, input: &mut Read) -> String {
|
||||||
unimplemented!()
|
self.read_input(input);
|
||||||
|
|
||||||
|
|
||||||
|
self.descend((500, 0));
|
||||||
|
|
||||||
|
let range_filter = |&&(_, y): &&(usize, usize)| y >= self.ymin && y <= self.ymax;
|
||||||
|
|
||||||
|
let result = self.contained.iter().filter(range_filter).count();
|
||||||
|
format!("{}", result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use day17::Day17;
|
||||||
|
use common::Solution;
|
||||||
|
|
||||||
|
const SAMPLE_INPUT: &[u8] = include_bytes!("samples/17.txt");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part1() {
|
||||||
|
let mut instance = Day17::new();
|
||||||
|
assert_eq!("57", instance.part1(&mut SAMPLE_INPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
let mut instance = Day17::new();
|
||||||
|
assert_eq!("29", instance.part2(&mut SAMPLE_INPUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
8
2018/src/samples/17.txt
Normal file
8
2018/src/samples/17.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
x=495, y=2..7
|
||||||
|
y=7, x=495..501
|
||||||
|
x=501, y=3..7
|
||||||
|
x=498, y=2..4
|
||||||
|
x=506, y=1..2
|
||||||
|
x=498, y=10..13
|
||||||
|
x=504, y=10..13
|
||||||
|
y=13, x=498..504
|
||||||
Reference in New Issue
Block a user