Compare commits

...

3 Commits

Author SHA1 Message Date
Johannes
73b612d25b day 15 task 1 2019-12-21 23:08:59 +01:00
Johannes
73e4d50c51 easier loading of IntCodeComputer program and single step function 2019-12-21 23:08:35 +01:00
Johannes
ddd215c9a2 day 21 task 2 2019-12-21 12:30:00 +01:00
6 changed files with 298 additions and 1 deletions

1
input/day15.txt Normal file
View File

@@ -0,0 +1 @@
3,1033,1008,1033,1,1032,1005,1032,31,1008,1033,2,1032,1005,1032,58,1008,1033,3,1032,1005,1032,81,1008,1033,4,1032,1005,1032,104,99,1001,1034,0,1039,1002,1036,1,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1001,1034,0,1039,102,1,1036,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,102,1,1035,1040,1002,1038,1,1043,101,0,1037,1042,1105,1,124,1001,1034,1,1039,1008,1036,0,1041,102,1,1035,1040,1001,1038,0,1043,101,0,1037,1042,1006,1039,217,1006,1040,217,1008,1039,40,1032,1005,1032,217,1008,1040,40,1032,1005,1032,217,1008,1039,33,1032,1006,1032,165,1008,1040,33,1032,1006,1032,165,1101,0,2,1044,1106,0,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1105,1,224,1,1041,1043,1032,1006,1032,217,1,1042,1043,1032,1001,1032,-1,1032,1002,1032,39,1032,1,1032,1039,1032,101,-1,1032,1032,101,252,1032,211,1007,0,42,1044,1106,0,224,1102,0,1,1044,1106,0,224,1006,1044,247,1001,1039,0,1034,1001,1040,0,1035,1001,1041,0,1036,1001,1043,0,1038,102,1,1042,1037,4,1044,1106,0,0,6,28,51,33,63,27,52,11,53,13,96,8,87,11,23,65,43,11,13,9,37,66,68,40,19,41,6,90,28,19,38,86,38,22,7,44,36,23,17,1,16,54,36,74,14,79,2,14,83,10,38,19,62,66,27,56,33,52,47,98,41,39,77,83,48,29,49,15,80,59,9,72,79,55,24,66,50,24,27,56,37,41,13,72,35,13,64,70,5,66,78,37,78,24,43,93,22,41,30,58,14,45,6,27,44,48,40,52,31,12,3,72,7,14,59,35,17,63,34,79,93,17,54,98,35,21,91,25,32,77,10,31,88,17,35,79,96,11,83,15,48,9,19,64,24,65,86,32,71,22,88,55,31,18,88,68,34,40,94,1,71,24,40,44,28,43,4,98,21,80,17,53,2,94,6,43,59,23,66,63,12,30,45,39,93,41,85,43,51,18,99,59,86,40,36,26,94,33,41,28,66,79,81,11,61,46,32,72,71,47,39,22,69,60,36,50,12,44,28,41,79,17,6,74,8,56,39,33,67,23,20,51,12,7,26,57,1,92,80,11,52,19,5,54,13,41,56,37,22,57,43,18,97,27,83,30,3,77,85,66,64,17,99,27,25,95,40,81,97,13,35,46,14,25,63,36,72,87,20,96,29,2,69,90,27,27,91,52,14,14,73,55,4,73,19,85,39,84,23,23,90,40,5,88,53,77,8,92,11,82,66,6,27,84,53,38,93,34,37,58,20,43,25,73,78,30,17,92,54,38,26,67,16,30,28,79,77,26,3,15,82,59,34,34,18,44,34,33,83,35,90,31,58,44,16,18,65,8,70,90,32,46,21,41,54,39,43,93,23,99,11,43,50,98,33,34,53,54,53,16,39,88,53,36,69,85,26,44,38,62,98,6,79,26,35,49,67,22,11,74,35,80,4,50,18,54,4,10,4,58,4,46,20,15,77,73,11,41,58,85,39,87,37,73,36,36,67,28,12,17,34,53,38,89,96,34,39,67,64,33,81,37,74,88,20,84,94,53,39,57,73,13,76,1,35,14,73,29,29,23,73,52,16,85,87,33,48,13,2,93,78,7,17,60,49,13,36,89,40,25,44,55,26,81,37,31,84,31,62,2,66,77,23,88,11,81,9,63,46,19,35,54,17,85,24,1,86,28,72,1,1,61,27,38,81,8,67,82,3,11,77,35,62,83,20,28,61,37,37,92,22,72,76,37,52,17,62,68,38,53,2,57,82,67,25,11,59,3,49,97,1,40,91,75,7,85,98,33,90,1,37,57,14,34,67,65,20,85,10,18,86,20,52,84,24,20,70,10,64,16,64,2,15,85,36,28,7,87,47,44,9,29,54,83,28,37,81,68,18,12,80,26,98,97,25,86,69,39,70,22,23,72,15,56,94,27,14,13,8,50,73,90,24,95,14,41,57,22,67,25,80,46,39,84,80,19,22,63,53,45,62,21,84,36,69,41,44,96,38,92,21,23,64,35,11,75,57,88,6,7,90,10,36,19,68,78,23,62,34,49,4,80,38,2,70,48,39,55,20,22,39,8,90,64,38,39,47,41,63,72,5,10,72,88,35,50,5,66,30,80,74,23,97,39,98,19,17,85,38,34,62,37,25,58,15,93,37,13,71,72,72,4,84,40,92,61,88,9,7,62,59,87,17,36,39,43,21,11,16,58,16,58,20,66,18,83,33,66,62,90,32,74,15,58,62,43,16,66,22,90,2,68,30,54,18,59,22,50,12,60,35,66,77,51,36,64,89,82,21,85,0,0,21,21,1,10,1,0,0,0,0,0,0

View File

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

View File

@@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::path::Path;
pub type RAM = HashMap<usize, i128>;
@@ -14,6 +15,15 @@ pub fn run() {
task2(ram.clone());
}
pub fn load_ram<P: AsRef<Path>>(path: P) -> RAM {
let input = std::fs::read_to_string(path).unwrap();
input
.split(",")
.enumerate()
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect()
}
pub struct IntCodeComputer {
input_storage: Vec<i128>,
output_storage: Vec<i128>,
@@ -169,6 +179,13 @@ impl IntCodeComputer {
}
}
pub fn run_single(&mut self, input: i128) -> i128 {
self.set_input(&[input]);
self.clear_output();
self.run_until_input_empty();
*self.get_output().first().unwrap()
}
pub fn run_until_end(&mut self) {
if !self.run_until_input_empty() {
panic!("There wasn't enough input given to run until the program halted");

253
src/tasks/day15.rs Normal file
View File

@@ -0,0 +1,253 @@
use super::day05::*;
use std::collections::HashMap;
use std::collections::VecDeque;
use Direction::*;
#[allow(dead_code)]
pub fn run() {
let ram = load_ram("input/day15.txt");
task1(ram.clone());
}
#[allow(dead_code)]
fn task1(ram: RAM) {
let (map, goal) = explore_map(ram);
let shortest_path = map.get_shortest_path_to(Pos(0, 0), goal);
/*
map.print(
Map::positions_on_path(Pos(0, 0), &shortest_path)
.iter()
.map(|p| (*p, 'x'))
.collect(),
);
*/
println!(
"Task 1: shortest path to goal ({:?}) has length {}",
goal,
shortest_path.len()
);
}
fn explore_map(ram: RAM) -> (Map, Pos) {
let mut map = Map {
positions: HashMap::new(),
};
let mut current = Pos(0, 0);
map.positions.insert(current, '.');
let mut target: Option<Pos> = None;
let mut pc = IntCodeComputer::new(vec![], ram);
while let Some(non_explored_neighbor) = map.get_unexplored() {
// move to next field with unexplored neighbors
// *find path
// *follow directions
let round_starts_from = current;
let directions = map.get_shortest_path_to(round_starts_from, non_explored_neighbor);
for d in directions {
let res = pc.run_single(d.to_robot_cmd());
if res == 0 {
map.print(HashMap::new());
panic!("Ran against a wall stepping {:?} from {:?}.", d, current);
}
current = current.neighbor(d);
}
// explore all 4 neighbor positions
// i.e. for every direction move - if result is 0 mark as wall,
// if result is 1 or 2 move back and mark as empty. If result is 2 store
// target position
let ns = vec![N, S, W, E];
for d in ns {
let r = pc.run_single(d.to_robot_cmd());
match r {
0 => {
map.positions.insert(current.neighbor(d), '#');
}
1 => {
map.positions.insert(current.neighbor(d), '.');
pc.run_single(d.opposite().to_robot_cmd());
}
2 => {
map.positions.insert(current.neighbor(d), '.');
pc.run_single(d.opposite().to_robot_cmd());
target = Some(current.neighbor(d));
}
_ => panic!("unknown field type {}", r),
};
}
}
(map, target.unwrap())
}
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
struct Pos(i32, i32);
impl Pos {
fn add(&self, other: Self) -> Self {
Pos(self.0 + other.0, self.1 + other.1)
}
fn direction_to(&self, from: Pos) -> Direction {
let m: HashMap<Pos, Direction> = vec![
(Pos(0, 1), N),
(Pos(0, -1), S),
(Pos(1, 0), W),
(Pos(-1, 0), E),
]
.into_iter()
.collect();
m.get(&Pos(self.0 - from.0, self.1 - from.1))
.map(|p| *p)
.unwrap()
}
fn neighbor(&self, direction: Direction) -> Pos {
match direction {
N => self.add(Pos(0, -1)),
S => self.add(Pos(0, 1)),
W => self.add(Pos(-1, 0)),
E => self.add(Pos(1, 0)),
}
}
}
#[derive(Debug)]
struct Map {
positions: HashMap<Pos, char>,
}
impl Map {
fn get_unexplored(&self) -> Option<Pos> {
let neighbors = vec![Pos(-1, 0), Pos(1, 0), Pos(0, -1), Pos(0, 1)];
let r = self
.positions
.iter()
.filter(|(_, c)| **c == '.')
.map(|(p, _)| p)
.find(|pos| {
neighbors
.iter()
.any(|delta| !self.positions.contains_key(&pos.add(*delta)))
});
r.map(|p| *p)
}
fn get_shortest_path_to(&self, start: Pos, goal: Pos) -> Vec<Direction> {
let neighbors = vec![Pos(-1, 0), Pos(1, 0), Pos(0, -1), Pos(0, 1)];
let mut open: VecDeque<Pos> = VecDeque::new();
open.push_back(start);
let mut predecessors: HashMap<Pos, Option<Pos>> = HashMap::new();
predecessors.insert(start, None);
while let Some(current) = open.pop_front() {
let field = self.positions.get(&current);
if let Some(v) = field {
if *v != '.' {
continue;
}
} else {
continue;
}
neighbors.iter().for_each(|d| {
let n = current.add(*d);
if !predecessors.contains_key(&n) {
predecessors.insert(n, Some(current));
open.push_back(n);
}
});
if current == goal {
break;
}
}
let mut directions = Vec::new();
let mut current = goal;
while let Some(Some(pred)) = predecessors.get(&current) {
directions.push(current.direction_to(*pred).opposite());
current = *pred;
}
directions.reverse();
directions
}
#[allow(dead_code)]
fn positions_on_path(start: Pos, directions: &Vec<Direction>) -> Vec<Pos> {
let mut result = vec![start];
let mut current = start;
for d in directions {
current = current.neighbor(*d);
result.push(current);
}
result
}
fn print(&self, special: HashMap<Pos, char>) {
let xmin = (self
.positions
.iter()
.min_by_key(|(Pos(x, _), _)| x)
.unwrap()
.0)
.0;
let xmax = (self
.positions
.iter()
.max_by_key(|(Pos(x, _), _)| x)
.unwrap()
.0)
.0;
let ymin = (self
.positions
.iter()
.min_by_key(|(Pos(_, y), _)| y)
.unwrap()
.0)
.1;
let ymax = (self
.positions
.iter()
.max_by_key(|(Pos(_, y), _)| y)
.unwrap()
.0)
.1;
for y in ymin..=ymax {
for x in xmin..=xmax {
let c = self.positions.get(&Pos(x, y)).unwrap_or(&' ');
let c = if let Some(s) = special.get(&Pos(x, y)) {
s
} else {
c
};
print!("{}", c);
}
println!("");
}
}
}
#[derive(Hash, PartialEq, Copy, Clone, Debug)]
enum Direction {
N,
S,
W,
E,
}
impl Direction {
fn opposite(&self) -> Self {
match self {
N => S,
S => N,
W => E,
E => W,
}
}
fn to_robot_cmd(&self) -> i128 {
match self {
N => 1,
S => 2,
W => 3,
E => 4,
}
}
}

View File

@@ -1,5 +1,6 @@
use super::day05::*;
#[allow(dead_code)]
pub fn run() {
let input = std::fs::read_to_string("input/day21.txt").unwrap();
let ram: RAM = input
@@ -8,6 +9,7 @@ pub fn run() {
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
.collect();
task1(ram.clone());
task2(ram.clone());
}
fn task1(ram: RAM) {
@@ -23,6 +25,29 @@ WALK
play(ram.clone(), p);
}
fn task2(ram: RAM) {
// jump if NOT(A and B and C) and D and (H or (E and I) or (E and F))
let p = r"OR H J
OR E T
AND I T
OR T J
NOT E T
NOT T T
AND F T
OR T J
AND D J
NOT A T
NOT T T
AND B T
AND C T
NOT T T
AND T J
RUN
"
.to_string();
play(ram.clone(), p);
}
fn play(ram: RAM, program: String) {
let mut computer = IntCodeComputer::new(program.chars().map(|c| c as i128).collect(), ram);
computer.run_until_end();

View File

@@ -11,5 +11,6 @@ pub mod day11;
pub mod day12;
pub mod day13;
pub mod day14;
pub mod day15;
pub mod day16;
pub mod day21;