|
|
@@ -0,0 +1,490 @@
|
|
|
+/*
|
|
|
+--- Day 5: Sunny with a Chance of Asteroids ---
|
|
|
+
|
|
|
+You're starting to sweat as the ship makes its way toward Mercury. The Elves suggest that you get
|
|
|
+the air conditioner working by upgrading your ship computer to support the Thermal Environment
|
|
|
+Supervision Terminal.
|
|
|
+
|
|
|
+The Thermal Environment Supervision Terminal (TEST) starts by running a diagnostic program (your
|
|
|
+puzzle input). The TEST diagnostic program will run on your existing Intcode computer after a few
|
|
|
+modifications:
|
|
|
+
|
|
|
+First, you'll need to add two new instructions:
|
|
|
+
|
|
|
+ Opcode 3 takes a single integer as input and saves it to the position given by its only
|
|
|
+ parameter. For example, the instruction 3,50 would take an input value and store it at address
|
|
|
+ 50.
|
|
|
+
|
|
|
+ Opcode 4 outputs the value of its only parameter. For example, the instruction 4,50 would
|
|
|
+ output the value at address 50.
|
|
|
+
|
|
|
+Programs that use these instructions will come with documentation that explains what should be
|
|
|
+connected to the input and output. The program 3,0,4,0,99 outputs whatever it gets as input, then
|
|
|
+halts.
|
|
|
+
|
|
|
+Second, you'll need to add support for parameter modes:
|
|
|
+
|
|
|
+Each parameter of an instruction is handled based on its parameter mode. Right now, your ship
|
|
|
+computer already understands parameter mode 0, position mode, which causes the parameter to be
|
|
|
+interpreted as a position - if the parameter is 50, its value is the value stored at address 50 in
|
|
|
+memory. Until now, all parameters have been in position mode.
|
|
|
+
|
|
|
+Now, your ship computer will also need to handle parameters in mode 1, immediate mode. In immediate
|
|
|
+mode, a parameter is interpreted as a value - if the parameter is 50, its value is simply 50.
|
|
|
+
|
|
|
+Parameter modes are stored in the same value as the instruction's opcode. The opcode is a two-digit
|
|
|
+number based only on the ones and tens digit of the value, that is, the opcode is the rightmost two
|
|
|
+digits of the first value in an instruction. Parameter modes are single digits, one per parameter,
|
|
|
+read right-to-left from the opcode: the first parameter's mode is in the hundreds digit, the second
|
|
|
+parameter's mode is in the thousands digit, the third parameter's mode is in the ten-thousands
|
|
|
+digit, and so on. Any missing modes are 0.
|
|
|
+
|
|
|
+For example, consider the program 1002,4,3,4,33.
|
|
|
+
|
|
|
+The first instruction, 1002,4,3,4, is a multiply instruction - the rightmost two digits of the
|
|
|
+first value, 02, indicate opcode 2, multiplication. Then, going right to left, the parameter modes
|
|
|
+are 0 (hundreds digit), 1 (thousands digit), and 0 (ten-thousands digit, not present and therefore
|
|
|
+zero):
|
|
|
+
|
|
|
+ABCDE
|
|
|
+ 1002
|
|
|
+
|
|
|
+DE - two-digit opcode, 02 == opcode 2
|
|
|
+ C - mode of 1st parameter, 0 == position mode
|
|
|
+ B - mode of 2nd parameter, 1 == immediate mode
|
|
|
+ A - mode of 3rd parameter, 0 == position mode,
|
|
|
+ omitted due to being a leading zero
|
|
|
+
|
|
|
+This instruction multiplies its first two parameters. The first parameter, 4 in position mode,
|
|
|
+works like it did before - its value is the value stored at address 4 (33). The second parameter, 3
|
|
|
+in immediate mode, simply has value 3. The result of this operation, 33 * 3 = 99, is written
|
|
|
+according to the third parameter, 4 in position mode, which also works like it did before - 99 is
|
|
|
+written to address 4.
|
|
|
+
|
|
|
+Parameters that an instruction writes to will never be in immediate mode.
|
|
|
+
|
|
|
+Finally, some notes:
|
|
|
+
|
|
|
+ It is important to remember that the instruction pointer should increase by the number of
|
|
|
+ values in the instruction after the instruction finishes. Because of the new instructions, this
|
|
|
+ amount is no longer always 4.
|
|
|
+
|
|
|
+ Integers can be negative: 1101,100,-1,4,0 is a valid program (find 100 + -1, store the result
|
|
|
+ in position 4).
|
|
|
+
|
|
|
+The TEST diagnostic program will start by requesting from the user the ID of the system to test by
|
|
|
+running an input instruction - provide it 1, the ID for the ship's air conditioner unit.
|
|
|
+
|
|
|
+It will then perform a series of diagnostic tests confirming that various parts of the Intcode
|
|
|
+computer, like parameter modes, function correctly. For each test, it will run an output
|
|
|
+instruction indicating how far the result of the test was from the expected value, where 0 means
|
|
|
+the test was successful. Non-zero outputs mean that a function is not working correctly; check the
|
|
|
+instructions that were run before the output instruction to see which one failed.
|
|
|
+
|
|
|
+Finally, the program will output a diagnostic code and immediately halt. This final output isn't an
|
|
|
+error; an output followed immediately by a halt means the program finished. If all outputs were
|
|
|
+zero except the diagnostic code, the diagnostic program ran successfully.
|
|
|
+
|
|
|
+After providing 1 to the only input instruction and passing all the tests, what diagnostic code
|
|
|
+does the program produce?
|
|
|
+*/
|
|
|
+
|
|
|
+use log::{debug, trace};
|
|
|
+use std::convert::TryFrom;
|
|
|
+use std::io::{stdin, stdout, Write};
|
|
|
+
|
|
|
+use crate::puzzle::options::Options;
|
|
|
+use crate::puzzle::traits::{Create, Solve};
|
|
|
+
|
|
|
+pub struct Puzzle {
|
|
|
+ options: Options,
|
|
|
+ computer: Computer,
|
|
|
+}
|
|
|
+
|
|
|
+impl Solve for Puzzle {
|
|
|
+ fn solve(&self) -> i32 {
|
|
|
+ match self.options.puzzle {
|
|
|
+ 1 => self.solve_p1(),
|
|
|
+ 2 => self.solve_p2(),
|
|
|
+ x => panic!("Unknown puzzle {}", x),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Create for Puzzle {
|
|
|
+ fn new(opt: Options) -> Box<dyn Solve> {
|
|
|
+ Box::new(Self {
|
|
|
+ options: opt,
|
|
|
+ computer: Computer {
|
|
|
+ opcodes: if opt.prompt {
|
|
|
+ Self::prompt_for_opcodes()
|
|
|
+ } else {
|
|
|
+ Self::default_opcodes()
|
|
|
+ },
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Puzzle {
|
|
|
+ fn solve_p1(&self) -> i32 {
|
|
|
+ let result = self.computer.run();
|
|
|
+ match result {
|
|
|
+ Ok(res) => res[0],
|
|
|
+ Err(e) => panic!(e),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fn solve_p2(&self) -> i32 {
|
|
|
+ unimplemented!()
|
|
|
+ }
|
|
|
+
|
|
|
+ fn prompt_for_opcodes() -> Vec<i32> {
|
|
|
+ println!("enter comma-separated values, like given: ");
|
|
|
+ let mut input = String::new();
|
|
|
+
|
|
|
+ match stdin().read_line(&mut input) {
|
|
|
+ Ok(_) => (),
|
|
|
+ Err(e) => panic!("Failed to read input: {}", e),
|
|
|
+ }
|
|
|
+
|
|
|
+ input
|
|
|
+ .split(',')
|
|
|
+ .map(|code| match code.trim().parse::<i32>() {
|
|
|
+ Ok(i) => i,
|
|
|
+ Err(e) => panic!("failed to parse {}: {}", code, e),
|
|
|
+ })
|
|
|
+ .collect()
|
|
|
+ }
|
|
|
+
|
|
|
+ fn default_opcodes() -> Vec<i32> {
|
|
|
+ vec![
|
|
|
+ 3, 225, 1, 225, 6, 6, 1100, 1, 238, 225, 104, 0, 1101, 11, 91, 225, 1002, 121, 77, 224,
|
|
|
+ 101, -6314, 224, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 3, 224, 1, 223, 224, 223,
|
|
|
+ 1102, 74, 62, 225, 1102, 82, 7, 224, 1001, 224, -574, 224, 4, 224, 102, 8, 223, 223,
|
|
|
+ 1001, 224, 3, 224, 1, 224, 223, 223, 1101, 28, 67, 225, 1102, 42, 15, 225, 2, 196, 96,
|
|
|
+ 224, 101, -4446, 224, 224, 4, 224, 102, 8, 223, 223, 101, 6, 224, 224, 1, 223, 224,
|
|
|
+ 223, 1101, 86, 57, 225, 1, 148, 69, 224, 1001, 224, -77, 224, 4, 224, 102, 8, 223, 223,
|
|
|
+ 1001, 224, 2, 224, 1, 223, 224, 223, 1101, 82, 83, 225, 101, 87, 14, 224, 1001, 224,
|
|
|
+ -178, 224, 4, 224, 1002, 223, 8, 223, 101, 7, 224, 224, 1, 223, 224, 223, 1101, 38, 35,
|
|
|
+ 225, 102, 31, 65, 224, 1001, 224, -868, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 5,
|
|
|
+ 224, 1, 223, 224, 223, 1101, 57, 27, 224, 1001, 224, -84, 224, 4, 224, 102, 8, 223,
|
|
|
+ 223, 1001, 224, 7, 224, 1, 223, 224, 223, 1101, 61, 78, 225, 1001, 40, 27, 224, 101,
|
|
|
+ -89, 224, 224, 4, 224, 1002, 223, 8, 223, 1001, 224, 1, 224, 1, 224, 223, 223, 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,
|
|
|
+ 1008, 677, 226, 224, 1002, 223, 2, 223, 1006, 224, 329, 101, 1, 223, 223, 8, 226, 677,
|
|
|
+ 224, 102, 2, 223, 223, 1005, 224, 344, 101, 1, 223, 223, 1107, 226, 677, 224, 102, 2,
|
|
|
+ 223, 223, 1006, 224, 359, 101, 1, 223, 223, 1007, 226, 226, 224, 102, 2, 223, 223,
|
|
|
+ 1006, 224, 374, 101, 1, 223, 223, 7, 677, 677, 224, 102, 2, 223, 223, 1005, 224, 389,
|
|
|
+ 1001, 223, 1, 223, 108, 677, 677, 224, 1002, 223, 2, 223, 1005, 224, 404, 101, 1, 223,
|
|
|
+ 223, 1008, 226, 226, 224, 102, 2, 223, 223, 1005, 224, 419, 1001, 223, 1, 223, 1107,
|
|
|
+ 677, 226, 224, 102, 2, 223, 223, 1005, 224, 434, 1001, 223, 1, 223, 1108, 677, 677,
|
|
|
+ 224, 102, 2, 223, 223, 1006, 224, 449, 1001, 223, 1, 223, 7, 226, 677, 224, 102, 2,
|
|
|
+ 223, 223, 1005, 224, 464, 101, 1, 223, 223, 1008, 677, 677, 224, 102, 2, 223, 223,
|
|
|
+ 1005, 224, 479, 101, 1, 223, 223, 1007, 226, 677, 224, 1002, 223, 2, 223, 1006, 224,
|
|
|
+ 494, 101, 1, 223, 223, 8, 677, 226, 224, 1002, 223, 2, 223, 1005, 224, 509, 101, 1,
|
|
|
+ 223, 223, 1007, 677, 677, 224, 1002, 223, 2, 223, 1006, 224, 524, 101, 1, 223, 223,
|
|
|
+ 107, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 539, 101, 1, 223, 223, 107, 226, 677,
|
|
|
+ 224, 102, 2, 223, 223, 1005, 224, 554, 1001, 223, 1, 223, 7, 677, 226, 224, 102, 2,
|
|
|
+ 223, 223, 1006, 224, 569, 1001, 223, 1, 223, 107, 677, 677, 224, 1002, 223, 2, 223,
|
|
|
+ 1005, 224, 584, 101, 1, 223, 223, 1107, 677, 677, 224, 102, 2, 223, 223, 1005, 224,
|
|
|
+ 599, 101, 1, 223, 223, 1108, 226, 677, 224, 102, 2, 223, 223, 1006, 224, 614, 101, 1,
|
|
|
+ 223, 223, 8, 226, 226, 224, 102, 2, 223, 223, 1006, 224, 629, 101, 1, 223, 223, 108,
|
|
|
+ 226, 677, 224, 102, 2, 223, 223, 1005, 224, 644, 1001, 223, 1, 223, 108, 226, 226, 224,
|
|
|
+ 102, 2, 223, 223, 1005, 224, 659, 101, 1, 223, 223, 1108, 677, 226, 224, 102, 2, 223,
|
|
|
+ 223, 1006, 224, 674, 1001, 223, 1, 223, 4, 223, 99, 226,
|
|
|
+ ]
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug, Copy, Clone)]
|
|
|
+enum OpMode {
|
|
|
+ Position = 0,
|
|
|
+ Immediate,
|
|
|
+}
|
|
|
+
|
|
|
+impl TryFrom<i32> for OpMode {
|
|
|
+ type Error = i32;
|
|
|
+
|
|
|
+ fn try_from(v: i32) -> Result<Self, Self::Error> {
|
|
|
+ trace!("try converting {} to enum OpMode", v);
|
|
|
+
|
|
|
+ match v {
|
|
|
+ x if x == OpMode::Position as i32 => Ok(OpMode::Position),
|
|
|
+ x if x == OpMode::Immediate as i32 => Ok(OpMode::Immediate),
|
|
|
+ _ => Err(v),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+enum OpCode {
|
|
|
+ Add = 1,
|
|
|
+ Mult,
|
|
|
+ Input,
|
|
|
+ Output,
|
|
|
+ Halt = 99,
|
|
|
+}
|
|
|
+
|
|
|
+impl TryFrom<i32> for OpCode {
|
|
|
+ type Error = i32;
|
|
|
+
|
|
|
+ fn try_from(v: i32) -> Result<Self, Self::Error> {
|
|
|
+ trace!("try converting {} to enum OpCode", v);
|
|
|
+
|
|
|
+ match v {
|
|
|
+ x if x == OpCode::Add as i32 => Ok(OpCode::Add),
|
|
|
+ x if x == OpCode::Mult as i32 => Ok(OpCode::Mult),
|
|
|
+ x if x == OpCode::Input as i32 => Ok(OpCode::Input),
|
|
|
+ x if x == OpCode::Output as i32 => Ok(OpCode::Output),
|
|
|
+ x if x == OpCode::Halt as i32 => Ok(OpCode::Halt),
|
|
|
+ _ => Err(v),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl OpCode {
|
|
|
+ fn num_args(&self) -> i32 {
|
|
|
+ match self {
|
|
|
+ OpCode::Add => 4,
|
|
|
+ OpCode::Mult => 4,
|
|
|
+ OpCode::Input => 2,
|
|
|
+ OpCode::Output => 2,
|
|
|
+ OpCode::Halt => 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[derive(Debug)]
|
|
|
+struct Operation<'a> {
|
|
|
+ opcode: OpCode,
|
|
|
+ opcodes: &'a mut Vec<i32>,
|
|
|
+ param_1_mode: OpMode,
|
|
|
+ param_2_mode: OpMode,
|
|
|
+ param_3_mode: OpMode,
|
|
|
+}
|
|
|
+
|
|
|
+type OperationParseError = String;
|
|
|
+
|
|
|
+impl Operation<'_> {
|
|
|
+ fn new(opcodes: &mut Vec<i32>, index: usize) -> Result<Operation, OperationParseError> {
|
|
|
+ let mut opcode = opcodes[index];
|
|
|
+ debug!("try converting {} to Operation", opcode);
|
|
|
+
|
|
|
+ let operation = match OpCode::try_from(opcode % 100) {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => return Err(format!("Unknown opcode {}", e)),
|
|
|
+ };
|
|
|
+ opcode /= 100;
|
|
|
+ trace!("operation: {:?}, opcode: {}", operation, opcode);
|
|
|
+
|
|
|
+ let param_1_mode = match OpMode::try_from(opcode % 10) {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => return Err(format!("unknown operation mode {}", e)),
|
|
|
+ };
|
|
|
+ opcode /= 10;
|
|
|
+ trace!("param_1_mode: {:?}, opcode: {}", param_1_mode, opcode);
|
|
|
+
|
|
|
+ let param_2_mode = match OpMode::try_from(opcode % 10) {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => return Err(format!("unknown operation mode {}", e)),
|
|
|
+ };
|
|
|
+ opcode /= 10;
|
|
|
+ trace!("param_2_mode: {:?}, opcode: {}", param_2_mode, opcode);
|
|
|
+
|
|
|
+ let param_3_mode = match OpMode::try_from(opcode % 10) {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => return Err(format!("unknown operation mode {}", e)),
|
|
|
+ };
|
|
|
+ trace!("param_3_mode: {:?}", param_2_mode);
|
|
|
+
|
|
|
+ Ok(Operation {
|
|
|
+ opcode: operation,
|
|
|
+ opcodes: opcodes,
|
|
|
+ param_1_mode,
|
|
|
+ param_2_mode,
|
|
|
+ param_3_mode,
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ fn apply(&mut self, index: usize) -> Result<Option<usize>, String> {
|
|
|
+ debug!("applying {:?} at index {}", self, index);
|
|
|
+
|
|
|
+ match &self.opcode {
|
|
|
+ OpCode::Add => {
|
|
|
+ let arg1 = self.value_from(self.param_1_mode, index + 1);
|
|
|
+ let arg2 = self.value_from(self.param_2_mode, index + 2);
|
|
|
+ self.value_to(self.param_3_mode, index + 3, arg1 + arg2);
|
|
|
+ }
|
|
|
+ OpCode::Mult => {
|
|
|
+ let arg1 = self.value_from(self.param_1_mode, index + 1);
|
|
|
+ let arg2 = self.value_from(self.param_2_mode, index + 2);
|
|
|
+ self.value_to(self.param_3_mode, index + 3, arg1 * arg2);
|
|
|
+ }
|
|
|
+ OpCode::Input => {
|
|
|
+ print!("Input: ");
|
|
|
+ stdout().flush().unwrap();
|
|
|
+
|
|
|
+ let input = &mut String::new();
|
|
|
+ let _ = stdin().read_line(input);
|
|
|
+ let num: i32 = match input.trim().parse() {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => return Err(format!("failed to decode input {}: {}", input, e)),
|
|
|
+ };
|
|
|
+ self.value_to(self.param_1_mode, index + 1, num);
|
|
|
+ }
|
|
|
+ OpCode::Output => {
|
|
|
+ let arg1 = self.value_from(self.param_1_mode, index + 1);
|
|
|
+ println!("Output: {}", arg1);
|
|
|
+ }
|
|
|
+ OpCode::Halt => return Ok(None),
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(Some(self.opcode.num_args() as usize))
|
|
|
+ }
|
|
|
+
|
|
|
+ fn value_from(&mut self, opmode: OpMode, index: usize) -> i32 {
|
|
|
+ debug!("GET via OpMode {:?} from index {}", opmode, index);
|
|
|
+
|
|
|
+ match opmode {
|
|
|
+ OpMode::Position => {
|
|
|
+ let val = self.opcodes[self.opcodes[index] as usize];
|
|
|
+ trace!("retrieving position {}: {}", index, val);
|
|
|
+ val
|
|
|
+ }
|
|
|
+ OpMode::Immediate => {
|
|
|
+ let val = self.opcodes[index];
|
|
|
+ trace!("directly using position {}: {}", index, val);
|
|
|
+ val
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fn value_to(&mut self, opmode: OpMode, index: usize, value: i32) {
|
|
|
+ debug!("SET {} via OpMode {:?} to index {}", value, opmode, index);
|
|
|
+
|
|
|
+ match opmode {
|
|
|
+ OpMode::Position => {
|
|
|
+ let pos = self.opcodes[index] as usize;
|
|
|
+ trace!(
|
|
|
+ "storing value {} to position {}: {}",
|
|
|
+ value,
|
|
|
+ pos,
|
|
|
+ self.opcodes[index]
|
|
|
+ );
|
|
|
+ self.opcodes[pos] = value
|
|
|
+ }
|
|
|
+ OpMode::Immediate => {
|
|
|
+ trace!(
|
|
|
+ "immediately storing value {} to position {}: {}",
|
|
|
+ value,
|
|
|
+ index,
|
|
|
+ self.opcodes[index]
|
|
|
+ );
|
|
|
+ self.opcodes[index] = value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct Computer {
|
|
|
+ opcodes: Vec<i32>,
|
|
|
+}
|
|
|
+
|
|
|
+impl Computer {
|
|
|
+ fn run(&self) -> Result<Vec<i32>, String> {
|
|
|
+ let mut index: usize = 0;
|
|
|
+ let ref mut opcodes = self.opcodes.clone();
|
|
|
+
|
|
|
+ while index < opcodes.len() {
|
|
|
+ let mut op = match Operation::new(opcodes, index) {
|
|
|
+ Ok(x) => x,
|
|
|
+ Err(e) => {
|
|
|
+ return Err(format!(
|
|
|
+ "failed to parse operation '{}': {}",
|
|
|
+ opcodes[index], e
|
|
|
+ ))
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ match op.apply(index) {
|
|
|
+ Ok(Some(i)) => index += i,
|
|
|
+ Ok(None) => break,
|
|
|
+ Err(e) => return Err(e),
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ debug!("resulting opcodes: {:?}", opcodes);
|
|
|
+
|
|
|
+ Ok(opcodes.to_owned())
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#[cfg(test)]
|
|
|
+mod puzzle_1 {
|
|
|
+ use super::Computer;
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn opcodes_sample_1() {
|
|
|
+ assert_eq!(
|
|
|
+ Computer {
|
|
|
+ opcodes: vec![1002, 4, 3, 4, 33],
|
|
|
+ }
|
|
|
+ .run()
|
|
|
+ .unwrap(),
|
|
|
+ vec![1002, 4, 3, 4, 99]
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn opcodes_sample_2() {
|
|
|
+ assert_eq!(
|
|
|
+ Computer {
|
|
|
+ opcodes: vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]
|
|
|
+ }
|
|
|
+ .run()
|
|
|
+ .unwrap(),
|
|
|
+ vec![3500, 9, 10, 70, 2, 3, 11, 0, 99, 30, 40, 50]
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn opcodes_sample_3() {
|
|
|
+ assert_eq!(
|
|
|
+ Computer {
|
|
|
+ opcodes: vec![10001, 1, 1, 0, 99]
|
|
|
+ }
|
|
|
+ .run()
|
|
|
+ .unwrap(),
|
|
|
+ vec![10001, 1, 1, 2, 99]
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn opcodes_sample_4() {
|
|
|
+ assert_eq!(
|
|
|
+ Computer {
|
|
|
+ opcodes: vec![1, 0, 0, 0, 99]
|
|
|
+ }
|
|
|
+ .run()
|
|
|
+ .unwrap(),
|
|
|
+ vec![2, 0, 0, 0, 99]
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ #[test]
|
|
|
+ fn opcodes_sample_5() {
|
|
|
+ assert_eq!(
|
|
|
+ Computer {
|
|
|
+ opcodes: vec![3, 0, 4, 0, 99]
|
|
|
+ }
|
|
|
+ .run()
|
|
|
+ .unwrap(),
|
|
|
+ vec![2, 0, 0, 0, 99]
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|