This commit is contained in:
foosinn 2020-05-28 22:49:16 +02:00
parent 0bd196febf
commit 244e308200
5 changed files with 222 additions and 5 deletions

32
Cargo.lock generated
View file

@ -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"

View file

@ -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

File diff suppressed because one or more lines are too long

135
src/day13/main.rs Normal file
View 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>;

View file

@ -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);