Compare commits
3 Commits
2040bc00aa
...
73b612d25b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73b612d25b | ||
|
|
73e4d50c51 | ||
|
|
ddd215c9a2 |
1
input/day15.txt
Normal file
1
input/day15.txt
Normal 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
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
mod tasks;
|
mod tasks;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tasks::day21::run();
|
tasks::day15::run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
pub type RAM = HashMap<usize, i128>;
|
pub type RAM = HashMap<usize, i128>;
|
||||||
|
|
||||||
@@ -14,6 +15,15 @@ pub fn run() {
|
|||||||
task2(ram.clone());
|
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 {
|
pub struct IntCodeComputer {
|
||||||
input_storage: Vec<i128>,
|
input_storage: Vec<i128>,
|
||||||
output_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) {
|
pub fn run_until_end(&mut self) {
|
||||||
if !self.run_until_input_empty() {
|
if !self.run_until_input_empty() {
|
||||||
panic!("There wasn't enough input given to run until the program halted");
|
panic!("There wasn't enough input given to run until the program halted");
|
||||||
|
|||||||
253
src/tasks/day15.rs
Normal file
253
src/tasks/day15.rs
Normal 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(¤t);
|
||||||
|
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(¤t) {
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
use super::day05::*;
|
use super::day05::*;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
let input = std::fs::read_to_string("input/day21.txt").unwrap();
|
let input = std::fs::read_to_string("input/day21.txt").unwrap();
|
||||||
let ram: RAM = input
|
let ram: RAM = input
|
||||||
@@ -8,6 +9,7 @@ pub fn run() {
|
|||||||
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
|
.map(|(i, s)| (i, s.parse::<i128>().unwrap()))
|
||||||
.collect();
|
.collect();
|
||||||
task1(ram.clone());
|
task1(ram.clone());
|
||||||
|
task2(ram.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn task1(ram: RAM) {
|
fn task1(ram: RAM) {
|
||||||
@@ -23,6 +25,29 @@ WALK
|
|||||||
play(ram.clone(), p);
|
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) {
|
fn play(ram: RAM, program: String) {
|
||||||
let mut computer = IntCodeComputer::new(program.chars().map(|c| c as i128).collect(), ram);
|
let mut computer = IntCodeComputer::new(program.chars().map(|c| c as i128).collect(), ram);
|
||||||
computer.run_until_end();
|
computer.run_until_end();
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ pub mod day11;
|
|||||||
pub mod day12;
|
pub mod day12;
|
||||||
pub mod day13;
|
pub mod day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
|
pub mod day15;
|
||||||
pub mod day16;
|
pub mod day16;
|
||||||
pub mod day21;
|
pub mod day21;
|
||||||
|
|||||||
Reference in New Issue
Block a user