Skip to content

Commit 27b04b3

Browse files
committed
More 2020 days
1 parent aef34db commit 27b04b3

File tree

7 files changed

+463
-2
lines changed

7 files changed

+463
-2
lines changed

Cargo.lock

Lines changed: 161 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ default-run = "advent-of-code"
1414
[dependencies]
1515
ansi_term = "0.12.1"
1616
aoc_macros = { path = "./aoc_macros" }
17+
cached = "0.56.0"
1718
clap = { version = "4.0.29", features = ["cargo", "derive", "env"] }
1819
env_logger = "0.11.8"
1920
hex = "0.4.3"

data

Submodule data updated from 2f4a5b2 to 73c0666

src/aoc/y2020/day08.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) 2025 Lexi Robinson
2+
//
3+
// Licensed under the EUPL, Version 1.2
4+
//
5+
// You may not use this work except in compliance with the Licence.
6+
// You should have received a copy of the Licence along with this work. If not, see:
7+
// <https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12>.
8+
// See the Licence for the specific language governing permissions and limitations under the Licence.
9+
10+
use std::{collections::HashSet, str::FromStr};
11+
12+
use itertools::Itertools;
13+
14+
use crate::AoCError;
15+
16+
#[derive(Debug, Clone, Copy)]
17+
enum Opcode {
18+
Acc(i32),
19+
Jmp(i32),
20+
Nop(i32),
21+
}
22+
23+
impl FromStr for Opcode {
24+
type Err = AoCError;
25+
26+
fn from_str(s: &str) -> Result<Self, Self::Err> {
27+
let (opcode, arg) = s
28+
.split_once(' ')
29+
.ok_or_else(|| AoCError::new(format!("Expected {s} to have a space in it!")))?;
30+
let arg = arg.parse()?;
31+
Ok(match opcode {
32+
"acc" => Self::Acc(arg),
33+
"jmp" => Self::Jmp(arg),
34+
"nop" => Self::Nop(arg),
35+
_ => return Err(AoCError::new(format!("Unexpected opcode {opcode}"))),
36+
})
37+
}
38+
}
39+
40+
impl Opcode {
41+
fn swapulate(self) -> Self {
42+
match self {
43+
Self::Acc(_) => self,
44+
Self::Jmp(i) => Self::Nop(i),
45+
Self::Nop(i) => Self::Jmp(i),
46+
}
47+
}
48+
}
49+
50+
#[derive(Debug, Clone, Copy)]
51+
enum Outcome {
52+
InfiniteLoop,
53+
Error,
54+
Terminated,
55+
}
56+
57+
fn computate(opcodes: &[Opcode]) -> (Outcome, i32) {
58+
let mut pc = 0;
59+
let mut acc = 0;
60+
let max = opcodes.len();
61+
let mut visited_instructions = HashSet::with_capacity(max);
62+
log::debug!("Got {max} opcodes!");
63+
while pc < max {
64+
if !visited_instructions.insert(pc) {
65+
log::debug!("Got an infinite loop at {pc}!");
66+
return (Outcome::InfiniteLoop, acc);
67+
}
68+
let opcode = opcodes[pc];
69+
log::debug!("pc is at {pc}, acc is {acc}, opcode is {opcode:?}");
70+
match opcode {
71+
Opcode::Acc(amt) => acc += amt,
72+
Opcode::Jmp(offset) => {
73+
if let Some(new_pc) = pc.checked_add_signed(offset as isize) {
74+
log::debug!("Jumping to {new_pc}!");
75+
pc = new_pc;
76+
continue;
77+
} else {
78+
log::error!("Opcode {opcode:?} set pc below zero!");
79+
return (Outcome::Error, acc);
80+
}
81+
}
82+
Opcode::Nop(_) => (),
83+
}
84+
pc += 1;
85+
}
86+
log::debug!("Program terminated with pc at {pc} and acc at {acc}!");
87+
(Outcome::Terminated, acc)
88+
}
89+
90+
pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
91+
let opcodes: Vec<Opcode> = data.map(|line| line.parse()).try_collect()?;
92+
let (outcome, acc) = computate(&opcodes);
93+
assert!(matches!(outcome, Outcome::InfiniteLoop));
94+
let ret = acc;
95+
Ok(ret.to_string())
96+
}
97+
98+
pub fn part_2(data: crate::DataIn) -> crate::AoCResult<String> {
99+
let opcodes: Vec<Opcode> = data.map(|line| line.parse()).try_collect()?;
100+
101+
let ret = (0..opcodes.len())
102+
.map(|i| {
103+
let mut modified = opcodes.clone();
104+
modified[i] = modified[i].swapulate();
105+
computate(&modified)
106+
})
107+
.find_map(|(outcome, acc)| match outcome {
108+
Outcome::InfiniteLoop => None,
109+
_ => Some(acc),
110+
})
111+
.ok_or(AoCError::new("no modifications worked!"))?;
112+
113+
Ok(ret.to_string())
114+
}
115+
116+
inventory::submit!(crate::AoCDay {
117+
year: "2020",
118+
day: "8",
119+
part_1: crate::AoCPart {
120+
main: part_1,
121+
example: part_1
122+
},
123+
part_2: Some(crate::AoCPart {
124+
main: part_2,
125+
example: part_2
126+
})
127+
});

0 commit comments

Comments
 (0)