Browse Source

add day14

niels 2 years ago
parent
commit
8bbbaa0cc2
2 changed files with 130 additions and 0 deletions
  1. 127 0
      src/bin/day14.rs
  2. 3 0
      test_inputs/day14.txt

+ 127 - 0
src/bin/day14.rs

@@ -0,0 +1,127 @@
+use std::collections::HashSet;
+
+use aoc2022_niels_overkamp::common::{self, AOCResult};
+
+use itertools::Itertools;
+use nom::{
+    bytes::complete::tag,
+    character::complete::u64 as u64_parser,
+    combinator::all_consuming,
+    error::Error,
+    multi::separated_list1,
+    sequence::{terminated, tuple},
+    Finish, Parser,
+};
+
+const DAY: &str = "day14";
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+    common::run(DAY, &run)
+}
+
+pub fn run(input: &Vec<String>) -> AOCResult {
+    let point_parser = tuple((terminated(u64_parser, tag(",")), u64_parser));
+    let wall_parser = separated_list1(tag(" -> "), point_parser);
+    let mut wall_parser = all_consuming(wall_parser);
+
+    let mut map: HashSet<(u64, u64)> = HashSet::new();
+
+    for line in input {
+        let result: Result<Vec<(u64, u64)>, Error<&str>> =
+            wall_parser.parse(line.as_str()).finish().map(|(_, l)| l);
+        let wall = result.map_err(|e| e.to_string())?;
+        for line in wall.windows(2) {
+            let (p1, p2) = if let &[p1, p2] = line {
+                (p1, p2)
+            } else {
+                panic!("windows returned not 2 length");
+            };
+            let (hori, iter) = if p1.0 == p2.0 {
+                (false, p1.1.min(p2.1)..=p1.1.max(p2.1))
+            } else if p1.1 == p2.1 {
+                (true, p1.0.min(p2.0)..=p1.0.max(p2.0))
+            } else {
+                return Err(format!("Found non straight line: {:?} -> {:?}", p1, p2).into());
+            };
+            println!("{:?} -> {:?} hori:{}", p1, p2, hori);
+            for v in iter.into_iter() {
+                let p = if hori { (v, p1.1) } else { (p1.0, v) };
+                map.insert(p);
+            }
+        }
+    }
+
+    let death_plane = *map.iter().map(|(_, y)| y).max().unwrap();
+    println!("plane: {}", death_plane);
+
+    let floor = death_plane + 2;
+
+    let (min_x, max_x) = map.iter().map(|(x, _)| x).minmax().into_option().unwrap();
+    let (min_x, max_x) = (*min_x, *max_x);
+
+    for y in 0..=death_plane {
+        let s: String = (min_x..=max_x)
+            .into_iter()
+            .map(|x| if map.contains(&(x, y)) { '#' } else { ' ' })
+            .collect();
+        println!("{}", s);
+    }
+
+    let wall_map = map.clone();
+
+    let (mut x, mut y) = (500, 0);
+    let mut count = 0;
+    let mut count1 = None;
+    let count2;
+    loop {
+        if y > death_plane && count1.is_none() {
+            count1 = Some(count);
+        }
+        match (
+            y + 1 == floor,
+            map.contains(&(x, y + 1)),
+            map.contains(&(x - 1, y + 1)),
+            map.contains(&(x + 1, y + 1)),
+        ) {
+            (false, false, _, _) => (x, y) = (x, y + 1),
+            (false, _, false, _) => (x, y) = (x - 1, y + 1),
+            (false, _, _, false) => (x, y) = (x + 1, y + 1),
+            _ => {
+                map.insert((x, y));
+                count += 1;
+                if (x, y) == (500, 0) {
+                    count2 = count;
+                    break;
+                }
+                (x, y) = (500, 0);
+            }
+        }
+    }
+    println!("");
+
+    let (min_x, max_x) = map.iter().map(|(x, _)| x).minmax().into_option().unwrap();
+    let (min_x, max_x) = (*min_x, *max_x);
+
+    for y in 0..=death_plane {
+        let s: String = (min_x..=max_x)
+            .into_iter()
+            .map(|x| {
+                if wall_map.contains(&(x, y)) {
+                    '#'
+                } else if map.contains(&(x, y)) {
+                    '.'
+                } else {
+                    ' '
+                }
+            })
+            .collect();
+        println!("{}", s);
+    }
+
+    Ok([Some(count1.unwrap().to_string()), Some(count2.to_string())])
+}
+
+#[test]
+pub fn test_day14() {
+    assert!(common::run_test(DAY, &run))
+}

+ 3 - 0
test_inputs/day14.txt

@@ -0,0 +1,3 @@
+498,4 -> 498,6 -> 496,6
+503,4 -> 502,4 -> 502,9 -> 494,9
+24$93