Day 5, Stage 1

This commit is contained in:
Armin Friedl 2019-12-07 00:23:17 +01:00
parent fe694d1e6d
commit c944c2a758
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
4 changed files with 885 additions and 0 deletions

View file

@ -4,6 +4,7 @@
## Days
## License
I don't expect this to be used in any relevant capacity. Hence, this code is

9
day5/1/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "intcode"
version = "0.1.0"
authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

678
day5/1/input Normal file
View file

@ -0,0 +1,678 @@
3
225
1
225
6
6
1100
1
238
225
104
0
1101
90
60
224
1001
224
-150
224
4
224
1002
223
8
223
1001
224
7
224
1
224
223
223
1
57
83
224
1001
224
-99
224
4
224
1002
223
8
223
1001
224
5
224
1
223
224
223
1102
92
88
225
101
41
187
224
1001
224
-82
224
4
224
1002
223
8
223
101
7
224
224
1
224
223
223
1101
7
20
225
1101
82
64
225
1002
183
42
224
101
-1554
224
224
4
224
102
8
223
223
1001
224
1
224
1
224
223
223
1102
70
30
224
101
-2100
224
224
4
224
102
8
223
223
101
1
224
224
1
224
223
223
2
87
214
224
1001
224
-2460
224
4
224
1002
223
8
223
101
7
224
224
1
223
224
223
102
36
180
224
1001
224
-1368
224
4
224
1002
223
8
223
1001
224
5
224
1
223
224
223
1102
50
38
225
1102
37
14
225
1101
41
20
225
1001
217
7
224
101
-25
224
224
4
224
1002
223
8
223
101
2
224
224
1
224
223
223
1101
7
30
225
1102
18
16
225
4
223
99
0
0
0
677
0
0
0
0
0
0
0
0
0
0
0
1105
0
99999
1105
227
247
1105
1
99999
1005
227
99999
1005
0
256
1105
1
99999
1106
227
99999
1106
0
265
1105
1
99999
1006
0
99999
1006
227
274
1105
1
99999
1105
1
280
1105
1
99999
1
225
225
225
1101
294
0
0
105
1
0
1105
1
99999
1106
0
300
1105
1
99999
1
225
225
225
1101
314
0
0
106
0
0
1105
1
99999
7
226
226
224
102
2
223
223
1006
224
329
101
1
223
223
1107
677
226
224
102
2
223
223
1006
224
344
1001
223
1
223
8
677
226
224
1002
223
2
223
1005
224
359
101
1
223
223
107
677
677
224
1002
223
2
223
1006
224
374
101
1
223
223
7
677
226
224
1002
223
2
223
1006
224
389
101
1
223
223
108
677
226
224
1002
223
2
223
1005
224
404
101
1
223
223
1108
677
226
224
102
2
223
223
1005
224
419
101
1
223
223
8
226
677
224
102
2
223
223
1006
224
434
1001
223
1
223
1008
677
677
224
1002
223
2
223
1005
224
449
1001
223
1
223
1107
226
677
224
102
2
223
223
1006
224
464
101
1
223
223
107
226
677
224
1002
223
2
223
1006
224
479
1001
223
1
223
7
226
677
224
102
2
223
223
1005
224
494
1001
223
1
223
8
677
677
224
102
2
223
223
1006
224
509
1001
223
1
223
1108
677
677
224
102
2
223
223
1005
224
524
1001
223
1
223
1108
226
677
224
1002
223
2
223
1005
224
539
101
1
223
223
107
226
226
224
102
2
223
223
1006
224
554
1001
223
1
223
1007
226
226
224
102
2
223
223
1005
224
569
1001
223
1
223
1008
226
226
224
102
2
223
223
1005
224
584
101
1
223
223
1007
677
677
224
1002
223
2
223
1005
224
599
1001
223
1
223
108
677
677
224
1002
223
2
223
1006
224
614
1001
223
1
223
1007
226
677
224
1002
223
2
223
1006
224
629
101
1
223
223
1008
677
226
224
102
2
223
223
1005
224
644
101
1
223
223
1107
226
226
224
1002
223
2
223
1005
224
659
1001
223
1
223
108
226
226
224
1002
223
2
223
1005
224
674
101
1
223
223
4
223
99
226

197
day5/1/src/main.rs Normal file
View file

@ -0,0 +1,197 @@
use std::fs::File;
use std::io::{BufReader, BufRead, stdin, stdout, Write};
use std::error::Error;
use std::result::Result;
#[derive(Debug)]
struct Computer {
mem: Vec<i32>,
intp: *mut i32, // here will be dragons
}
struct Opcode {
inst: u8,
mode: Vec<Opmode>,
}
enum Opmode {
Position,
Immediate
}
impl From<i32> for Opcode {
fn from(num: i32) -> Self {
let mut x = num;
let mut opcode = Opcode {
inst: (num%100) as u8,
mode: Vec::new()
};
x /= 100; // strip 2 least significant digits
loop {
match x%10 {
0 => opcode.mode.push(Opmode::Position),
1 => opcode.mode.push(Opmode::Immediate),
_ => panic!{"Invalid opmode: {}", x%10}
}
x /= 10;
if x == 0 {break}
}
opcode
}
}
#[allow(dead_code)]
impl Computer {
fn new() -> Self {
let mut mem = vec![0];
let intp = &mut mem[0] as *mut i32;
Computer {mem, intp}
}
fn push(&mut self, val: i32) {
if self.mem[0] == 0 { // we are in init state
self.mem[0] = val
} else {
self.mem.push(val);
}
}
fn set(&mut self, pos: usize, val: i32) {
self.mem[pos] = val;
}
fn compute(&mut self) -> i32 {
// first reset the pointer just to be sure
self.intp = &mut self.mem[0] as *mut i32;
loop {
let opcode: Opcode = self._expect_next(&Opmode::Immediate).into();
match opcode.inst {
1 => self._add(&opcode.mode),
2 => self._mul(&opcode.mode),
3 => self._input(),
4 => self._output(&opcode.mode),
99 => break,
_ => panic!{"Invalid opcode {}", opcode.inst},
}
}
self.mem[0]
}
fn _add(&mut self, modes: &[Opmode]) {
let op1 = self._expect_next(&modes.get(0).unwrap_or(&Opmode::Position));
let op2 = self._expect_next(&modes.get(1).unwrap_or(&Opmode::Position));
let pos = self._expect_next(&Opmode::Immediate) as usize;
self.mem[pos] = op1 + op2;
}
fn _mul(&mut self, modes: &[Opmode]) {
let op1 = self._expect_next(&modes.get(0).unwrap_or(&Opmode::Position));
let op2 = self._expect_next(&modes.get(1).unwrap_or(&Opmode::Position));
let pos = self._expect_next(&Opmode::Immediate) as usize;
self.mem[pos] = op1*op2;
}
fn _input(&mut self) {
let pos = self._expect_next(&Opmode::Immediate) as usize;
let mut input = String::new();
print!{"Input: "};
stdout().flush().unwrap();
stdin().read_line(&mut input).unwrap();
self.mem[pos] = input.trim().parse().expect("Invalid input");
}
fn _output(&mut self, modes: &[Opmode]) {
let op = self._expect_next(&modes.get(0).unwrap_or(&Opmode::Position));
println!("{}", op)
}
fn _next(&mut self) -> Option<i32> {
unsafe{ // Dragons
// overflow check, smart cpu
let lstp = self.mem.last_mut().unwrap() as *mut i32;
if self.intp == lstp.offset(1) {
return None;
}
let op = *self.intp;
self.intp = self.intp.offset(1);
Some(op)
}
}
fn _expect_next(&mut self, mode: &Opmode) -> i32 {
let next = self._next().expect("Exhausted");
match mode {
Opmode::Position => self.mem[next as usize],
Opmode::Immediate => next
}
}
}
impl Clone for Computer {
fn clone(&self) -> Self {
let mut mem = self.mem.clone();
let intp = &mut mem[0] as *mut i32;
Computer { mem, intp }
}
}
fn main() -> Result<(), Box<dyn Error>>{
let input = File::open("input")?;
let reader = BufReader::new(input);
let mut computer = Computer::new();
reader.lines()
.filter_map(Result::ok) // transform into Option and filter
.filter_map(|l| l.parse().ok()) // parse String to i32 transform to Option and filter
.for_each(|i| computer.push(i)); // push instruction to computer
computer.compute();
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn tc1() {
let mut computer = Computer::new();
let mem = vec![1002,4,3,4,33];
mem.iter().for_each(|&n| computer.push(n));
println!{"{:?}", computer}
computer.compute();
println!{"{:?}", computer}
assert_eq!{99, computer.mem[4]}
}
#[test]
fn tc2() {
let mut computer = Computer::new();
let mem = vec![1101,100,-1,4,0];
mem.iter().for_each(|&n| computer.push(n));
println!{"{:?}", computer}
computer.compute();
println!{"{:?}", computer}
assert_eq!{99, computer.mem[4]}
}
}