Compare commits

..

2 commits

Author SHA1 Message Date
dece 5d09932b11 Day 8 in Rust 2020-12-08 19:45:26 +01:00
dece 1ebb5f738e Day 8 2020-12-08 19:45:21 +01:00
2 changed files with 143 additions and 0 deletions

65
2020/day8.py Normal file
View file

@ -0,0 +1,65 @@
def main():
with open("day8.txt", "rt") as f:
lines = [line.rstrip() for line in f.readlines()]
# Part 1
visited = set()
vm = Vm(lines)
while vm.ip not in visited:
visited.add(vm.ip)
vm.step()
print("Acc after revisiting op:", vm.acc)
# Part 2
jmps = reversed([i for i, inst in enumerate(vm.code) if inst[0] == "jmp"])
for i in jmps:
vm.reset()
orig_jmp = vm.code[i]
vm.code[i] = ["nop", orig_jmp[1]]
if not vm.does_loop():
print(vm.acc)
return
# No need to try for nops apparently!
class Vm:
def __init__(self, code):
self.text = code
self.reset()
def reset(self):
self.code = self.parse_code(self.text)
self.ip = 0
self.acc = 0
def step(self):
inst = self.code[self.ip]
if inst[0] == "nop":
pass
elif inst[0] == "jmp":
self.ip += int(inst[1])
return
elif inst[0] == "acc":
self.acc += int(inst[1])
self.ip += 1
def does_loop(self):
visited = set()
while self.ip < len(self.code):
visited.add(self.ip)
self.step()
if self.ip in visited:
return True
return False
@staticmethod
def parse_code(code):
ops = []
for line in code:
ops.append(line.split())
return ops
if __name__ == "__main__":
main()

78
2020/day8.rs Normal file
View file

@ -0,0 +1,78 @@
use std::collections;
use std::fs;
use std::io::{self, BufRead};
#[derive(Clone)]
enum Op {
Nop(i64),
Jmp(i64),
Acc(i64),
}
struct Cpu {
ip: u64,
acc: i64,
}
impl Cpu {
fn step(&mut self, code: &Vec<Op>) {
match code[self.ip as usize] {
Op::Nop(_) => {},
Op::Jmp(i) => { self.ip = (self.ip as i64 + i) as u64; return }
Op::Acc(i) => { self.acc += i }
}
self.ip += 1;
}
}
fn main() {
let file = fs::File::open("day8.txt").unwrap();
let lines: Vec<String> = io::BufReader::new(file).lines().map(|r| r.unwrap()).collect();
let mut code: Vec<Op> = lines.iter().map(|line| {
let inst: Vec<&str> = line.splitn(2, " ").collect();
match inst[0] {
"nop" => Op::Nop(inst[1].parse::<i64>().unwrap()),
"jmp" => Op::Jmp(inst[1].parse::<i64>().unwrap()),
"acc" => Op::Acc(inst[1].parse::<i64>().unwrap()),
unk => panic!("Unknown op '{}'", unk),
}
}).collect();
// Part 1.
let mut visited: collections::HashSet<u64> = collections::HashSet::new();
let mut cpu = Cpu { ip: 0, acc: 0 };
while !visited.contains(&cpu.ip) {
visited.insert(cpu.ip);
cpu.step(&code);
}
println!("Acc after first revisit: {}.", cpu.acc);
// Part 2.
for i in 0..code.len() {
match &code[i] {
Op::Jmp(val) => {
let op_backup = code[i].clone();
code[i] = Op::Nop(*val);
if let Some(acc) = run(&code) {
println!("Acc after non-looping execution: {}.", acc);
break
}
code[i] = op_backup;
}
_ => {}
}
}
}
fn run(code: &Vec<Op>) -> Option<i64> {
let mut visited: collections::HashSet<u64> = collections::HashSet::new();
let mut cpu = Cpu { ip: 0, acc: 0 };
while cpu.ip < code.len() as u64 {
visited.insert(cpu.ip);
cpu.step(&code);
if visited.contains(&cpu.ip) {
return None
}
}
Some(cpu.acc)
}