瀏覽代碼

bad day12

Jake Fenton 1 年之前
父節點
當前提交
65be4177cc
共有 2 個文件被更改,包括 153 次插入0 次删除
  1. 148 0
      src/bin/12.rs
  2. 5 0
      src/examples/12.txt

+ 148 - 0
src/bin/12.rs

@@ -0,0 +1,148 @@
+#![feature(let_chains)]
+use std::{collections::{HashSet, HashMap}, thread::current};
+
+#[derive(Clone, Hash, Eq, PartialEq)]
+pub struct Point {
+    pub x: usize,
+    pub y: usize
+}
+
+pub struct HeightMap {
+    map: Vec<Vec<char>>,
+    best_steps: HashMap<Point, usize>,
+    start: Point,
+    end: Point
+}
+
+impl HeightMap {
+    pub fn get_neighbors(& self, point: &Point) -> Vec<Point> {
+        let mut neighbors = Vec::new();
+        if point.x > 0 {
+            neighbors.push(Point { x: point.x - 1, y: point.y});
+        }
+        if point.x + 1< self.map[0].len() {
+            neighbors.push(Point { x: point.x + 1, y: point.y})
+        }
+        if point.y > 0 {
+            neighbors.push(Point { y: point.y - 1, x: point.x})
+        }
+        if point.y + 1 < self.map.len() {
+            neighbors.push(Point { y: point.y + 1, x: point.x})
+        }
+
+        return neighbors
+    }
+
+    pub fn acceptable_next(curr: &char) -> char {
+        if *curr == 'S' {
+            return 'a'
+        }
+        if *curr == 'z' {
+            return 'E'
+        }
+
+        return ((*curr as u8) + 1).try_into().unwrap()
+    }
+
+    pub fn best_possible_dist(&self, curr: &Point) -> usize {
+        self.end.x.abs_diff(curr.x) + self.end.y.abs_diff(curr.y)
+    }
+}
+
+fn search_map(map: &mut HeightMap, mut breadcrumbs: HashSet<Point>, current_pos: Point, best: usize) -> usize {
+    if breadcrumbs.len() + map.best_possible_dist(&current_pos) >= best {
+        return usize::MAX;
+    }
+    breadcrumbs.insert(current_pos.clone());
+    if current_pos == map.end {
+        println!("We've arrived!");
+        return breadcrumbs.len();
+    }
+
+    let mut min = best;
+
+    for neighbor in map.get_neighbors(&current_pos) {
+        if breadcrumbs.contains(&neighbor) {
+            continue;
+        }
+        
+        let neighbor_val = map.map[neighbor.y][neighbor.x];
+        let curr_val = map.map[current_pos.y][current_pos.x];
+            if !(neighbor_val == HeightMap::acceptable_next(&curr_val) || (neighbor_val <= curr_val) && (neighbor_val != 'E' && neighbor_val != 'S')) {
+            continue;
+        }
+
+        if map.best_steps.contains_key(&neighbor) && map.best_steps[&neighbor] <= breadcrumbs.len() + map.best_possible_dist(&current_pos) {
+            continue;
+        }
+        
+        let new = search_map(map, breadcrumbs.clone(), neighbor, min);
+        if new < min {
+            min = new;
+        }
+    }
+
+    if !map.best_steps.contains_key(&current_pos) {
+        map.best_steps.insert(current_pos, min);
+    } else {
+        if min < map.best_steps[&current_pos] {
+            map.best_steps.insert(current_pos, min);
+        }
+    }
+
+    min
+}
+
+pub fn part_one(input: &str) -> Option<usize> {
+    let _map: Vec<Vec<char>> = input.lines().map(|line| line.chars().collect()).collect();
+    let mut end_coord = Point { x: 0, y: 0 };
+    let mut start_coord = Point { x: 0, y: 0 };
+
+
+    for (r_idx, row) in _map.iter().enumerate() {
+        for (col_idx, c) in row.iter().enumerate() {
+            if *c == 'E' {
+                end_coord = Point {y: r_idx, x: col_idx};
+            } else if *c == 'S' {
+                start_coord = Point {y: r_idx, x: col_idx};
+            }
+        }
+    }
+
+    let mut map = HeightMap {
+        best_steps: HashMap::new(),
+        map: _map,
+        start: start_coord.clone(),
+        end: end_coord.clone()
+    };
+
+    let best = map.map.len() * map.map[0].len();
+    Some(search_map(&mut map, HashSet::from_iter([start_coord.clone()].into_iter()), start_coord, best) - 1)
+}
+
+pub fn part_two(input: &str) -> Option<u32> {
+    None
+}
+
+fn main() {
+    let input = &advent_of_code::read_file("inputs", 12);
+    advent_of_code::solve!(1, part_one, input);
+    advent_of_code::solve!(2, part_two, input);
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_part_one() {
+        let input = advent_of_code::read_file("examples", 12);
+        assert_eq!(part_one(&input), Some(31));
+    }
+
+    #[test]
+    fn test_part_two() {
+        let input = advent_of_code::read_file("examples", 12);
+        assert_eq!(part_two(&input), None);
+    }
+}

+ 5 - 0
src/examples/12.txt

@@ -0,0 +1,5 @@
+Sabqponm
+abcryxxl
+accszExk
+acctuvwj
+abdefghi