Compare commits
6 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
81745013c9 | ||
![]() |
6f5e848c09 | ||
![]() |
604a4a7b29 | ||
![]() |
450a6b4f8a | ||
![]() |
d42a9178da | ||
![]() |
41c99c2032 |
6 changed files with 234 additions and 16 deletions
32
Cargo.lock
generated
32
Cargo.lock
generated
|
@ -3,3 +3,35 @@
|
|||
[[package]]
|
||||
name = "aoc2019"
|
||||
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"
|
||||
|
|
|
@ -4,9 +4,8 @@ version = "0.1.0"
|
|||
authors = ["Stefan Schwarz <stefan@f2o.io>"]
|
||||
edition = "2018"
|
||||
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
[dependencies]
|
||||
ncurses = "5.99.0"
|
||||
|
||||
[[bin]]
|
||||
name = "day1"
|
||||
|
@ -48,6 +47,10 @@ path = "src/day11/main.rs"
|
|||
name = "day12"
|
||||
path = "src/day12/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day13"
|
||||
path = "src/day13/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day14"
|
||||
path = "src/day14/main.rs"
|
||||
|
|
1
input13
Normal file
1
input13
Normal file
File diff suppressed because one or more lines are too long
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();
|
||||
}
|
||||
self.ordered.reverse();
|
||||
self.ordered.pop();
|
||||
self.ordered.retain(|res| res != "ORE");
|
||||
}
|
||||
|
||||
/// calculate how much ores are required for required_fuel
|
||||
|
@ -84,6 +84,7 @@ impl NanoFactory {
|
|||
});
|
||||
|
||||
// return cost for ore
|
||||
println!("{:?}", storage);
|
||||
*storage.get("ORE").unwrap() as usize
|
||||
}
|
||||
|
||||
|
@ -277,7 +278,8 @@ mod tests {
|
|||
.trim()
|
||||
.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.resource_usage(1), 31);
|
||||
}
|
||||
|
@ -297,7 +299,8 @@ mod tests {
|
|||
.trim()
|
||||
.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.resource_usage(1), 165);
|
||||
}
|
||||
|
@ -321,7 +324,6 @@ mod tests {
|
|||
);
|
||||
let factory = NanoFactory::from(bufreader);
|
||||
assert_eq!(factory.generate_fuel(), 13312);
|
||||
assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 82892753);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -344,10 +346,10 @@ mod tests {
|
|||
.trim()
|
||||
.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.resource_usage(1), 180697);
|
||||
// TODO assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 5586022);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -375,9 +377,9 @@ mod tests {
|
|||
.trim()
|
||||
.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.resource_usage(1), 2210736);
|
||||
// TODO assert_eq!(factory.generate_fuel_from_ores(1_000_000_000_000), 460664);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ pub struct Computer {
|
|||
modes: Modes,
|
||||
inputs: VecDeque<isize>,
|
||||
outputs: VecDeque<isize>,
|
||||
halted: bool,
|
||||
pub halted: bool,
|
||||
}
|
||||
|
||||
impl Clone for Computer {
|
||||
|
@ -181,6 +181,11 @@ impl Computer {
|
|||
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 {
|
||||
let mut computer = self.clone();
|
||||
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> {
|
||||
loop {
|
||||
self.step();
|
||||
|
@ -223,7 +248,28 @@ impl Computer {
|
|||
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 = ModedOpcode::from(instruction);
|
||||
self.modes = Modes::from(&instruction);
|
||||
|
@ -272,9 +318,8 @@ impl Computer {
|
|||
Mode::Immediate => want,
|
||||
Mode::Relative => (self.rel + self.get_pos(want)) as usize,
|
||||
};
|
||||
if length < want {
|
||||
let missing = (want - length) + 10000;
|
||||
self.program.extend_from_slice(&vec![0; missing])
|
||||
if length <= want {
|
||||
self.program.resize(want + 1, 0);
|
||||
}
|
||||
self.program[want] = value;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue