Compare commits
4 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
655b99da1b | ||
![]() |
244e308200 | ||
![]() |
0bd196febf | ||
![]() |
a9b5197ca7 |
8 changed files with 444 additions and 16 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -3,3 +3,35 @@
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aoc2019"
|
name = "aoc2019"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"ncurses",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ncurses"
|
||||||
|
version = "5.99.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15699bee2f37e9f8828c7b35b2bc70d13846db453f2d507713b758fabe536b82"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||||
|
|
13
Cargo.toml
13
Cargo.toml
|
@ -4,9 +4,8 @@ version = "0.1.0"
|
||||||
authors = ["Stefan Schwarz <stefan@f2o.io>"]
|
authors = ["Stefan Schwarz <stefan@f2o.io>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
[profile.release]
|
ncurses = "5.99.0"
|
||||||
debug = true
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "day1"
|
name = "day1"
|
||||||
|
@ -48,6 +47,14 @@ path = "src/day11/main.rs"
|
||||||
name = "day12"
|
name = "day12"
|
||||||
path = "src/day12/main.rs"
|
path = "src/day12/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day13"
|
||||||
|
path = "src/day13/main.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "day14"
|
name = "day14"
|
||||||
path = "src/day14/main.rs"
|
path = "src/day14/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day15"
|
||||||
|
path = "src/day15/main.rs"
|
||||||
|
|
1
input13
Normal file
1
input13
Normal file
File diff suppressed because one or more lines are too long
1
input15
Normal file
1
input15
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,1002,1034,1,1039,102,1,1036,1041,1001,1035,-1,1040,1008,1038,0,1043,102,-1,1043,1032,1,1037,1032,1042,1106,0,124,1002,1034,1,1039,1001,1036,0,1041,1001,1035,1,1040,1008,1038,0,1043,1,1037,1038,1042,1105,1,124,1001,1034,-1,1039,1008,1036,0,1041,1001,1035,0,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,1,1032,1006,1032,165,1008,1040,9,1032,1006,1032,165,1102,1,2,1044,1105,1,224,2,1041,1043,1032,1006,1032,179,1102,1,1,1044,1106,0,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,35,1044,1106,0,224,1101,0,0,1044,1105,1,224,1006,1044,247,102,1,1039,1034,1002,1040,1,1035,1002,1041,1,1036,102,1,1043,1038,101,0,1042,1037,4,1044,1105,1,0,1,5,41,19,22,1,39,81,29,20,15,82,33,18,45,30,32,55,28,26,70,13,56,32,28,18,3,59,90,11,95,15,85,8,61,25,59,24,34,1,85,5,25,54,57,18,20,54,80,91,28,65,36,12,44,36,13,92,24,56,13,39,69,29,79,10,41,27,23,25,72,20,3,61,15,51,11,12,12,48,10,45,13,29,49,90,30,17,9,41,21,18,7,30,48,17,83,71,4,10,31,10,96,81,77,9,50,39,21,36,33,72,12,3,23,79,18,4,75,17,58,64,8,7,97,60,72,72,1,94,55,42,2,94,2,21,88,19,82,57,96,19,25,27,41,62,15,40,23,61,86,27,73,61,13,46,52,81,12,34,23,73,23,59,1,30,47,9,99,10,37,17,28,98,5,92,73,8,63,4,86,76,79,7,30,68,28,91,12,12,98,74,4,22,44,10,23,45,37,16,90,76,23,74,75,12,21,38,14,15,76,28,49,71,7,6,6,71,53,33,12,87,15,92,66,21,38,13,53,92,34,49,25,6,67,21,27,89,24,61,25,30,41,30,99,28,19,41,90,51,74,14,33,54,48,10,14,42,2,67,76,10,21,2,67,43,27,69,11,16,78,7,36,9,24,48,63,81,53,29,94,34,25,99,66,47,17,97,33,52,11,62,22,52,30,23,89,95,15,13,50,48,26,10,6,69,78,13,6,94,1,28,67,10,70,16,50,19,24,15,79,50,27,3,19,62,4,31,83,20,17,83,67,5,80,26,36,62,87,3,10,80,22,65,60,10,78,4,20,60,30,11,7,83,10,13,72,81,37,22,14,55,63,51,27,32,77,52,20,50,16,48,2,55,10,53,26,84,6,87,43,37,26,3,85,62,25,78,50,16,10,37,22,54,5,80,24,7,32,49,18,27,12,41,70,82,20,34,91,15,98,77,22,6,79,3,8,54,17,32,4,44,2,97,14,15,65,30,97,14,79,75,11,77,5,61,37,20,91,20,45,74,19,40,2,41,89,12,34,44,18,62,57,17,68,22,96,7,59,63,2,60,70,2,26,75,26,3,53,19,80,16,97,7,34,58,52,66,24,75,25,30,75,42,13,12,89,13,3,84,92,1,75,30,54,43,2,56,15,1,15,84,99,6,98,42,17,29,1,18,26,70,71,29,91,23,21,87,66,18,38,32,18,81,65,2,58,99,12,4,84,24,32,88,30,67,49,29,59,64,18,70,10,24,56,5,27,97,50,4,28,85,65,16,67,83,15,16,61,18,86,8,36,25,36,29,97,45,19,81,41,29,45,30,69,26,57,93,27,72,34,30,99,61,2,48,16,12,76,98,28,14,32,32,90,48,10,30,57,23,39,2,8,39,33,13,88,34,31,74,15,60,8,47,60,31,5,79,1,98,86,33,3,99,33,62,11,96,25,22,38,98,84,3,56,70,49,3,8,56,87,4,29,59,65,26,34,77,7,14,78,26,25,70,49,3,31,45,92,24,95,17,4,9,4,96,64,92,27,67,4,99,6,44,7,16,86,2,75,1,6,68,81,4,1,44,49,7,92,8,40,36,25,81,13,56,99,10,2,30,72,6,43,30,12,43,93,19,20,23,95,10,19,66,63,28,96,40,50,8,15,56,38,13,93,42,71,12,18,87,8,4,21,85,9,2,66,77,10,80,26,61,9,43,20,88,10,39,67,55,31,49,17,58,26,80,20,84,54,49,5,73,11,52,15,63,7,62,24,57,92,61,25,87,56,37,31,38,14,99,0,0,21,21,1,10,1,0,0,0,0,0,0
|
135
src/day13/main.rs
Normal file
135
src/day13/main.rs
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
use aoc2019::intcode;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use ncurses;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let f = File::open("input13")?;
|
||||||
|
let mut computer = intcode::Computer::from(f);
|
||||||
|
let mut grid: Grid = HashMap::new();
|
||||||
|
while let Some(output) = computer.run_until_n_output(3) {
|
||||||
|
let mut output = output.into_iter();
|
||||||
|
let xy = XY {
|
||||||
|
x: output.next().unwrap(),
|
||||||
|
y: output.next().unwrap(),
|
||||||
|
};
|
||||||
|
let tile = Tile::from(output.next().unwrap());
|
||||||
|
grid.insert(xy, tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// part 1
|
||||||
|
let blocks = grid.iter().filter(|(_, v)| **v == Tile::Block).count();
|
||||||
|
println!("blocks: {}", blocks);
|
||||||
|
|
||||||
|
// part2
|
||||||
|
ncurses::initscr();
|
||||||
|
ncurses::noecho();
|
||||||
|
let mut computer = computer.clone_with_modified_program(vec![(0, 2)]);
|
||||||
|
let mut paddlex = 0;
|
||||||
|
let mut score = 0;
|
||||||
|
while !computer.halted {
|
||||||
|
if let Some(output) = &computer.run_until_input() {
|
||||||
|
output.chunks(3).for_each(|c| {
|
||||||
|
if let &[x, y, value] = c {
|
||||||
|
if x == -1 && y == 0 {
|
||||||
|
score = value;
|
||||||
|
} else {
|
||||||
|
let tile = Tile::from(value);
|
||||||
|
if Tile::from(value) == Tile::HorizontalPaddle {
|
||||||
|
paddlex = x;
|
||||||
|
}
|
||||||
|
ncurses::mvprintw((y + 1) as i32, x as i32, tile.char());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let np = next_pos(&mut computer.clone());
|
||||||
|
ncurses::mvprintw(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
&format!(
|
||||||
|
"willx: {:0>2} paddlex: {:0>2} score: {:0>7}",
|
||||||
|
np, paddlex, score
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let joystick = match np.cmp(&paddlex) {
|
||||||
|
Ordering::Less => -1,
|
||||||
|
Ordering::Equal => 0,
|
||||||
|
Ordering::Greater => 1,
|
||||||
|
};
|
||||||
|
computer.push_input_and_step(joystick);
|
||||||
|
ncurses::refresh();
|
||||||
|
}
|
||||||
|
ncurses::endwin();
|
||||||
|
println!("score: {}", score);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_pos(computer: &mut intcode::Computer) -> isize {
|
||||||
|
while !computer.halted {
|
||||||
|
if let Some(output) = computer.run_until_input() {
|
||||||
|
for c in output.chunks(3) {
|
||||||
|
if let &[x, y, value] = c {
|
||||||
|
if x == -1 && y == 0 {
|
||||||
|
// skip score
|
||||||
|
} else if Tile::from(value) == Tile::Ball && y == 23 {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
computer.push_input_and_step(0);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
enum Tile {
|
||||||
|
Empty,
|
||||||
|
Wall,
|
||||||
|
Block,
|
||||||
|
HorizontalPaddle,
|
||||||
|
Ball,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Tile {
|
||||||
|
fn from(i: isize) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => Tile::Empty,
|
||||||
|
1 => Tile::Wall,
|
||||||
|
2 => Tile::Block,
|
||||||
|
3 => Tile::HorizontalPaddle,
|
||||||
|
4 => Tile::Ball,
|
||||||
|
_ => unreachable!("there are only 5 tiles..."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tile {
|
||||||
|
fn char(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Tile::Empty => " ",
|
||||||
|
Tile::Wall => "X",
|
||||||
|
Tile::Block => "O",
|
||||||
|
Tile::HorizontalPaddle => "-",
|
||||||
|
Tile::Ball => "*",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Hash)]
|
||||||
|
struct XY {
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(isize, isize)> for XY {
|
||||||
|
fn from(xy: (isize, isize)) -> Self {
|
||||||
|
XY { x: xy.0, y: xy.1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Grid = HashMap<XY, Tile>;
|
|
@ -60,7 +60,7 @@ impl NanoFactory {
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
self.ordered.reverse();
|
self.ordered.reverse();
|
||||||
self.ordered.pop();
|
self.ordered.retain(|res| res != "ORE");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// calculate how much ores are required for required_fuel
|
/// calculate how much ores are required for required_fuel
|
||||||
|
@ -84,6 +84,7 @@ impl NanoFactory {
|
||||||
});
|
});
|
||||||
|
|
||||||
// return cost for ore
|
// return cost for ore
|
||||||
|
println!("{:?}", storage);
|
||||||
*storage.get("ORE").unwrap() as usize
|
*storage.get("ORE").unwrap() as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +278,8 @@ mod tests {
|
||||||
.trim()
|
.trim()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
);
|
);
|
||||||
let factory = NanoFactory::from(bufreader);
|
let mut factory = NanoFactory::from(bufreader);
|
||||||
|
factory.resolve_order();
|
||||||
assert_eq!(factory.generate_fuel(), 31);
|
assert_eq!(factory.generate_fuel(), 31);
|
||||||
assert_eq!(factory.resource_usage(1), 31);
|
assert_eq!(factory.resource_usage(1), 31);
|
||||||
}
|
}
|
||||||
|
@ -297,7 +299,8 @@ mod tests {
|
||||||
.trim()
|
.trim()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
);
|
);
|
||||||
let factory = NanoFactory::from(bufreader);
|
let mut factory = NanoFactory::from(bufreader);
|
||||||
|
factory.resolve_order();
|
||||||
assert_eq!(factory.generate_fuel(), 165);
|
assert_eq!(factory.generate_fuel(), 165);
|
||||||
assert_eq!(factory.resource_usage(1), 165);
|
assert_eq!(factory.resource_usage(1), 165);
|
||||||
}
|
}
|
||||||
|
@ -321,7 +324,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
let factory = NanoFactory::from(bufreader);
|
let factory = NanoFactory::from(bufreader);
|
||||||
assert_eq!(factory.generate_fuel(), 13312);
|
assert_eq!(factory.generate_fuel(), 13312);
|
||||||
assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 82892753);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -344,10 +346,10 @@ mod tests {
|
||||||
.trim()
|
.trim()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
);
|
);
|
||||||
let factory = NanoFactory::from(bufreader);
|
let mut factory = NanoFactory::from(bufreader);
|
||||||
|
factory.resolve_order();
|
||||||
assert_eq!(factory.generate_fuel(), 180697);
|
assert_eq!(factory.generate_fuel(), 180697);
|
||||||
assert_eq!(factory.resource_usage(1), 180697);
|
assert_eq!(factory.resource_usage(1), 180697);
|
||||||
// TODO assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 5586022);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -375,9 +377,9 @@ mod tests {
|
||||||
.trim()
|
.trim()
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
);
|
);
|
||||||
let factory = NanoFactory::from(bufreader);
|
let mut factory = NanoFactory::from(bufreader);
|
||||||
|
factory.resolve_order();
|
||||||
assert_eq!(factory.generate_fuel(), 2210736);
|
assert_eq!(factory.generate_fuel(), 2210736);
|
||||||
assert_eq!(factory.resource_usage(1), 2210736);
|
assert_eq!(factory.resource_usage(1), 2210736);
|
||||||
// TODO assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 460664);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
205
src/day15/main.rs
Normal file
205
src/day15/main.rs
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use aoc2019::intcode;
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let f = File::open("input15")?;
|
||||||
|
let computer = intcode::Computer::from(f);
|
||||||
|
let mut map = Map::new();
|
||||||
|
let steps = map.walk(&XY { x: 0, y: 0 }, &computer, 0).unwrap();
|
||||||
|
|
||||||
|
for y in map.ymin..=map.ymax {
|
||||||
|
for x in map.xmin..=map.xmax {
|
||||||
|
if x == 0 && y == 0 {
|
||||||
|
print!("0");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let status = map.m.get(&XY { x, y }).unwrap_or(&Status::Empty);
|
||||||
|
let c = match status {
|
||||||
|
Status::HitWall => "#",
|
||||||
|
Status::MoveComplete => ".",
|
||||||
|
Status::Finished => "X",
|
||||||
|
Status::Empty => " ",
|
||||||
|
Status::Oxigenated => "o",
|
||||||
|
};
|
||||||
|
print!("{}", c);
|
||||||
|
}
|
||||||
|
println!("");
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("i walked {} steps", steps);
|
||||||
|
let steps = map.fill();
|
||||||
|
println!("filled with oxygen after {} minutes", steps);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
struct Map {
|
||||||
|
m: HashMap<XY, Status>,
|
||||||
|
xmin: isize,
|
||||||
|
xmax: isize,
|
||||||
|
ymin: isize,
|
||||||
|
ymax: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Map {
|
||||||
|
fn new() -> Self {
|
||||||
|
Map::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn walk(&mut self, start: &XY, computer: &intcode::Computer, steps: usize) -> Option<usize> {
|
||||||
|
let steps = steps + 1;
|
||||||
|
let mut result = None;
|
||||||
|
for dir in 1..=4 {
|
||||||
|
let direction = Direction::from(dir);
|
||||||
|
let xy = start.add((&direction).into());
|
||||||
|
if self.m.contains_key(&xy) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
self.update_limits(&xy);
|
||||||
|
let mut computer = computer.clone();
|
||||||
|
if let Some(status) = computer.run_io(dir) {
|
||||||
|
let status = Status::from(status);
|
||||||
|
self.m.insert(xy.clone(), status.clone());
|
||||||
|
match status {
|
||||||
|
Status::HitWall => (),
|
||||||
|
Status::MoveComplete => match self.walk(&xy, &computer, steps) {
|
||||||
|
Some(i) => result = Some(i + 1),
|
||||||
|
None => (),
|
||||||
|
},
|
||||||
|
Status::Finished => result = Some(1),
|
||||||
|
_ => unreachable!("unknown status"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("computer unexpectedly halted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill(&mut self) -> usize {
|
||||||
|
let mut src: Vec<XY> = self
|
||||||
|
.m
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(xy, status)| match status {
|
||||||
|
Status::Finished => Some(xy),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
let mut steps = 0;
|
||||||
|
while src.len() > 0 {
|
||||||
|
steps += 1;
|
||||||
|
src.iter()
|
||||||
|
.for_each(|xy| *self.m.get_mut(xy).unwrap() = Status::Oxigenated);
|
||||||
|
src = src
|
||||||
|
.into_iter()
|
||||||
|
.map(|xy| {
|
||||||
|
(1..=4)
|
||||||
|
.map(Direction::from)
|
||||||
|
.map(move |d| xy.add((&d).into()))
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.filter(|xy| match self.m.get(xy) {
|
||||||
|
Some(Status::MoveComplete) => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
self.m
|
||||||
|
.values()
|
||||||
|
.filter(|status| match status {
|
||||||
|
Status::MoveComplete => true,
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.count(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
steps - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_limits(&mut self, xy: &XY) {
|
||||||
|
if self.xmin > xy.x {
|
||||||
|
self.xmin = xy.x
|
||||||
|
}
|
||||||
|
if self.xmax < xy.x {
|
||||||
|
self.xmax = xy.x
|
||||||
|
}
|
||||||
|
if self.ymin > xy.y {
|
||||||
|
self.ymin = xy.y
|
||||||
|
}
|
||||||
|
if self.ymax < xy.y {
|
||||||
|
self.ymax = xy.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum Direction {
|
||||||
|
North = 1,
|
||||||
|
South = 2,
|
||||||
|
West = 3,
|
||||||
|
East = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Direction {
|
||||||
|
fn from(i: isize) -> Self {
|
||||||
|
match i {
|
||||||
|
1 => Direction::North,
|
||||||
|
2 => Direction::South,
|
||||||
|
3 => Direction::West,
|
||||||
|
4 => Direction::East,
|
||||||
|
_ => unreachable!("no status for computer output"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<(isize, isize)> for &Direction {
|
||||||
|
fn into(self) -> (isize, isize) {
|
||||||
|
match self {
|
||||||
|
Direction::North => (0, 1),
|
||||||
|
Direction::South => (0, -1),
|
||||||
|
Direction::West => (-1, 0),
|
||||||
|
Direction::East => (1, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum Status {
|
||||||
|
HitWall = 0,
|
||||||
|
MoveComplete = 1,
|
||||||
|
Finished = 2,
|
||||||
|
Empty = 3,
|
||||||
|
Oxigenated = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<isize> for Status {
|
||||||
|
fn from(i: isize) -> Self {
|
||||||
|
match i {
|
||||||
|
0 => Status::HitWall,
|
||||||
|
1 => Status::MoveComplete,
|
||||||
|
2 => Status::Finished,
|
||||||
|
_ => unreachable!("no status for computer output"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
||||||
|
struct XY {
|
||||||
|
x: isize,
|
||||||
|
y: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XY {
|
||||||
|
fn add(&self, delta: (isize, isize)) -> XY {
|
||||||
|
XY {
|
||||||
|
x: self.x + delta.0,
|
||||||
|
y: self.y + delta.1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -131,7 +131,7 @@ pub struct Computer {
|
||||||
modes: Modes,
|
modes: Modes,
|
||||||
inputs: VecDeque<isize>,
|
inputs: VecDeque<isize>,
|
||||||
outputs: VecDeque<isize>,
|
outputs: VecDeque<isize>,
|
||||||
halted: bool,
|
pub halted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for Computer {
|
impl Clone for Computer {
|
||||||
|
@ -181,6 +181,11 @@ impl Computer {
|
||||||
self.outputs.pop_front()
|
self.outputs.pop_front()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_input_and_step(&mut self, input: isize) {
|
||||||
|
self.inputs.push_back(input);
|
||||||
|
self.step()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clone_with_modified_program(&self, u: Vec<(usize, isize)>) -> Computer {
|
pub fn clone_with_modified_program(&self, u: Vec<(usize, isize)>) -> Computer {
|
||||||
let mut computer = self.clone();
|
let mut computer = self.clone();
|
||||||
for (pos, val) in u {
|
for (pos, val) in u {
|
||||||
|
@ -201,6 +206,26 @@ impl Computer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn run_until_input(&mut self) -> Option<Vec<isize>> {
|
||||||
|
self.step_until_input();
|
||||||
|
if self.outputs.len() > 0 {
|
||||||
|
return Some(self.outputs.split_off(0).into_iter().collect());
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_until_n_output(&mut self, n: usize) -> Option<Vec<isize>> {
|
||||||
|
loop {
|
||||||
|
self.step();
|
||||||
|
if self.outputs.len() >= n {
|
||||||
|
return Some(self.outputs.split_off(0).into_iter().collect());
|
||||||
|
}
|
||||||
|
if self.halted {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run_until_output(&mut self) -> Option<isize> {
|
pub fn run_until_output(&mut self) -> Option<isize> {
|
||||||
loop {
|
loop {
|
||||||
self.step();
|
self.step();
|
||||||
|
@ -223,7 +248,28 @@ impl Computer {
|
||||||
self.run_until_output()
|
self.run_until_output()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self) {
|
fn step_until_input(&mut self) {
|
||||||
|
while !self.halted {
|
||||||
|
let instruction = self.program[self.pos];
|
||||||
|
let instruction = ModedOpcode::from(instruction);
|
||||||
|
self.modes = Modes::from(&instruction);
|
||||||
|
let advance = match Opcode::from(&instruction) {
|
||||||
|
Opcode::Add => self.add(),
|
||||||
|
Opcode::Multiply => self.multiply(),
|
||||||
|
Opcode::Input => return,
|
||||||
|
Opcode::Output => self.output(),
|
||||||
|
Opcode::JumpIfTrue => self.jump_if_true(),
|
||||||
|
Opcode::JumpIfFalse => self.jump_if_false(),
|
||||||
|
Opcode::LessThan => self.less_than(),
|
||||||
|
Opcode::Equals => self.equals(),
|
||||||
|
Opcode::RelativeAdj => self.relative_adj(),
|
||||||
|
Opcode::Halt => self.halt(),
|
||||||
|
};
|
||||||
|
self.pos += advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(&mut self) {
|
||||||
let instruction = self.program[self.pos];
|
let instruction = self.program[self.pos];
|
||||||
let instruction = ModedOpcode::from(instruction);
|
let instruction = ModedOpcode::from(instruction);
|
||||||
self.modes = Modes::from(&instruction);
|
self.modes = Modes::from(&instruction);
|
||||||
|
@ -272,9 +318,8 @@ impl Computer {
|
||||||
Mode::Immediate => want,
|
Mode::Immediate => want,
|
||||||
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
|
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
|
||||||
};
|
};
|
||||||
if length < want {
|
if length <= want {
|
||||||
let missing = (want - length) + 10000;
|
self.program.resize(want + 1, 0);
|
||||||
self.program.extend_from_slice(&vec![0; missing])
|
|
||||||
}
|
}
|
||||||
self.program[want] = value;
|
self.program[want] = value;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue