day8
This commit is contained in:
parent
2c499e9efe
commit
90561f8fa9
180
src/day8.rs
Normal file
180
src/day8.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
mod day8;
|
||||||
mod day7;
|
mod day7;
|
||||||
mod day6;
|
mod day6;
|
||||||
mod day5;
|
mod day5;
|
||||||
|
Loading…
Reference in New Issue
Block a user