advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

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 }