This commit is contained in:
Andrew Glaze 2023-12-28 13:35:39 -05:00
parent 2c499e9efe
commit 90561f8fa9
2 changed files with 181 additions and 0 deletions

180
src/day8.rs Normal file
View File

@ -0,0 +1,180 @@
use aoc_runner_derive::{aoc, aoc_generator};
use itertools::Itertools;
#[aoc_generator(day8)]
fn parse(input: &str) -> Box<[Instruction]> {
let input: Vec<Instruction> = input.lines()
.map(|line| {
let (instruction, arg) = line.split(' ').collect_tuple().unwrap();
(instruction, arg.parse::<i32>().unwrap()).into()
}).collect_vec();
input.try_into().unwrap()
}
use Instruction::*;
#[derive(Debug, Clone, Copy)]
enum Instruction {
ACC(i32),
JMP(i32),
NOP(i32)
}
impl From<(&str, i32)> for Instruction {
fn from(value: (&str, i32)) -> Self {
match value {
(i, v) if i == "acc" => ACC(v),
(i, v) if i == "jmp" => JMP(v),
(i, v) if i == "nop" => NOP(v),
_ => unreachable!()
}
}
}
#[aoc(day8, part1)]
fn part1(input: &[Instruction]) -> i32 {
let mut visited: Vec<bool> = vec![false; input.len()];
let mut next = 0;
let mut acc = 0;
loop {
let inst = &input[next];
if visited[next] {
break;
}
visited[next] = true;
match inst {
ACC(arg) => acc += arg,
JMP(arg) => {next = (next as i32 + *arg) as usize; continue;},
NOP(_) => {},
}
next += 1;
}
acc
}
#[aoc(day8, part2)]
fn part2(input: &[Instruction]) -> i32 {
let mut visited: Vec<bool> = vec![false; input.len()];
let mut next = 0;
let mut acc = 0;
loop {
let inst = &input[next];
if visited[next] {
break;
}
visited[next] = true;
match inst {
ACC(arg) => acc += arg,
JMP(arg) => {next = (next as i32 + *arg) as usize; continue;},
NOP(_) => {},
}
next += 1;
}
let mut landing_spots = vec![false; input.len() + 1];
let mut i = input.len();
loop {
landing_spots[i] = true;
i -= 1;
if let JMP(x) = input[i] {
if x < 0 {
break;
}
}
}
let start = i;
let swap = if visited[i] {
i
} else {
loop {
i -= 1;
if landing_spots[i] {
continue;
} else if let NOP(x) = input[i] {
if visited[i] && landing_spots[((i as i32) + x) as usize] {
break i;
}
} else if let JMP(x) = input[i] {
if !visited[i]
&& landing_spots[((i as i32) + x) as usize]
&& !landing_spots[i]
{
let mut j = i - 1;
loop {
if matches!(input[j], JMP(_)) {
break;
}
j -= 1;
}
if visited[j] {
break j;
} else {
landing_spots[j + 1..=i].iter_mut().for_each(|a| {
*a = true;
});
i = start;
}
}
}
}
};
let mut program = input.to_vec();
program[swap] = match program[swap] {
ACC(_) => unreachable!(),
JMP(x) => NOP(x),
NOP(x) => JMP(x),
};
let mut next = 0;
let mut acc = 0;
loop {
if next >= program.len() {
break;
}
let inst = &program[next];
match inst {
ACC(arg) => acc += arg,
JMP(arg) => {next = (next as i32 + *arg) as usize; continue;},
NOP(_) => {},
}
next += 1;
}
acc
}
#[cfg(test)]
mod tests {
use super::*;
const EX: &str = r"nop +0
acc +1
jmp +4
acc +3
jmp -3
acc -99
acc +1
jmp -4
acc +6";
#[test]
fn part1_example() {
assert_eq!(part1(&parse(EX)), 5);
}
#[test]
fn part2_example() {
assert_eq!(part2(&parse(EX)), 8);
}
}

View File

@ -1,3 +1,4 @@
mod day8;
mod day7;
mod day6;
mod day5;