2016/24
This commit is contained in:
4
2016/24/Cargo.lock
generated
Normal file
4
2016/24/Cargo.lock
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[root]
|
||||||
|
name = "24"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
6
2016/24/Cargo.toml
Normal file
6
2016/24/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "24"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["logaritmisk <anders.e.olsson@gmail.com>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
5
2016/24/example.txt
Normal file
5
2016/24/example.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
###########
|
||||||
|
#0.1.....2#
|
||||||
|
#.#######.#
|
||||||
|
#4.......3#
|
||||||
|
###########
|
||||||
43
2016/24/input.txt
Normal file
43
2016/24/input.txt
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
###################################################################################################################################################################################
|
||||||
|
#.........#...#.............#...#3#.#.....#...........#.........#.#...#.......#.#.#...#...#.................#...........#.#...#.#.......#.......#.......#...#...#.....#.....#.....#
|
||||||
|
#.#.#.#.#.#.#########.#.#.###.#.#.#.###.###.#.###.#.#.#.###.#.###.#.#.#.#.#####.#.#.#.#.#.#.###.#.#.#.#.#.#.#.###.#.#.###.#.#.#.#####.#.#.#.###.#.#.#.#.#.###.#.###.###.###.###.#.#
|
||||||
|
#...#...#...#.......#...#.#.#.....#...#.....#.........#.......#.#...#...#.#.............#...#.......#.#.#...#.#.....#.......#...#.....#...#...........#...#...#.#...............#2#
|
||||||
|
#.###.#.#.#####.###.###.#.#.#.#.###.#.#.#####.#######.#.###.###.#.#.#.#.#.#####.###.###.#.#.#####.#.###.#.###.#.#.#.#.#.#######.#######.#.#.###.###.###.#.#.#.#.#.#.###.#.###.#.###
|
||||||
|
#.......#.........#.#.#...#...#...#.....#.#.............#.....#...#.......#.#.....#...#...#.......#.............................#.#...#...#...#.....#...#.......#.......#.......#.#
|
||||||
|
#.###.#.#.#########.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#####.#.#.#######.#.#.#.#.#.#.#####.#.###.#.#####.#.###.###.#.#.###.###.#.#.#.#####.#.###.#.#.#.#######.###.#.#.#.###.###.#
|
||||||
|
#...#.#...#...#...#...#.#...#.....#...#...........#.....#.........#.#...#...#...#.#...#.......#...#.#.....#.#.....#...#.#.......#.#.#.......#.......#...........#.#.#...#.#.......#
|
||||||
|
#.#.#.###.###.#.#.#######.#.#.#.#.#.#.###.###########.#.#.#####.###.#.#.#####.#.#.#.#####.###.#.###.#####.###.#####.#########.#.###.#.###.#.#.#.#.###.###.#.#####.#.#.#.#.#.###.#.#
|
||||||
|
#.......#.......#...........#...#.#...#.............#.#.#...#...#.....#...#...#.#...#...#.......#.#.#.#...#.....#.#.#.........#...#...#.....#.#...........#.#.......#.#.#...#...#.#
|
||||||
|
#.#.#.###.#####.#.#####.#.###.#.#.#.###.#.#.#.###.###.#.#####.###.#####.#.#.#####.#.#.#.#######.#.###.#.###.#####.#.#####.#.#.#####.#.#.#.#.###.#.#######.#.#.#.###########.#.#.#.#
|
||||||
|
#.#.#.....#.#1..........#.#...#...#.....#.........#...............#.#...#.....#...#.......#...........#.#...#.#.....#.............#.............#.....#...#.....#...#.....#.#.....#
|
||||||
|
#.#.###.#.#.#####.#.#.#.###.#####.#.#.#.###.###.#.#.#.#####.#.#.###.#.#.#####.#.#.#.#.#.#.###.#.###.#.#.#.#.#.#.###.#.#.#####.###.###.###.#.#.#.###.#.#.#.#.#.###.#.#.#####.#####.#
|
||||||
|
#...#...#.#...#.#.#.#.#.......#.....................#.#...............#.......#.#...#.#.#.....#.#.#...#...#.#.......#.....#.#...#.........#.#.#...#.........#.............#.....#.#
|
||||||
|
#.###.###.###.#.#.###.#.#####.#.#####.###.###########.###.#.#.#####.#.#.#.###.###.#.#.#.#.###.#.#.#.#.###.#.###.#.#########.#.#.#.#.###.#.#.#.#.#.#.#.#.#.###.###.#####.#.#####.###
|
||||||
|
#.....#.#.......#.#.#.....#...#.......#...#.#...#.............#.#.#.....#.........#...#.#.........#.#.#.#...#.#...#...#.......#.....#.#.....#.#.#.......#.#...#.#.....#.......#...#
|
||||||
|
#.#.###.#.#######.#.#.#.###.#.###.###.#####.#.#.#.#.###.###.###.#.#.#####.#.#####.#.#.#.#.#.#########.#.#.#.#.#.#.#.#.#.###.#.###.#.#.###.###.#.#######.#.#.#.#.#.###.#.#.#.#.###.#
|
||||||
|
#.#.#.......#...#...#.#.#.#.....#.....#...#...#.....#...#...#...#...........#...........#.........#.#.....#.....#.......#...#...#...#.#...#.#.#.........#...#.....#.#...#.#.....#.#
|
||||||
|
#.#.#.#####.#.#.#.###.###.#.#.#####.#.###.#.#.#####.#.#####.#.#.#.#####.###.#.#.#.#.###.#.#.#.#.#.#.#.###.#.#####.###.###.#.#.#.#.#.#.#.#.#.###.###.#.#######.#####.###.#.###.###.#
|
||||||
|
#.#.......#.#...#.#...#.#.#.......#...#.....#.........#.....#.#.....#...#...#.#.#...#.....#...#...#...#.....#.......#.#.#...#.#.........#...#.#..4#.#.#.#.#.....#.....#.........#.#
|
||||||
|
#.###.#.#.#.###.#.#.###.#.#######.#.#.###.#.###.#.#.#.#.#.#.###.#####.#.###.#######.#####.###.#.#.#.#.#.###.#.#####.#.#.#.#.#.#.#.#.#.#.#.#.#.#######.#.#.#.#.#.#.#.#.#.#.###.#.#.#
|
||||||
|
#0#...#.#.#.....#...#...#.#...#...#...#...#.......#.#.#.....#...#...#...#...#...#...#.........#.......#...#.......#...#...#...#.......#...#...............#.....#...#...#...#.#...#
|
||||||
|
###.#.#.###.###########.#.#####.###.###.###.###.###.#.###.#.#.#.#.#.#.#.#.#.#.###.#.###.#.#.#.#####.#.#.#.#.#.#.#.#.#.#.#.###.#####.#.#####.#.#.#.#####.#.#.#####.#####.#.#.#.#.###
|
||||||
|
#...#.#...#.......#...#...........#...#.....#...#...#.#.........#.....#.#...#.......#.....#.#.#.........#.........#...#.#.#...#.#.....#.....................#...............#.....#
|
||||||
|
###.#.#.#.#.#.###.#.#.#.#.#######.#.#.###.###.#.#.#####.###.###.###.###.#.#.#.#.#######.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.#.#####.###.#######.###.###.#.###.###.###.###.#.#.#
|
||||||
|
#...#.............#.#...........#.#.#.....#.....#.......#.#.....#...#.........#.....#.......#.....#...#.....#...#.......#...#...#.#.........#...#...........#.......#...#.......#.#
|
||||||
|
###.#.#########.#.#.#####.#.#.#.#.#.#.###.#.#######.#.#.#.#.#.#####.#.#.#.#####.#.#.#.#####.#######.#.#.#.#.#.#####.#.#.#.#####.#.#.###.#######.#######.#.#.###.#.#.#.#.#.#.###.#.#
|
||||||
|
#.#...............#.#.......#.....#.................#...#.#.#.......#...#.......#.#.#...#.#.......#...#.....#.....#...#.#.......#.#.#.....#.....#.....#.#...#.#...#...#.#...#.#.#.#
|
||||||
|
#.#.#.###.#.#.#.#.#.#.#.#.#.#########.#.#.#.#.#.#.#.#.#.#.#.###.#.#.#.###.#.#.#.#.#.###.#.#.###.#.#.###.###.#.#.#####.#####.#####.#.#.#.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.#.#####
|
||||||
|
#...#.#.....#...#.............#.#.#.#.........#.#...#.#.....#.......#...#.#.#.....#.......#...#...#...........#.....#.#.......#...#...#.#.........#...#...#.....#.......#...#.....#
|
||||||
|
###.#.#.#.#.#.#.###.#.###.#.###.#.#.#.#.###.#.###.#.#.#####.###.###.#.#.#.###.#.#.###.###.###.#.#.#.#.###.#####.###.#####.#.#.###.###.#####.#####.#.#.#######.###.###.###.#.#.#.#.#
|
||||||
|
#...#.#.....#.........#.......#.#...#.......#...#...#...........#.....#.......#...........#.......#...#...#.....#.....#...#.......#.#.#...#.#.....#.........#.....#...#.#...#.#...#
|
||||||
|
###.###.###.###.#.#####.###.#.#.#.#.#.###.###.###.###.#.#####.#.#.#.#.###.#.#.###.#.###.###.#.#.###.###.#.#.#.#.#.#.#.#.#.#.#.#.###.#.###.#.###.#.#.#####.#.#####.#.#.#.#####.#.#.#
|
||||||
|
#.#.#...#.#.#...................#.......#.#.#.#.#.....#.#.#.....#...#.......#.#...#.......#.....#...#.....#...#...#.#...#...#.........#...#...#...........#.........#.#..5#...#...#
|
||||||
|
#.#.#.###.#.###.#####.#.#.###.#.#####.#.#.#.#.#.#.###.#.#.#.#######.###.#.#.#.#.#.###.#.#.#.###.#.#####.#.#.#.#####.#.###.#.#.###.###.#.###.#.#.###########.#.#######.#.#.#.###.###
|
||||||
|
#...#.#.#...#.#.................#.#.....#.#.........#.....#.#.#...#.#.........#...#.#...#.#.........#...#...#.....#.#.#.#.....#...#.#.....#.#.............#.#...#.#.#.....#...#...#
|
||||||
|
#.#.###.#.#.#.#.#.#.#.#.###.###.#.#.#######.#######.###.#.#.#.###.#.#.#####.###.###.#####.#.#####.#.#.#.#.#.#.###.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#.#.#.###.#.#.#.#.#####.###.#.#
|
||||||
|
#...#.....#.....#.....#.#...#...#...............#...#...#...#.....#...#.#.....#.#.#...#...#.#...#...#.....#...#...#...................#.........#...#.........#.#...#.......#...#.#
|
||||||
|
###.#.###.#.#.#.###.#.#.#.#.#.###.###.#.###.###.#.###.#.#######.#.#.#.#.#.#####.#.#.#.#.#.###.#.#.#.#####.#.#.###.#.#######.#######.###.#######.#.#.#.#.###.###.###.#.#.#.#.#.#.#.#
|
||||||
|
#.....#7..#.#.#...........#.#...#.........#.....#.#.#...#.....#.............#...#...#...#.#.#...#.......#...#.....#.#.......#.#.....#...#...#...#...#...#...#.#.....#.#.......#.#.#
|
||||||
|
#.#.#.#.#.#.#.#.#.#.###.#####.#.#############.#.###.#.#.#.#.###.###.#######.#.#.###.#.###.#.###.#######.###.###.#.#.###.#.#.#.#.#.###.###.###.#.#.###.#.#.#.#.#.#.###.#.###.#.#.###
|
||||||
|
#...#.....#.#...#.#.....#.....#...#...#.......#6#.......#.#.......#.#.........#...#.#.....#.....#.#.......#.#.......#.......#.....#.....#.....#...#.#.#.#...#.#...#.#...#...#.#.#.#
|
||||||
|
###################################################################################################################################################################################
|
||||||
249
2016/24/src/main.rs
Normal file
249
2016/24/src/main.rs
Normal file
@@ -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<Cell>;
|
||||||
|
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<Cell, Cell>, current: Cell) -> Vec<Cell> {
|
||||||
|
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<Vec<Cell>, ()> {
|
||||||
|
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<Vec<char>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PathBuilder for Grid {
|
||||||
|
fn neighbors(&mut self, cell: Cell) -> Vec<Cell> {
|
||||||
|
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::<Vec<_>>())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut grid = Grid { grid: grid };
|
||||||
|
|
||||||
|
let targets: HashMap<char, (usize, usize)> = 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]);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user