diff options
| -rw-r--r-- | input9 | 1 | ||||
| -rw-r--r-- | src/main.rs | 144 |
2 files changed, 106 insertions, 39 deletions
@@ -0,0 +1 @@ +1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1102,3,1,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,902,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1101,309,0,1024,1101,0,24,1002,1102,388,1,1029,1102,1,21,1019,1101,0,33,1015,1102,1,304,1025,1101,344,0,1027,1101,25,0,1003,1102,1,1,1021,1101,29,0,1012,1101,0,23,1005,1102,1,32,1007,1102,38,1,1000,1101,30,0,1016,1102,1,347,1026,1101,0,26,1010,1101,0,39,1004,1102,1,36,1011,1101,0,393,1028,1101,0,37,1013,1101,0,35,1008,1101,34,0,1001,1101,0,495,1022,1102,1,28,1018,1101,0,0,1020,1102,1,22,1006,1101,488,0,1023,1102,31,1,1009,1102,1,20,1017,1101,0,27,1014,109,10,21102,40,1,4,1008,1014,37,63,1005,63,205,1001,64,1,64,1106,0,207,4,187,1002,64,2,64,109,-18,1207,8,37,63,1005,63,227,1001,64,1,64,1106,0,229,4,213,1002,64,2,64,109,17,1207,-7,25,63,1005,63,247,4,235,1106,0,251,1001,64,1,64,1002,64,2,64,109,-8,1202,6,1,63,1008,63,29,63,1005,63,275,1001,64,1,64,1106,0,277,4,257,1002,64,2,64,109,25,1205,-6,293,1001,64,1,64,1105,1,295,4,283,1002,64,2,64,109,-4,2105,1,2,4,301,1106,0,313,1001,64,1,64,1002,64,2,64,109,-9,1208,-4,31,63,1005,63,335,4,319,1001,64,1,64,1105,1,335,1002,64,2,64,109,16,2106,0,-2,1106,0,353,4,341,1001,64,1,64,1002,64,2,64,109,-13,2102,1,-8,63,1008,63,38,63,1005,63,373,1105,1,379,4,359,1001,64,1,64,1002,64,2,64,109,9,2106,0,3,4,385,1105,1,397,1001,64,1,64,1002,64,2,64,109,-11,21107,41,42,0,1005,1014,415,4,403,1106,0,419,1001,64,1,64,1002,64,2,64,109,14,1206,-7,431,1106,0,437,4,425,1001,64,1,64,1002,64,2,64,109,-23,2107,37,-5,63,1005,63,455,4,443,1105,1,459,1001,64,1,64,1002,64,2,64,109,10,21107,42,41,-2,1005,1013,475,1105,1,481,4,465,1001,64,1,64,1002,64,2,64,2105,1,8,1001,64,1,64,1106,0,497,4,485,1002,64,2,64,109,-6,21108,43,41,8,1005,1017,517,1001,64,1,64,1106,0,519,4,503,1002,64,2,64,109,5,2101,0,-9,63,1008,63,23,63,1005,63,541,4,525,1106,0,545,1001,64,1,64,1002,64,2,64,109,-13,1201,5,0,63,1008,63,20,63,1005,63,565,1105,1,571,4,551,1001,64,1,64,1002,64,2,64,109,16,1205,4,589,4,577,1001,64,1,64,1106,0,589,1002,64,2,64,109,-16,1202,4,1,63,1008,63,23,63,1005,63,615,4,595,1001,64,1,64,1106,0,615,1002,64,2,64,109,1,2101,0,6,63,1008,63,33,63,1005,63,639,1001,64,1,64,1105,1,641,4,621,1002,64,2,64,109,8,21101,44,0,8,1008,1018,44,63,1005,63,667,4,647,1001,64,1,64,1105,1,667,1002,64,2,64,109,-7,1201,1,0,63,1008,63,39,63,1005,63,689,4,673,1106,0,693,1001,64,1,64,1002,64,2,64,109,7,2102,1,-8,63,1008,63,24,63,1005,63,715,4,699,1105,1,719,1001,64,1,64,1002,64,2,64,109,5,2108,34,-7,63,1005,63,739,1001,64,1,64,1105,1,741,4,725,1002,64,2,64,109,-22,2108,25,10,63,1005,63,763,4,747,1001,64,1,64,1106,0,763,1002,64,2,64,109,31,1206,-4,781,4,769,1001,64,1,64,1105,1,781,1002,64,2,64,109,-10,21101,45,0,5,1008,1019,47,63,1005,63,805,1001,64,1,64,1105,1,807,4,787,1002,64,2,64,109,2,21108,46,46,-3,1005,1013,825,4,813,1106,0,829,1001,64,1,64,1002,64,2,64,109,-22,2107,40,10,63,1005,63,845,1105,1,851,4,835,1001,64,1,64,1002,64,2,64,109,17,1208,-7,36,63,1005,63,871,1001,64,1,64,1105,1,873,4,857,1002,64,2,64,109,16,21102,47,1,-9,1008,1018,47,63,1005,63,899,4,879,1001,64,1,64,1106,0,899,4,64,99,21102,1,27,1,21101,0,913,0,1105,1,920,21201,1,39657,1,204,1,99,109,3,1207,-2,3,63,1005,63,962,21201,-2,-1,1,21102,1,940,0,1105,1,920,21201,1,0,-1,21201,-2,-3,1,21101,955,0,0,1105,1,920,22201,1,-1,-2,1106,0,966,21202,-2,1,-2,109,-3,2105,1,0 diff --git a/src/main.rs b/src/main.rs index 53060ce..ce5ce0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -167,32 +167,56 @@ enum ProgramState { struct IntComputer { ip : usize, - mem : Vec<i32>, - input : VecDeque<i32>, - output : VecDeque<i32>, + mem : Vec<isize>, + base_address : isize, + input : VecDeque<isize>, + output : VecDeque<isize>, suspend_on_output : bool, } impl IntComputer { - fn new(program : &[i32]) -> IntComputer { + fn new(program : &[isize]) -> IntComputer { IntComputer { ip : 0, mem : program.to_vec(), + base_address : 0, input : VecDeque::new(), output : VecDeque::new(), suspend_on_output : false, } } - fn get_operands(&self, inputs : &[i32], mode : i32) -> Vec<i32> { + fn read_mem(&mut self, i : usize) -> isize { + if i >= self.mem.len() { + self.mem.resize(i+1, 0); + } + self.mem[i] + } + + fn write_mem(&mut self, i : isize, val : isize, mode : isize) { + let pos = match mode { + 0 => i, + 1 => panic!("writing not supported in immediate mode"), + 2 => self.base_address + i, + _ => panic!("unimplemented mode") + } as usize; + if pos >= self.mem.len() { + self.mem.resize(pos+1, 0); + } + self.mem[pos] = val; + } + + fn get_operands(&mut self, count : usize, mode : isize) -> Vec<isize> { + let inputs = self.mem[self.ip+1..=self.ip+count].to_vec(); let mut tmp = mode; let mut ops = Vec::new(); for i in inputs { let m = tmp % 10; tmp /= 10; match m { - 0 => ops.push(self.mem[*i as usize]), - 1 => ops.push(*i), + 0 => ops.push(self.read_mem(i as usize)), + 1 => ops.push(i), + 2 => ops.push(self.read_mem((self.base_address + i) as usize)), _ => panic!("invalid mode") } } @@ -215,24 +239,25 @@ impl IntComputer { match opcode { 1 => { /* add */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); - let dst = self.mem[self.ip+3] as usize; - self.mem[dst] = ops[0] + ops[1]; + let ops = self.get_operands(2, mode); + let dst = self.mem[self.ip+3] as isize; + self.write_mem(dst, ops[0] + ops[1], mode/100); self.ip += 4; } 2 => { /* multiply */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); - let dst = self.mem[self.ip+3] as usize; - self.mem[dst] = ops[0] * ops[1]; + let ops = self.get_operands(2, mode); + let dst = self.mem[self.ip+3] as isize; + self.write_mem(dst, ops[0] * ops[1], mode/100); self.ip += 4; } 3 => { /* read stdin */ - let dst = self.mem[self.ip+1] as usize; - self.mem[dst] = self.input.pop_front().expect("not enough input available"); + let dst = self.mem[self.ip+1] as isize; + let input = self.input.pop_front().expect("not enough input available"); + self.write_mem(dst, input, mode); self.ip += 2; } 4 => { /* write stdout */ - let ops = self.get_operands(&[self.mem[self.ip+1]], mode); + let ops = self.get_operands(1, mode); self.output.push_back(ops[0]); self.ip += 2; if self.suspend_on_output { @@ -240,7 +265,7 @@ impl IntComputer { } } 5 => { /* jump-if-true */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); + let ops = self.get_operands(2, mode); if ops[0] != 0 { self.ip = ops[1] as usize; } else { @@ -248,7 +273,7 @@ impl IntComputer { } } 6 => { /* jump-if-false */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); + let ops = self.get_operands(2, mode); if ops[0] == 0 { self.ip = ops[1] as usize; } else { @@ -256,25 +281,30 @@ impl IntComputer { } } 7 => { /* less-than */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); - let dst = self.mem[self.ip+3] as usize; + let ops = self.get_operands(2, mode); + let dst = self.mem[self.ip+3] as isize; if ops[0] < ops[1] { - self.mem[dst] = 1; + self.write_mem(dst, 1, mode/100); } else { - self.mem[dst] = 0; + self.write_mem(dst, 0, mode/100); } self.ip += 4; } 8 => { /* equals */ - let ops = self.get_operands(&self.mem[self.ip+1..=self.ip+2], mode); - let dst = self.mem[self.ip+3] as usize; + let ops = self.get_operands(2, mode); + let dst = self.mem[self.ip+3] as isize; if ops[0] == ops[1] { - self.mem[dst] = 1; + self.write_mem(dst, 1, mode/100); } else { - self.mem[dst] = 0; + self.write_mem(dst, 0, mode/100); } self.ip += 4; } + 9 => { /* adjust relative base */ + let ops = self.get_operands(1, mode); + self.base_address += ops[0]; + self.ip += 2; + } 99 => return ProgramState::HALTED, _ => panic!("invalid opcode") } @@ -286,9 +316,9 @@ impl IntComputer { fn day2() { let input = read_file("input2"); let input = input.trim_end(); - let mut program : Vec<i32> = input.split(',') - .map(|x| x.parse::<i32>().unwrap()) - .collect(); + let mut program : Vec<isize> = input.split(',') + .map(|x| x.parse::<isize>().unwrap()) + .collect(); program[1] = 12; program[2] = 2; @@ -462,9 +492,9 @@ fn day4() { fn day5() { let input = read_file("input5"); let input = input.trim_end(); - let program : Vec<i32> = input.split(',') - .map(|x| x.parse::<i32>().unwrap()) - .collect(); + let program : Vec<isize> = input.split(',') + .map(|x| x.parse::<isize>().unwrap()) + .collect(); let mut computer = IntComputer::new(&program); computer.input.push_back(1); computer.run_program(); @@ -492,7 +522,7 @@ fn day6() { println!("6b: {}", orbit_map.count_transfers(orbit_map.map["YOU"], orbit_map.map["SAN"])); } -fn permutations(elements : Vec<i32>) -> Vec<Vec<i32>> { +fn permutations(elements : Vec<isize>) -> Vec<Vec<isize>> { let mut result = Vec::new(); if elements.len() == 1 { result.push(elements); @@ -510,7 +540,7 @@ fn permutations(elements : Vec<i32>) -> Vec<Vec<i32>> { result } -fn max_thruster_signal(program : &[i32]) -> i32 { +fn max_thruster_signal(program : &[isize]) -> isize { let phase_settings = permutations(vec![0, 1, 2, 3, 4]); let mut signals = Vec::new(); @@ -529,7 +559,7 @@ fn max_thruster_signal(program : &[i32]) -> i32 { *signals.iter().max().unwrap() } -fn max_thruster_signal_feedback(program : &[i32]) -> i32 { +fn max_thruster_signal_feedback(program : &[isize]) -> isize { let phase_settings = permutations(vec![5, 6, 7, 8, 9]); let mut signals = Vec::new(); @@ -566,9 +596,9 @@ fn max_thruster_signal_feedback(program : &[i32]) -> i32 { fn day7() { let input = read_file("input7"); let input = input.trim_end(); - let program : Vec<i32> = input.split(',') - .map(|x| x.parse::<i32>().unwrap()) - .collect(); + let program : Vec<isize> = input.split(',') + .map(|x| x.parse::<isize>().unwrap()) + .collect(); println!("7a: {}", max_thruster_signal(&program)); @@ -621,8 +651,26 @@ fn day8() { } } +fn day9() { + let input = read_file("input9"); + let input = input.trim_end(); + let program : Vec<isize> = input.split(',') + .map(|x| x.parse::<isize>().unwrap()) + .collect(); + + let mut computer = IntComputer::new(&program); + computer.input.push_back(1); + computer.run_program(); + println!("9a: {}", computer.output[0]); + + let mut computer = IntComputer::new(&program); + computer.input.push_back(2); + computer.run_program(); + println!("9b: {}", computer.output[0]); +} + fn main() { - day8(); + day9(); } #[cfg(test)] @@ -733,4 +781,22 @@ mod tests { let program = vec![3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10]; assert_eq!(max_thruster_signal_feedback(&program), 18216); } + + #[test] + fn test_day9() { + let program = vec![109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99]; + let mut computer = IntComputer::new(&program); + computer.run_program(); + assert!(computer.output.iter().eq(program.iter())); + + let program = vec![1102,34915192,34915192,7,4,7,99,0]; + let mut computer = IntComputer::new(&program); + computer.run_program(); + assert_eq!(computer.output[0], 1219070632396864); + + let program = vec![104,1125899906842624,99]; + let mut computer = IntComputer::new(&program); + computer.run_program(); + assert_eq!(computer.output[0], 1125899906842624); + } } |
