day-09.rs (5248B)
1 use std::collections::HashMap; 2 type Op = i128; 3 4 fn main() { 5 let input = std::fs::read_to_string("input.txt") 6 .unwrap() 7 .trim() 8 .split(",") 9 .map(|op| op.parse::<Op>().unwrap()) 10 .collect::<Vec<Op>>(); 11 println!("Rust:"); 12 println!("Part 1: {}", part_1(&input)); 13 println!("Part 2: {}", part_2(&input)); 14 } 15 16 fn computer(program: &Vec<Op>, input: Op) -> Vec<Op> { 17 // Use a hash table for more memory. 18 let mut program = program 19 .iter() 20 .enumerate() 21 .map(|(idx, &op)| (idx, op)) 22 .collect::<HashMap<usize, Op>>(); 23 let mut output = vec![]; 24 let mut pc = 0; 25 let mut relative_base = 0; 26 27 let get_param = |loc: usize, mode, program: &HashMap<usize, Op>, relative_base| -> Op { 28 match mode { 29 // Position mode. 30 0 => *program.get(&(program[&loc] as usize)).unwrap_or(&0), 31 // Immediate mode. 32 1 => program[&loc], 33 // Relative mode. 34 2 => *program 35 .get(&((relative_base + program[&loc]) as usize)) 36 .unwrap_or(&0), 37 _ => panic!(), 38 } 39 }; 40 41 let get_res_loc = 42 |loc: usize, mode, program: &HashMap<usize, Op>, relative_base: i128| -> usize { 43 match mode { 44 // Position mode. 45 0 => program[&loc] as usize, 46 // Immediate mode is banned. 47 // Relative mode. 48 2 => (relative_base + program[&loc]) as usize, 49 _ => panic!(), 50 } 51 }; 52 53 loop { 54 let op_code = program[&pc] % 100; 55 let mode_1 = (program[&pc] % 1000) / 100; 56 let mode_2 = (program[&pc] % 10000) / 1000; 57 let mode_3 = (program[&pc] % 100000) / 10000; 58 // Third parameter is location to write to, and will never be immediate 59 // mode. 60 match op_code { 61 1 => { 62 let res_loc = get_res_loc(pc + 3, mode_3, &program, relative_base); 63 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 64 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 65 *program.entry(res_loc).or_default() = param_1 + param_2; 66 pc += 4; 67 } 68 2 => { 69 let res_loc = get_res_loc(pc + 3, mode_3, &program, relative_base); 70 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 71 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 72 *program.entry(res_loc as usize).or_default() = param_1 * param_2; 73 pc += 4; 74 } 75 3 => { 76 let res_loc = get_res_loc(pc + 1, mode_1, &program, relative_base); 77 *program.entry(res_loc as usize).or_default() = input; 78 pc += 2; 79 } 80 4 => { 81 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 82 output.push(param_1); 83 pc += 2; 84 } 85 5 => { 86 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 87 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 88 if param_1 != 0 { 89 pc = param_2 as usize; 90 } else { 91 pc += 3; 92 } 93 } 94 6 => { 95 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 96 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 97 if param_1 == 0 { 98 pc = param_2 as usize; 99 } else { 100 pc += 3; 101 } 102 } 103 7 => { 104 let res_loc = get_res_loc(pc + 3, mode_3, &program, relative_base); 105 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 106 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 107 *program.entry(res_loc as usize).or_default() = 108 if param_1 < param_2 { 1 } else { 0 }; 109 pc += 4; 110 } 111 8 => { 112 let res_loc = get_res_loc(pc + 3, mode_3, &program, relative_base); 113 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 114 let param_2 = get_param(pc + 2, mode_2, &program, relative_base); 115 *program.entry(res_loc as usize).or_default() = 116 if param_1 == param_2 { 1 } else { 0 }; 117 pc += 4; 118 } 119 9 => { 120 let param_1 = get_param(pc + 1, mode_1, &program, relative_base); 121 relative_base += param_1; 122 pc += 2; 123 } 124 99 => { 125 break; 126 } 127 _ => { 128 println!("Unknown op {}", op_code); 129 println!("{}", program[&pc]); 130 panic!(); 131 } 132 } 133 } 134 135 output 136 } 137 138 fn part_1(input: &Vec<Op>) -> i128 { 139 let output = computer(input, 1); 140 *output.last().unwrap() 141 } 142 143 fn part_2(input: &Vec<Op>) -> i128 { 144 let output = computer(input, 2); 145 *output.last().unwrap() 146 }