diff --git a/README.md b/README.md index c5f65b1..654a6f8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ ## Days + ## License I don't expect this to be used in any relevant capacity. Hence, this code is diff --git a/day5/1/Cargo.toml b/day5/1/Cargo.toml new file mode 100644 index 0000000..650d691 --- /dev/null +++ b/day5/1/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "intcode" +version = "0.1.0" +authors = ["Armin Friedl "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day5/1/input b/day5/1/input new file mode 100644 index 0000000..d4854c2 --- /dev/null +++ b/day5/1/input @@ -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 \ No newline at end of file diff --git a/day5/1/src/main.rs b/day5/1/src/main.rs new file mode 100644 index 0000000..026134c --- /dev/null +++ b/day5/1/src/main.rs @@ -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, + intp: *mut i32, // here will be dragons +} + +struct Opcode { + inst: u8, + mode: Vec, +} + +enum Opmode { + Position, + Immediate +} + +impl From 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 { + 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>{ + 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]} + } +}