From 83e9f642e63ac22c6fdd49683a73b39398d12ec7 Mon Sep 17 00:00:00 2001 From: logaritmisk Date: Sun, 25 Dec 2016 22:06:23 +0100 Subject: [PATCH] 2016/24 --- 2016/24/Cargo.lock | 4 + 2016/24/Cargo.toml | 6 ++ 2016/24/example.txt | 5 + 2016/24/input.txt | 43 ++++++++ 2016/24/src/main.rs | 249 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 307 insertions(+) create mode 100644 2016/24/Cargo.lock create mode 100644 2016/24/Cargo.toml create mode 100644 2016/24/example.txt create mode 100644 2016/24/input.txt create mode 100644 2016/24/src/main.rs diff --git a/2016/24/Cargo.lock b/2016/24/Cargo.lock new file mode 100644 index 0000000..7ccbb49 --- /dev/null +++ b/2016/24/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "24" +version = "0.1.0" + diff --git a/2016/24/Cargo.toml b/2016/24/Cargo.toml new file mode 100644 index 0000000..18f190d --- /dev/null +++ b/2016/24/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "24" +version = "0.1.0" +authors = ["logaritmisk "] + +[dependencies] diff --git a/2016/24/example.txt b/2016/24/example.txt new file mode 100644 index 0000000..628e51b --- /dev/null +++ b/2016/24/example.txt @@ -0,0 +1,5 @@ +########### +#0.1.....2# +#.#######.# +#4.......3# +########### diff --git a/2016/24/input.txt b/2016/24/input.txt new file mode 100644 index 0000000..912ab98 --- /dev/null +++ b/2016/24/input.txt @@ -0,0 +1,43 @@ +################################################################################################################################################################################### +#.........#...#.............#...#3#.#.....#...........#.........#.#...#.......#.#.#...#...#.................#...........#.#...#.#.......#.......#.......#...#...#.....#.....#.....# +#.#.#.#.#.#.#########.#.#.###.#.#.#.###.###.#.###.#.#.#.###.#.###.#.#.#.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#####.#.#.#.###.#.#.#.#.#.###.#.###.###.###.###.#.# +#...#...#...#.......#...#.#.#.....#...#.....#.........#.......#.#...#...#.#.............#...#.......#.#.#...#.#.....#.......#...#.....#...#...........#...#...#.#...............#2# +#.###.#.#.#####.###.###.#.#.#.#.###.#.#.#####.#######.#.###.###.#.#.#.#.#.#####.###.###.#.#.#####.#.###.#.###.#.#.#.#.#.#######.#######.#.#.###.###.###.#.#.#.#.#.#.###.#.###.#.### +#.......#.........#.#.#...#...#...#.....#.#.............#.....#...#.......#.#.....#...#...#.......#.............................#.#...#...#...#.....#...#.......#.......#.......#.# +#.###.#.#.#########.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.#.#######.#.#.#.#.#.#.#####.#.###.#.#####.#.###.###.#.#.###.###.#.#.#.#####.#.###.#.#.#.#######.###.#.#.#.###.###.# +#...#.#...#...#...#...#.#...#.....#...#...........#.....#.........#.#...#...#...#.#...#.......#...#.#.....#.#.....#...#.#.......#.#.#.......#.......#...........#.#.#...#.#.......# +#.#.#.###.###.#.#.#######.#.#.#.#.#.#.###.###########.#.#.#####.###.#.#.#####.#.#.#.#####.###.#.###.#####.###.#####.#########.#.###.#.###.#.#.#.#.###.###.#.#####.#.#.#.#.#.###.#.# +#.......#.......#...........#...#.#...#.............#.#.#...#...#.....#...#...#.#...#...#.......#.#.#.#...#.....#.#.#.........#...#...#.....#.#...........#.#.......#.#.#...#...#.# +#.#.#.###.#####.#.#####.#.###.#.#.#.###.#.#.#.###.###.#.#####.###.#####.#.#.#####.#.#.#.#######.#.###.#.###.#####.#.#####.#.#.#####.#.#.#.#.###.#.#######.#.#.#.###########.#.#.#.# +#.#.#.....#.#1..........#.#...#...#.....#.........#...............#.#...#.....#...#.......#...........#.#...#.#.....#.............#.............#.....#...#.....#...#.....#.#.....# +#.#.###.#.#.#####.#.#.#.###.#####.#.#.#.###.###.#.#.#.#####.#.#.###.#.#.#####.#.#.#.#.#.#.###.#.###.#.#.#.#.#.#.###.#.#.#####.###.###.###.#.#.#.###.#.#.#.#.#.###.#.#.#####.#####.# +#...#...#.#...#.#.#.#.#.......#.....................#.#...............#.......#.#...#.#.#.....#.#.#...#...#.#.......#.....#.#...#.........#.#.#...#.........#.............#.....#.# +#.###.###.###.#.#.###.#.#####.#.#####.###.###########.###.#.#.#####.#.#.#.###.###.#.#.#.#.###.#.#.#.#.###.#.###.#.#########.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###.###.#####.#.#####.### +#.....#.#.......#.#.#.....#...#.......#...#.#...#.............#.#.#.....#.........#...#.#.........#.#.#.#...#.#...#...#.......#.....#.#.....#.#.#.......#.#...#.#.....#.......#...# +#.#.###.#.#######.#.#.#.###.#.###.###.#####.#.#.#.#.###.###.###.#.#.#####.#.#####.#.#.#.#.#.#########.#.#.#.#.#.#.#.#.#.###.#.###.#.#.###.###.#.#######.#.#.#.#.#.###.#.#.#.#.###.# +#.#.#.......#...#...#.#.#.#.....#.....#...#...#.....#...#...#...#...........#...........#.........#.#.....#.....#.......#...#...#...#.#...#.#.#.........#...#.....#.#...#.#.....#.# +#.#.#.#####.#.#.#.###.###.#.#.#####.#.###.#.#.#####.#.#####.#.#.#.#####.###.#.#.#.#.###.#.#.#.#.#.#.#.###.#.#####.###.###.#.#.#.#.#.#.#.#.#.###.###.#.#######.#####.###.#.###.###.# +#.#.......#.#...#.#...#.#.#.......#...#.....#.........#.....#.#.....#...#...#.#.#...#.....#...#...#...#.....#.......#.#.#...#.#.........#...#.#..4#.#.#.#.#.....#.....#.........#.# +#.###.#.#.#.###.#.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.#.###.#####.#.###.#######.#####.###.#.#.#.#.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#######.#.#.#.#.#.#.#.#.#.#.###.#.#.# +#0#...#.#.#.....#...#...#.#...#...#...#...#.......#.#.#.....#...#...#...#...#...#...#.........#.......#...#.......#...#...#...#.......#...#...............#.....#...#...#...#.#...# +###.#.#.###.###########.#.#####.###.###.###.###.###.#.###.#.#.#.#.#.#.#.#.#.#.###.#.###.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#####.#.#.#.#####.#.#.#####.#####.#.#.#.#.### +#...#.#...#.......#...#...........#...#.....#...#...#.#.........#.....#.#...#.......#.....#.#.#.........#.........#...#.#.#...#.#.....#.....................#...............#.....# +###.#.#.#.#.#.###.#.#.#.#.#######.#.#.###.###.#.#.#####.###.###.###.###.#.#.#.#.#######.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#####.###.#######.###.###.#.###.###.###.###.#.#.# +#...#.............#.#...........#.#.#.....#.....#.......#.#.....#...#.........#.....#.......#.....#...#.....#...#.......#...#...#.#.........#...#...........#.......#...#.......#.# +###.#.#########.#.#.#####.#.#.#.#.#.#.###.#.#######.#.#.#.#.#.#####.#.#.#.#####.#.#.#.#####.#######.#.#.#.#.#.#####.#.#.#.#####.#.#.###.#######.#######.#.#.###.#.#.#.#.#.#.###.#.# +#.#...............#.#.......#.....#.................#...#.#.#.......#...#.......#.#.#...#.#.......#...#.....#.....#...#.#.......#.#.#.....#.....#.....#.#...#.#...#...#.#...#.#.#.# +#.#.#.###.#.#.#.#.#.#.#.#.#.#########.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.###.###.#.#.#####.#####.#####.#.#.#.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.#.##### +#...#.#.....#...#.............#.#.#.#.........#.#...#.#.....#.......#...#.#.#.....#.......#...#...#...........#.....#.#.......#...#...#.#.........#...#...#.....#.......#...#.....# +###.#.#.#.#.#.#.###.#.###.#.###.#.#.#.#.###.#.###.#.#.#####.###.###.#.#.#.###.#.#.###.###.###.#.#.#.#.###.#####.###.#####.#.#.###.###.#####.#####.#.#.#######.###.###.###.#.#.#.#.# +#...#.#.....#.........#.......#.#...#.......#...#...#...........#.....#.......#...........#.......#...#...#.....#.....#...#.......#.#.#...#.#.....#.........#.....#...#.#...#.#...# +###.###.###.###.#.#####.###.#.#.#.#.#.###.###.###.###.#.#####.#.#.#.#.###.#.#.###.#.###.###.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#.#.#####.#.#####.#.#.#.#####.#.#.# +#.#.#...#.#.#...................#.......#.#.#.#.#.....#.#.#.....#...#.......#.#...#.......#.....#...#.....#...#...#.#...#...#.........#...#...#...........#.........#.#..5#...#...# +#.#.#.###.#.###.#####.#.#.###.#.#####.#.#.#.#.#.#.###.#.#.#.#######.###.#.#.#.#.#.###.#.#.#.###.#.#####.#.#.#.#####.#.###.#.#.###.###.#.###.#.#.###########.#.#######.#.#.#.###.### +#...#.#.#...#.#.................#.#.....#.#.........#.....#.#.#...#.#.........#...#.#...#.#.........#...#...#.....#.#.#.#.....#...#.#.....#.#.............#.#...#.#.#.....#...#...# +#.#.###.#.#.#.#.#.#.#.#.###.###.#.#.#######.#######.###.#.#.#.###.#.#.#####.###.###.#####.#.#####.#.#.#.#.#.#.###.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#.#.#.###.#.#.#.#.#####.###.#.# +#...#.....#.....#.....#.#...#...#...............#...#...#...#.....#...#.#.....#.#.#...#...#.#...#...#.....#...#...#...................#.........#...#.........#.#...#.......#...#.# +###.#.###.#.#.#.###.#.#.#.#.#.###.###.#.###.###.#.###.#.#######.#.#.#.#.#.#####.#.#.#.#.#.###.#.#.#.#####.#.#.###.#.#######.#######.###.#######.#.#.#.#.###.###.###.#.#.#.#.#.#.#.# +#.....#7..#.#.#...........#.#...#.........#.....#.#.#...#.....#.............#...#...#...#.#.#...#.......#...#.....#.#.......#.#.....#...#...#...#...#...#...#.#.....#.#.......#.#.# +#.#.#.#.#.#.#.#.#.#.###.#####.#.#############.#.###.#.#.#.#.###.###.#######.#.#.###.#.###.#.###.#######.###.###.#.#.###.#.#.#.#.#.###.###.###.#.#.###.#.#.#.#.#.#.###.#.###.#.#.### +#...#.....#.#...#.#.....#.....#...#...#.......#6#.......#.#.......#.#.........#...#.#.....#.....#.#.......#.#.......#.......#.....#.....#.....#...#.#.#.#...#.#...#.#...#...#.#.#.# +################################################################################################################################################################################### diff --git a/2016/24/src/main.rs b/2016/24/src/main.rs new file mode 100644 index 0000000..e96b625 --- /dev/null +++ b/2016/24/src/main.rs @@ -0,0 +1,249 @@ +use std::io::{self, BufRead}; +use std::collections::{BTreeSet, BTreeMap, HashMap}; +use std::usize; + + +pub type Cell = (usize, usize); + + +pub trait PathBuilder { + fn neighbors(&mut self, cell: Cell) -> Vec; + fn distance_between(&mut self, start: Cell, goal: Cell) -> usize; + + fn heuristic_cost_estimate(&mut self, start: Cell, goal: Cell) -> usize { + self.distance_between(start, goal) + } + + fn reconstruct_path(&self, came_from: &BTreeMap, current: Cell) -> Vec { + let mut current = current; + let mut path = Vec::new(); + + path.push(current); + + while came_from.contains_key(¤t) { + if let Some(next) = came_from.get(¤t) { + current = *next; + + path.push(*next); + } + } + + path + } +} + + +pub fn path_between(builder: &mut PathBuilder, start: Cell, goal: Cell) -> Result, ()> { + let mut closed_set = BTreeSet::new(); + let mut open_set = BTreeSet::new(); + + open_set.insert(start); + + let mut came_from = BTreeMap::new();; + + let mut g_score = BTreeMap::new(); + + g_score.insert(start, 0); + + let mut f_score = BTreeMap::new(); + + f_score.insert(start, builder.heuristic_cost_estimate(start, goal)); + + while !open_set.is_empty() { + let (current, _) = f_score.iter() + .filter(|&(&(x, y), _)| open_set.contains(&(x, y))) + .fold(((0, 0), usize::MAX), |((min_x, min_y), min_score), (&(x, y), &score)| { + if score < min_score { + ((x, y), score) + } else { + ((min_x, min_y), min_score) + } + }); + + if current == goal { + return Ok(builder.reconstruct_path(&came_from, current)); + } + + open_set.remove(¤t); + closed_set.insert(current); + + for neighbor in builder.neighbors(current) { + if closed_set.contains(&neighbor) { + continue; + } + + let tentative_g_score = *g_score + .entry(current) + .or_insert(usize::MAX) + builder.distance_between(current, neighbor); + + if !open_set.contains(&neighbor) { + open_set.insert(neighbor); + } else if tentative_g_score >= *g_score.entry(neighbor).or_insert(usize::MAX) { + continue + } + + came_from.insert(neighbor, current); + + g_score.insert(neighbor, tentative_g_score); + f_score.insert(neighbor, tentative_g_score + builder.heuristic_cost_estimate(neighbor, goal)); + } + } + + Err(()) +} + + +pub struct Grid { + grid: Vec> +} + +impl PathBuilder for Grid { + fn neighbors(&mut self, cell: Cell) -> Vec { + let mut neighbors = Vec::new(); + + // Check cell above. + if cell.1 > 0 && self.grid[cell.1 - 1][cell.0] != '#' { + neighbors.push((cell.0, cell.1 - 1)); + } + + // Check cell below. + if cell.1 < self.grid.len() - 1 && self.grid[cell.1 + 1][cell.0] != '#' { + neighbors.push((cell.0, cell.1 + 1)); + } + + // Check left cell. + if cell.0 > 0 && self.grid[cell.1][cell.0 - 1] != '#' { + neighbors.push((cell.0 - 1, cell.1)); + } + + // Check right cell. + if cell.0 < self.grid[0].len() - 1 && self.grid[cell.1][cell.0 + 1] != '#' { + neighbors.push((cell.0 + 1, cell.1)); + } + + neighbors + } + + fn distance_between(&mut self, start: Cell, goal: Cell) -> usize { + let delta_x = goal.0 as i64 - start.0 as i64; + let delta_y = goal.1 as i64 - start.1 as i64; + + (delta_x.abs() + delta_y.abs()) as usize + } +} + + +fn main() { + let stdin = io::stdin(); + + let grid = stdin.lock().lines() + .filter_map(|line| line.ok()) + .map(|line| line.chars().collect::>()) + .collect::>(); + + let mut grid = Grid { grid: grid }; + + let targets: HashMap = grid.grid.iter() + .enumerate() + .flat_map(|(y, row)| { + row.iter() + .cloned() + .enumerate() + .filter(|&(_, c)| c != '#' && c != '.') + .map(move |(x, c)| (c, (x, y))) + }) + .collect(); + + + let mut table = HashMap::new(); + + for left in targets.iter() { + for right in targets.iter().filter(|right| *right != left) { + if let Ok(path) = path_between(&mut grid, *left.1, *right.1) { + table.entry(left.0.clone()) + .or_insert(HashMap::new()) + .insert(right.0.clone(), path.len()); + } + } + } + + // Part 1. + let mut queue = Vec::new(); + + queue.push((0, vec!['0'])); + + 'main: loop { + let mut variants = Vec::new(); + + for &(ref total, ref items) in queue.iter() { + if items.len() == targets.len() { + break 'main; + } + + let last = items.last().unwrap(); + + for (next, distance) in table.get(last).unwrap().iter() { + if items.contains(&next) { + continue; + } + + let mut variant = items.clone(); + + variant.push(next.clone()); + + variants.push((total + distance - 1, variant)); + } + } + + queue = variants; + } + + queue.sort_by_key(|&(distance, _)| distance); + + println!("{:#?}", queue[0]); + + // Part 2. + let mut queue = Vec::new(); + + queue.push((0, vec!['0'])); + + 'main2: loop { + let mut variants = Vec::new(); + + for &(ref total, ref items) in queue.iter() { + let last = items.last().unwrap(); + + if items.len() >= targets.len() { + if *last != '0' { + if let Some(distance) = table.get(last).unwrap().get(&'0') { + let mut variant = items.clone(); + + variant.push('0'); + + variants.push((total + distance - 1, variant)); + } + } else { + break 'main2; + } + } + + for (next, distance) in table.get(last).unwrap().iter() { + if items.contains(&next) { + continue; + } + + let mut variant = items.clone(); + + variant.push(next.clone()); + + variants.push((total + distance - 1, variant)); + } + } + + queue = variants; + } + + queue.sort_by_key(|&(distance, _)| distance); + + println!("{:#?}", queue[0]); +}