diff options
author | Jesse Luehrs <doy@tozt.net> | 2022-12-11 21:59:21 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2022-12-11 22:16:30 -0500 |
commit | e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06 (patch) | |
tree | 93e418011c45cab8d4070d3d33b377a9364f4a27 /src/2020/8/mod.rs | |
parent | 179467096141b7e8f67d63b89fd21e779a564fe6 (diff) | |
download | advent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.tar.gz advent-of-code-e2d219b331a878bbb3c9dcef9ea4e218b2e3ee06.zip |
refactor
Diffstat (limited to 'src/2020/8/mod.rs')
-rw-r--r-- | src/2020/8/mod.rs | 133 |
1 files changed, 0 insertions, 133 deletions
diff --git a/src/2020/8/mod.rs b/src/2020/8/mod.rs deleted file mode 100644 index af08f5c..0000000 --- a/src/2020/8/mod.rs +++ /dev/null @@ -1,133 +0,0 @@ -use crate::prelude::*; - -#[derive(Clone, Copy)] -enum OpType { - Nop, - Acc, - Jmp, -} - -impl std::str::FromStr for OpType { - type Err = Error; - - fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { - Ok(match s { - "nop" => Self::Nop, - "acc" => Self::Acc, - "jmp" => Self::Jmp, - _ => return Err(anyhow!("invalid optype {}", s)), - }) - } -} - -#[derive(Clone, Copy)] -pub struct Op { - ty: OpType, - arg: i64, -} - -impl std::str::FromStr for Op { - type Err = Error; - - fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { - let captures = regex_captures!(r"^([^ ]*) ((?:-|\+)[0-9]+)$", s) - .context("failed to parse line")?; - let ty = captures.get(1).unwrap().as_str().parse()?; - let arg = captures - .get(2) - .unwrap() - .as_str() - .parse() - .context("invalid arg")?; - Ok(Self { ty, arg }) - } -} - -pub fn parse(fh: File) -> Result<Vec<Op>> { - parse::lines(fh).map(|line| line.parse()).collect() -} - -pub fn part1(opcodes: Vec<Op>) -> Result<i64> { - let (acc, success) = run(&opcodes)?; - if success { - return Err(anyhow!("unexpectedly succeeded")); - } - Ok(acc) -} - -pub fn part2(opcodes: Vec<Op>) -> Result<i64> { - for i in 0..opcodes.len() { - match opcodes[i].ty { - OpType::Nop => { - let mut attempt = opcodes.clone(); - attempt[i].ty = OpType::Jmp; - let (acc, success) = run(&attempt)?; - if success { - return Ok(acc); - } - } - OpType::Acc => {} - OpType::Jmp => { - let mut attempt = opcodes.clone(); - attempt[i].ty = OpType::Nop; - let (acc, success) = run(&attempt)?; - if success { - return Ok(acc); - } - } - } - } - Err(anyhow!("failed to find corrupted opcode")) -} - -fn run(opcodes: &[Op]) -> Result<(i64, bool)> { - let mut seen = vec![false; opcodes.len()]; - let mut pc = 0; - let mut acc = 0; - loop { - if pc >= opcodes.len() { - return Ok((acc, true)); - } else if seen[pc] { - return Ok((acc, false)); - } - seen[pc] = true; - - match opcodes[pc].ty { - OpType::Nop => { - pc += 1; - } - OpType::Acc => { - acc += opcodes[pc].arg; - pc += 1; - } - OpType::Jmp => { - let arg = opcodes[pc].arg; - if arg >= 0 { - if arg as usize > opcodes.len() - || pc > opcodes.len() - arg as usize - { - return Err(anyhow!("invalid jmp")); - } - pc += arg as usize; - } else { - if pc < (-arg as usize) { - return Err(anyhow!("invalid jmp")); - } - pc -= -arg as usize; - } - } - } - } -} - -#[test] -fn test() { - assert_eq!( - part1(parse(parse::data(2020, 8).unwrap()).unwrap()).unwrap(), - 1928 - ); - assert_eq!( - part2(parse(parse::data(2020, 8).unwrap()).unwrap()).unwrap(), - 1319 - ); -} |