day 18 task 1

This commit is contained in:
Johannes
2019-12-22 14:11:23 +01:00
parent 51f16fa7ad
commit 7b51854bb2
4 changed files with 300 additions and 1 deletions

81
input/day18.txt Normal file
View File

@@ -0,0 +1,81 @@
#################################################################################
#.#...#.....#...............#.....#v....#.........#p....#...#...................#
#.#.#.#.#.#.#M#############.#.###.#####.#####.###.#.###.#.#.#################.#.#
#..n#...#.#...#.#...........#...#.......#.....#.....#.#...#...#.......#...#...#.#
#########.#####.#.###########.#.#######.#.###########.#######.#C#####.#.#.#.###.#
#.........#.#.....#.........#.#.#.......#...........#...........#...#.#.#...#...#
#.#########.#.#########.#####.#W###.###############.###.#########.###.#.#####.###
#.Y...#...#...#.......#z......#...#.#...#...#.....#..d#.#.#..x..#...#.#.#...#.#.#
#####.#.#.#.###.#.###.#####.#####.#.#.#.#.#.#.###.###.#.#.#.###.#.#.#.#.#.#.#.#.#
#.....#.#...#...#.#.#.....#...#...#.#.#.#.#...#.......#...#.#...#.#.....#.#...#.#
#.#######.#######.#.#####.#####.#####.#.#.#############.###.#.###.#########.###.#
#...#...#.#...#...#.#...#.....#...B...#.#.....#...#.....#...#.#.....#....t#.....#
#.#.#.#.#.#.#.#.###.#.#.#####.#.#######.#.###.#.#.###.###.###.#.#####.###.#####N#
#.#...#.#...#.#.#.....#...#...#.#...#...#...#.#.#...#.#...#...#...#...#.#...#.#.#
#.#####.#####.#.#########.#.###.#.#.#.#.###.#.#.###.###.###.#######.###.###.#.#.#
#.#...#.#.......#...#.....#...#...#.#.#.#.#.#...#.#.....#...#.....#.#...#...#.#.#
#.#.###.#########.#.#.###.###.#####.#.#.#.#.#####.#######.###.###.#.#.###.###.#.#
#.#...#.#...#.....#.#...#...#.#...#.#.#.#.#.#.....#.....#...#.#.#...#...#.#...#.#
#.###.#.#.#.#.#####.#.#.#####.#.###.#.###.#.#.###.###.#.###.#.#.#####.#.#J#E###.#
#.....#.#.#...#...#.#.#.....#.#.....#...#.#.#.#.......#.#...#.#...#...#...#.....#
#######.#.#####.###.#######.#.#########.#.#.#.#########.#.###.#.#.#.#########.###
#.......#.#.....#.I.#.....#.............#...#...#.....#.#...#.#.#.#.........#...#
#.#######.###.###.#.#####.#.###########.#.###.#.###.###.###.#####.#########.###.#
#.......#...#.#...#.....#.#.#.......#...#.#...#.#...#.....#.........#.....#.#...#
#.#####.###.#.#.#######.#.###.#####.#.###.#####.#.###.#######.#####.#.###.#.###.#
#.#...#...#.#.#.......#.#.....#.#...#...#.#...#.#...#u#.....#...#...#.#.#.#...#.#
#.###.#.###.#.#######.#.#######.#.#####.#.#.#.#.#.#.#.#.#.#.###.#####.#.#.###.#.#
#...#.#...#.....#.....#.#.....#...#...#.#...#.#.#.#...#.#.#...#.#.....#.#.#...#.#
###.#.###.#####.#.#####.#.#.#.#.###.#.#.#####.#.#.#####.#.#.###.#.#####.#.#.###.#
#...#...#.......#.#.....#.#.#.#.....#.#.#.....#.#.#.....#.#.#...#.....#.#.#.#..k#
#.###.###########.#.#######.#.#######.#.#.#####.###.#####.###.#.#####.#.#.#.#.###
#...#...........#.#.....#...#.......#.#.#...#.........#...#...#.#.....#.#...#.#.#
###.#.###.###.###.#####.#.#.#######.#.#.###.#.#########.#.#.###.#.#####.#####.#.#
#.#.#...#...#.#...#...#.#.#.#.....#.#.#.#.#.#...#.......#.#.#...#...#.....#...#.#
#.#.###.###.#.#.###.#.#.#.###.###.###.###.#.#####.#######.#.#.#####.#.#.#.#.###.#
#.#.#.....#.#.#.....#g#...#...#.#...#...#.#.......#...#...#.#...#.#.#.#.#.#.....#
#.#.#######.#.#######.###.#.###.###.###.#.#########.###.###.###.#.#.#.#.#######.#
#...#.....#.#.#.....#.#...#.......#.#...#.....#.......#.#.#...#...#.#.#.......#.#
#.###.###.#.#.#.###.#.###########.#.#.###.###.#.#####.#.#.###.#####.#.#######.#.#
#.....#.....#...#...#.A...........#.........#.......#.R.....#.......#.......#...#
#######################################.@.#######################################
#.....#.........#...........#......r#...........#.#...#.............#.......#...#
###.###.#.#######.#.#######.#.#####.###.#.#.###.#.#.#.#.#######.###.#.#####.###.#
#...#...#.........#...#...#.#.....#.....#.#...#...#.#...#...#...#.#.#.....#.....#
#.###.###############.#.###.#.###.#####.#.###.#####.#######.#.###.#.#####.#######
#.....#.......#.#.....#...#.#.#...#.....#.#.#.#.....#.......#.#...#.....#.......#
#.#######.###.#.#.#######.#.###.#.#######.#.#.#.#########.###.#.#######G#.#####.#
#.....#...#.#...#.#.......#...#.#.#.....#...#.#.#.....#..a#...#.#.....#.#i....#.#
#####.#.###.###.#.###.#.#####.#.###.###.#####.#.###.#.#.#.#.###.#.###.#.#######.#
#...#.#.#.....#.#...#.#.#.....#.....#...#...#.......#...#.#.#.....#.#.........#.#
#.#.#.#.#.#####.###.#.###.###########.###.#.#.#############.#.#####.#########.#.#
#.#.#.#.#.......#...#.....#.....#...#...#.#.#.#.............#.......#...#.....O.#
#.#.#.#.#########.#######.#.###.#.#.###.#.#.###.###########.#########.#.#######.#
#.#.#e#.........#.#.....#...#...#.#.....#.#.#...#...........#.......#.#.....#...#
###.#.#########.#.#.###.#####P###.#######.#.#.#########.#####.#####.#.#####.#.###
#...#.......#...#...#.#.#...#...#...#...#.#...#.......#.#w....#f..#...#...#.#...#
#.#.#######.#.#######.#.#.#####.#.#.#.#.#.#.###.#####.###.###.#.#.#####.#.#.#####
#.#.#...#...#.........#.#...#...#.#...#.#.#.#.......#.#...#...#.#...#...#.#.#...#
#.#.#.###.#######.###.#.#.#.#.###.#####.#.###.#######.#.#######.###.#.###.#.#.#.#
#.#...#...#.....#...#.#.#.#...#..o..#...#...#...#...#.#...#...F.#...#...#.#...#.#
#.#####.###.###.###.###.#####.#####.#.#.#.#.#.###.#.#.###.#.#####L###.#.#.#####.#
#.......#...#.#.#...#.#.....#.....#.#.#.#.#...#...#.#.#...#...#...#...#.#.....#.#
#K#######.#.#.#.#.###.#####.#####X###.#.#######.###.#.#.#######.#####.#.#######.#
#....j..#.#.#.....#...#.....#...#...#.#.#.......#...#.#.....#...#.S.#.#.........#
#######.###.#####.#.###.#####.#.###.#.###.#######.###.#####.#.###.#.#.###########
#.....#...#.....#.#...#.......#...#.#...#.....#.#.#.......#.#l....#.#.#...#.....#
#T#.#####.#####.#####.#.#########.#.###.#.###.#.#.#####.#.#.#######.#.#.###.###.#
#.#.....#.#.....#.....#.#.......#.#.#...#c#.#.#.....#...#.#...Z.#...#.#.....#...#
#.###.###.#.#.###.#####.#.#####.#.#.#.#.#.#.#.#####.#.#######.###.###.#.#####.#.#
#...#...#...#.#...#...#...#...#.#.#.#.#.#...#.....#...#.....#.#s..#...#.#.#...#.#
###.###.#.#####.###.###.###.#.###.#.#.###.#######.###.#.#.###.#.###.###Q#.#.#####
#.#.#.#.#.#...#...#...#.#...#.....#.#...#.#.....#.#...#.#.#...#.V.#.#...#.#.....#
#.#.#.#.#.#.#.###.#.#.#.#.#########.###.#.#.###.#.#####.#.#.#####.#.#.###.#####.#
#...#.#...#.#...#.#.#.#.#...#...#...#...#.#...#y..#...#.#.#.......#.#.#.......#.#
#.###.#####.###.#.###.#.###.#.###.###.#.#####.#####.#.#.#.#########.#.#.#.#####.#
#.#.....#...#.#...#...#.#...#.#.D.#.U.#.#.....#...#.#.#.#.......#...#..b#.#.....#
#.#####.#.###.#####.###.#.###.#.###.###.#.#####.#.#.#.#.#######.#.#######.#.###.#
#.H...#.#...#...........#.#...#.#.....#.#m......#...#...#.......#.#...#...#.#...#
#####.#.###.#############.#.#.#.#####.#.#.###############.#######.#.#.#####.#.###
#..q......#...............#.#.........#.#...............#...........#.......#..h#
#################################################################################

View File

@@ -1,5 +1,5 @@
mod tasks; mod tasks;
fn main() { fn main() {
tasks::day15::run(); tasks::day18::run();
} }

217
src/tasks/day18.rs Normal file
View File

@@ -0,0 +1,217 @@
use itertools::Itertools;
use std::cmp::{Ord, Ordering, PartialOrd};
use std::collections::BinaryHeap;
use std::collections::HashSet;
use std::collections::VecDeque;
use std::rc::Rc;
pub fn run() {
let input: Map = Map(std::fs::read_to_string("input/day18.txt")
.unwrap()
.lines()
.map(|line| line.chars().collect_vec())
.collect_vec());
task1(input.clone());
}
fn task1(map: Map) {
let mut all_keys = map
.0
.iter()
.flatten()
.filter(|c| c.is_alphabetic() && c.is_lowercase())
.collect_vec();
all_keys.sort();
let all_keys: String = all_keys.into_iter().collect();
let map = Rc::from(map);
let mut visited: HashSet<StateSummary> = HashSet::new();
let mut open: BinaryHeap<State> = BinaryHeap::new();
let mut best_found_for_all = std::usize::MAX;
open.push(State::new(map.clone()));
while let Some(state) = open.pop() {
let summary = StateSummary::from(&state);
if visited.contains(&summary) || best_found_for_all <= state.steps_taken {
// there could come no better solution
continue;
}
if summary.1 == all_keys {
if state.steps_taken < best_found_for_all {
best_found_for_all = state.steps_taken;
}
}
state
.get_available_options()
.into_iter()
.for_each(|s| open.push(s));
visited.insert(summary);
}
println!(
"Task 1: best bound to get all keys is {}",
best_found_for_all
);
}
#[derive(Eq, PartialEq, Hash, Debug)]
struct StateSummary(Pos, String);
impl StateSummary {
fn from(state: &State) -> Self {
let mut s = state.opened.iter().collect_vec();
s.sort();
Self(
state.current,
s.into_iter()
.map(|c| {
let mut x = *c;
x.make_ascii_lowercase();
x
})
.collect(),
)
}
}
#[derive(Eq, PartialEq)]
struct StateSummaryDist(Pos, HashSet<char>, usize);
#[derive(PartialEq, Eq, Clone)]
struct Map(Vec<Vec<char>>);
impl Map {
fn coordinate_of(&self, symbol: char) -> Pos {
self.0
.iter()
.enumerate()
.map(|(y, line)| {
line.iter()
.enumerate()
.find(|(_x, c)| **c == symbol)
.map(|(x, _c)| Pos(x, y))
})
.find(|op| op.is_some())
.unwrap()
.unwrap()
}
fn reachable_keys(&self, start: Pos, open_doors: &HashSet<char>) -> Vec<(char, usize, Pos)> {
let all_keys = 'a'..='z';
let mut result = vec![];
let mut open: VecDeque<(Pos, usize)> = VecDeque::new();
open.push_back((start, 0));
let mut visited: HashSet<Pos> = HashSet::new();
while let Some((current, walked)) = open.pop_front() {
if visited.contains(&current) {
continue;
}
let field = self.0[current.1][current.0];
let field_is_key = all_keys.contains(&field);
// if can move over current type: push neighbors to open
if field == '.' || field == '@' || open_doors.contains(&field) || field_is_key {
current
.neighbors()
.iter()
.for_each(|n| open.push_back((*n, walked + 1)));
}
// if it is a key: push it to result
if field_is_key {
result.push((field, walked, current));
}
// anyways: push to visited
visited.insert(current);
}
result
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct Pos(usize, usize);
impl Pos {
fn neighbors(&self) -> [Pos; 4] {
[
Pos(self.0 - 1, self.1),
Pos(self.0 + 1, self.1),
Pos(self.0, self.1 - 1),
Pos(self.0, self.1 + 1),
]
}
}
#[derive(Eq, PartialEq)]
struct State {
current: Pos,
opened: HashSet<char>, // capital letter
map: Rc<Map>,
steps_taken: usize,
}
impl State {
fn new(map: Rc<Map>) -> Self {
Self {
current: map.coordinate_of('@'),
opened: HashSet::new(),
map: map,
steps_taken: 0,
}
}
fn get_available_options(&self) -> Vec<State> {
// find all keys that are not yet collected + their distance + position
let next_keys = self
.map
.reachable_keys(self.current, &self.opened)
.into_iter()
.filter(|(key, _, _)| {
let mut c = *key;
c.make_ascii_uppercase();
!self.opened.contains(&c)
})
.collect_vec();
// create new state with one open door added + steps increased + current position updated
next_keys
.into_iter()
.map(|(key, distance, current)| self.advance(key, distance, current))
.collect_vec()
}
fn advance(&self, key_added: char, additional_steps: usize, new_pos: Pos) -> Self {
let mut open_doors = self.opened.clone();
let mut door = key_added;
door.make_ascii_uppercase();
open_doors.insert(door);
Self {
current: new_pos,
opened: open_doors,
map: self.map.clone(),
steps_taken: self.steps_taken + additional_steps,
}
}
}
// The priority queue depends on `Ord`.
// Explicitly implement the trait so the queue becomes a min-heap
// instead of a max-heap.
impl Ord for State {
fn cmp(&self, other: &State) -> Ordering {
// Notice that the we flip the ordering on costs.
// In case of a tie we compare positions - this step is necessary
// to make implementations of `PartialEq` and `Ord` consistent.
other.steps_taken.cmp(&self.steps_taken)
}
}
// `PartialOrd` needs to be implemented as well.
impl PartialOrd for State {
fn partial_cmp(&self, other: &State) -> Option<Ordering> {
Some(self.cmp(other))
}
}

View File

@@ -13,4 +13,5 @@ pub mod day13;
pub mod day14; pub mod day14;
pub mod day15; pub mod day15;
pub mod day16; pub mod day16;
pub mod day18;
pub mod day21; pub mod day21;