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 }