Commit 1207f273 authored by Marcel Behrmann's avatar Marcel Behrmann

day(18): solve part 1

parent 85d6e16e
......@@ -3,14 +3,15 @@ mod intvm;
mod map;
use std::fs;
use std::collections::{HashMap, VecDeque};
use std::iter::FromIterator;
use std::cmp::Ordering;
use std::collections::{HashMap, HashSet, BinaryHeap};
use map::{Pos, Path, Key};
use pathfinding::directed::astar;
const INPUT_FILE: &str = "input.txt";
fn main() {
#[allow(dead_code)]
let input = fs::read_to_string(INPUT_FILE).expect("Error reading input");
let input = input.lines();
let input: Vec<&str> = input.collect::<Vec<&str>>();
......@@ -21,7 +22,25 @@ fn main() {
type Map = HashMap<Pos, char>;
type Network = HashMap<char, Key>;
type State = (char, Vec<char>, u32);
#[derive(Clone, Eq, Debug, PartialEq)]
struct State(char, Vec<char>, u32, Vec<char>);
// 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 {
other.2.cmp(&self.2).then_with(|| other.1.len().cmp(&self.1.len()))
}
}
// `PartialOrd` needs to be implemented as well.
impl PartialOrd for State {
fn partial_cmp(&self, other: &State) -> Option<Ordering> {
Some(self.cmp(&other))
}
}
#[allow(unused_variables)]
fn part_01(input: Vec<&str>) -> u32 {
......@@ -61,41 +80,66 @@ fn part_01(input: Vec<&str>) -> u32 {
}
let network = build_network(&map,&keys);
let mut queue: VecDeque<State> = VecDeque::new();
let mut queue: BinaryHeap<State> = BinaryHeap::new();
queue.push_back(('@', needed_keys, 0));
let mut lowest = std::u32::MAX;
let mut last = needed_keys.len();
queue.push(State('@', needed_keys, 0, Vec::new()));
let mut min = std::u32::MAX;
let mut cache: HashMap<String, u32> = HashMap::new();
while queue.len() > 0 {
let current = queue.pop_front().unwrap();
let current = queue.pop().unwrap();
if current.1.len() == 0 {
if current.2 < lowest {
lowest = current.2;
let hash = String::from_iter(&current.3);
if let Some(val) = cache.get(&hash) {
if *val < current.2 {
continue;
}
}
continue;
if current.1.len() == 0 {
if min > current.2 {
return current.2;
}
}
if current.2 > lowest {
continue;
if last > current.1.len() {
last = current.1.len();
}
for key in &current.1 {
if let Some(path) = get_path_to_key(network.get(&current.0).unwrap(), *key, &current.1) {
let mut new_needed: Vec<char> = current.1.clone();
let mut new_visit = current.3.clone();
let new_key = key.clone();
let mut new_needed: Vec<char> = current.1.clone();
let new_depth = (path.path.len() as u32) + current.2 - 1;
new_needed.remove(new_needed.iter().position(|x| *x == new_key).unwrap());
new_visit.push(new_key);
new_visit.sort();
let hash = String::from_iter(&new_visit);
queue.push_back((new_key, new_needed, new_depth));
if let Some(c) = cache.get_mut(&hash) {
if *c > new_depth {
*c = new_depth;
new_needed.remove(new_needed.iter().position(|x| *x == new_key).unwrap());
//println!("UPDATE: {} -> {}", hash, new_depth);
queue.push(State(new_key, new_needed, new_depth, new_visit));
}
} else {
new_needed.remove(new_needed.iter().position(|x| *x == new_key).unwrap());
//println!("INSERT: {} -> {}", hash, new_depth);
cache.insert(hash, new_depth);
queue.push(State(new_key, new_needed, new_depth, new_visit));
}
}
}
}
lowest
0
}
fn get_path_to_key(key: &Key, target: char, still_needed: &Vec<char>) -> Option<Path> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment