Commit 85d6e16e authored by Marcel Behrmann's avatar Marcel Behrmann

day(18): new try

parent 02ff3251
mod utils;
mod intvm;
mod map;
use std::fs;
use std::collections::{HashMap, VecDeque, HashSet};
use std::collections::{HashMap, VecDeque};
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 =
"########################
#[email protected]#
######################.#
#d.....................#
########################";
/* let input =
"#########
#[email protected]#
#########";*/
let input =
"########################
#...............b.C.D.f#
#.######################
#[email protected]#
########################";
let input =
"#################
#i.G..c...e..H.p#
########.########
#j.A..b...f..D.o#
########@########
#k.E..a...g..B.n#
########.########
#l.F..d...h..C.m#
#################"; /* /*
let input =
"########################
#@..............ac.GI.b#
###d#e#f################
###A#B#C################
###g#h#i################
########################";*/*/*/
let input = input.lines();
let input: Vec<&str> = input.collect::<Vec<&str>>();
part_01(input.clone());
println!("Result Part 1: {}", part_01(input.clone()));
part_02(input.clone());
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct Pos(i32, i32);
impl Pos {
fn successors(&self) -> Vec<(Pos, u32)> {
let &Pos(x, y) = self;
vec![Pos(x+1, y), Pos(x-1,y), Pos(x,y+1), Pos(x,y-1)]
.into_iter().map(|p| (p, 1)).collect()
}
fn distance(&self, a: &Self) -> u32 {
((self.0 - a.0).abs() + (self.1 - a.1).abs()) as u32
}
}
type Map = HashMap<Pos, char>;
type Network = HashMap<char, Key>;
type State = (char, Vec<char>, u32);
#[allow(unused_variables)]
fn part_01(input: Vec<&str>) {
let mut map: HashMap<Pos, char> = HashMap::new();
fn part_01(input: Vec<&str>) -> u32 {
let mut map: Map = HashMap::new();
let mut x = 0;
let mut y = 0;
let mut start = Pos(-1, -1);
let mut keys: Vec<Pos> = Vec::new();
let mut needed_keys: Vec<char> = Vec::new();
for line in input {
for c in line.chars() {
......@@ -86,12 +40,15 @@ fn part_01(input: Vec<&str>) {
match c {
'.' => (),
'#' => (),
'@' => start = Pos(x, y),
'@' => {
keys.push(Pos(x, y));
},
_ => {
let cu = c as u8;
if cu > 96 {
keys.push(Pos(x, y));
needed_keys.push(c);
}
}
};
......@@ -103,20 +60,60 @@ fn part_01(input: Vec<&str>) {
x = 0;
}
println!("Cave contains {} keys", keys.len());
let network = build_network(&map,&keys);
let mut queue: VecDeque<State> = VecDeque::new();
let steps_for_keys = find_keys(start.clone(), &map, keys.clone(), Vec::new(), 0);
queue.push_back(('@', needed_keys, 0));
println!("Needed {} Steps", steps_for_keys);
let mut lowest = std::u32::MAX;
println!("Result of Part 1");
while queue.len() > 0 {
let current = queue.pop_front().unwrap();
if current.1.len() == 0 {
if current.2 < lowest {
lowest = current.2;
}
continue;
}
if current.2 > lowest {
continue;
}
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 new_key = key.clone();
let new_depth = (path.path.len() as u32) + current.2 - 1;
new_needed.remove(new_needed.iter().position(|x| *x == new_key).unwrap());
queue.push_back((new_key, new_needed, new_depth));
}
}
}
lowest
}
fn find_keys(pos: Pos, map: &HashMap<Pos, char>, keys: Vec<Pos>, available: Vec<char>, length: u32) -> u32 {
if keys.len() == 0 {
return length;
fn get_path_to_key(key: &Key, target: char, still_needed: &Vec<char>) -> Option<Path> {
if let Some(path) = key.links.get(&target) {
for gate in &path.gates {
if still_needed.contains(&(((*gate as u8) + 32) as char)) {
return None;
}
}
return Some(path.clone());
}
None
}
fn build_network(map: &Map, keys: &Vec<Pos>) -> Network {
let mut network: Network = Network::new();
let successors = |p: &Pos| {
p.successors()
.iter()
......@@ -125,11 +122,8 @@ fn find_keys(pos: Pos, map: &HashMap<Pos, char>, keys: Vec<Pos>, available: Vec<
match p {
Some(x) => {
match x {
'.' => true,
'#' => false,
_ => {
*x as u8 > 96 || *x == '@' || available.contains(x)
}
_ => true,
}
},
None => {
......@@ -141,52 +135,50 @@ fn find_keys(pos: Pos, map: &HashMap<Pos, char>, keys: Vec<Pos>, available: Vec<
.collect::<Vec<(Pos, u32)>>()
};
let mut lowest = std::u32::MAX;
//println!("Looking for keys: {:?}, with open dors: {:?}", keys, available);
for key in &keys {
let goal = key;
let result = astar::astar(
&pos,
successors,
|p| p.distance(goal),
|p| *p == *goal
);
//println!("Found path: {:?}", result);
match result {
Some(path) => {
let mut new_keys = keys.clone();
let mut new_available = available.clone();
// Remove found key from list of keys
let pos = new_keys.iter().position(|x| *x == *key).unwrap();
new_keys.remove(pos);
// Add new key to available keys
new_available.push(((*map.get(goal).unwrap() as u8) - 32) as char);
//println!("We now have keys: {:?}", new_available);
let new_length = length + path.1;
for from in keys {
let from_key: char = *map.get(&from).unwrap();
let mut key = Key {
pos: from.clone(),
key: from_key,
links: HashMap::new(),
};
if new_length > lowest {
continue;
}
for to in keys {
let to_char = *map.get(&to).unwrap();
let result = astar::astar(
from,
successors,
|p| p.distance(to),
|p| *p == *to
);
match result {
None => (),
Some(path) => {
let mut p = Path {
from: from.clone(),
to: to.clone(),
path: path.0,
gates: Vec::new(),
};
for pos in &p.path {
let c = map.get(&pos).unwrap();
if *c >= 'A' && *c <= 'Z' {
p.gates.push(*c);
}
}
let overall = find_keys(goal.clone(), &map, new_keys, new_available, new_length);
key.links.insert(to_char, p);
},
};
}
if overall < lowest {
lowest = overall;
}
},
None => ()
};
network.insert(from_key, key);
}
lowest
network
}
#[allow(unused_variables)]
......
use std::collections::HashMap;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Pos(pub i32, pub i32);
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Path {
pub from: Pos,
pub to: Pos,
pub path: Vec<Pos>,
pub gates: Vec<char>,
}
#[derive(Clone, Debug)]
pub struct Key {
pub pos: Pos,
pub key: char,
pub links: HashMap<char, Path>,
}
impl Pos {
pub fn successors(&self) -> Vec<(Pos, u32)> {
let &Pos(x, y) = self;
vec![Pos(x+1, y), Pos(x-1,y), Pos(x,y+1), Pos(x,y-1)]
.into_iter().map(|p| (p, 1)).collect()
}
pub fn distance(&self, a: &Self) -> u32 {
((self.0 - a.0).abs() + (self.1 - a.1).abs()) as u32
}
}
\ No newline at end of file
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