2 files changed
+55
-4
No files matched your search
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
2025
|
2025
|
||||||
0
|
2001
|
||||||
+54
-3
@@ -4,7 +4,7 @@ use crate::utils;
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum Instruction {
|
enum Instruction {
|
||||||
Acc(i32),
|
Acc(i32),
|
||||||
Jmp(i32),
|
Jmp(i32),
|
||||||
@@ -115,6 +115,58 @@ impl Console {
|
|||||||
while self.step() == Status::Running {}
|
while self.step() == Status::Running {}
|
||||||
self.accumulator
|
self.accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn repair(&mut self) -> Result<i32> {
|
||||||
|
// first run() so we can find every instruction executed
|
||||||
|
// since we know we only have to flip one instruction (jmp <=> nop), then
|
||||||
|
// we're guaranteed to already hit it on this first run
|
||||||
|
self.run();
|
||||||
|
|
||||||
|
// now that we've run once, find the candidate instructions
|
||||||
|
let candidate_indices: Vec<usize> = self
|
||||||
|
.hits
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter(|(_, hits)| **hits > 0) // filter only instructions we hit
|
||||||
|
.map(|(i, _)| i) // map just the index
|
||||||
|
.filter(|i| match self.program[*i as usize] {
|
||||||
|
// filter instructions we can modify
|
||||||
|
Instruction::Jmp(_) => true,
|
||||||
|
Instruction::Nop(n) => {
|
||||||
|
if n != 0 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// now test each of these candidates by exchanging jmp <=> nop
|
||||||
|
for i in candidate_indices {
|
||||||
|
// save original instruction
|
||||||
|
let original_instruction = self.program[i].clone();
|
||||||
|
|
||||||
|
// exchange jmp<=>nop
|
||||||
|
self.program[i] = match &self.program[i] {
|
||||||
|
Instruction::Jmp(n) => Instruction::Nop(*n),
|
||||||
|
Instruction::Nop(n) => Instruction::Jmp(*n),
|
||||||
|
_ => unreachable!("invalid candidate instruction"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// run program
|
||||||
|
self.run();
|
||||||
|
if self.get_run_state() == Status::Completed {
|
||||||
|
return Ok(self.accumulator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// that didn't work, restore the original instruction
|
||||||
|
self.program[i] = original_instruction;
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(anyhow!("no result found"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run() -> Result<(i32, i32)> {
|
pub fn run() -> Result<(i32, i32)> {
|
||||||
@@ -122,10 +174,9 @@ pub fn run() -> Result<(i32, i32)> {
|
|||||||
let answers = utils::read_i64s("data/output-08.txt")?;
|
let answers = utils::read_i64s("data/output-08.txt")?;
|
||||||
|
|
||||||
let mut console = Console::from_str(&data)?;
|
let mut console = Console::from_str(&data)?;
|
||||||
println!("{:?}", console);
|
|
||||||
|
|
||||||
let p1 = console.run();
|
let p1 = console.run();
|
||||||
let p2 = 0;
|
let p2 = console.repair()?;
|
||||||
|
|
||||||
assert_eq!(p1, answers[0] as i32);
|
assert_eq!(p1, answers[0] as i32);
|
||||||
assert_eq!(p2, answers[1] as i32);
|
assert_eq!(p2, answers[1] as i32);
|
||||||
|
|||||||
Reference in new issue
Block a user