Skip to content

Commit

Permalink
Year 2016: Day 25
Browse files Browse the repository at this point in the history
  • Loading branch information
joshleaves committed Mar 22, 2024
1 parent cf19c2c commit 7a47db4
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 44 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Of note:
- The changelog 2015.5.2 has been rewritten from each commit content.
- This file may be amended entirely in the future to adhere to the [GNU Changelog style](https://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html#Style-of-Change-Logs)

## [2016.25.1]
### Added
- Solved [exercice for 2016, day 25](src/year_2016/25.rs).

## [2016.24.1]
### Added
- Solved [exercice for 2016, day 24](src/year_2016/24.rs).
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "advent-rs"
version = "2016.24.1"
version = "2016.25.1"
edition = "2021"
authors = ["Arnaud 'red' Rouyer"]
readme = "README.md"
Expand Down
4 changes: 4 additions & 0 deletions NOTES_2016.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ I had forgotten [the original was taking ten minutes to run](https://github.com/
## Day 24: Air Duct Spelunking

Look, [BreadthFirstSearch library](src/bfs.rs) is coming to our rescue again!

## Day 25: Clock Signal

The [Assembunny](src/year_2016/assembunny.rs) library proved very useful too \o/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ As I said, [Consistency is hard](https://github.com/joshleaves/advent-rb), and I

I'm also adding notes that may be useful if you're (like me) discovering Rust:
- [2015, complete!](NOTES_2015.md)
- [2016, up to day 24](NOTES_2016.md)
- [2016, complete!](NOTES_2016.md)

# Regarding style rules
I'm gonna use a mix of what `cargo fmt` does, with some stuff that feels more natural to me.
Expand Down
28 changes: 27 additions & 1 deletion benches/year_2016.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use advent_rs::year_2016::day_20;
use advent_rs::year_2016::day_21;
use advent_rs::year_2016::day_22;
use advent_rs::year_2016::day_23;
use advent_rs::year_2016::day_24;
use advent_rs::year_2016::day_25;
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn year_2016_day_01(c: &mut Criterion) {
Expand Down Expand Up @@ -299,6 +301,28 @@ fn year_2016_day_23(c: &mut Criterion) {
g2016_day_23.finish();
}

fn year_2016_day_24(c: &mut Criterion) {
let mut g2016_day_24 = c.benchmark_group("year_2016::day_24");
let input_year_2016_day_24 = include_str!("../inputs/year_2016/day_24_input");
g2016_day_24.bench_function("year_2016::day_24_v1", |b| {
b.iter(|| day_24::day_24_v1(black_box(input_year_2016_day_24)))
});
g2016_day_24.bench_function("year_2016::day_24_v2", |b| {
b.iter(|| day_24::day_24_v2(black_box(input_year_2016_day_24)))
});
g2016_day_24.finish();
}

fn year_2016_day_25(c: &mut Criterion) {
let mut g2016_day_25 = c.benchmark_group("year_2016::day_25");
let input_year_2016_day_25 = include_str!("../inputs/year_2016/day_25_input");
g2016_day_25.bench_function("year_2016::day_25", |b| {
b.iter(|| day_25::day_25(black_box(input_year_2016_day_25)))
});

g2016_day_25.finish();
}

criterion_group!(
benches,
year_2016_day_01,
Expand All @@ -323,6 +347,8 @@ criterion_group!(
year_2016_day_20,
year_2016_day_21,
year_2016_day_22,
year_2016_day_23
year_2016_day_23,
year_2016_day_24,
year_2016_day_25
);
criterion_main!(benches);
30 changes: 30 additions & 0 deletions inputs/year_2016/day_25_input
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
cpy a d
cpy 9 c
cpy 282 b
inc d
dec b
jnz b -2
dec c
jnz c -5
cpy d a
jnz 0 0
cpy a b
cpy 0 a
cpy 2 c
jnz b 2
jnz 1 6
dec b
dec c
jnz c -4
inc a
jnz 1 -7
cpy 2 b
jnz c 2
jnz 1 4
dec b
dec c
jnz 1 -4
jnz 0 0
out b
jnz a -19
jnz 1 -21
8 changes: 8 additions & 0 deletions src/year_2016.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub mod day_21;
pub mod day_22;
pub mod day_23;
pub mod day_24;
pub mod day_25;

pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
if part != 1 && part != 2 {
Expand Down Expand Up @@ -58,6 +59,7 @@ pub fn solve(day: u8, part: u8, input: impl Into<String>) -> Option<String> {
22 => Some(format!("{}", day_22::day_22(part, input))),
23 => Some(format!("{}", day_23::day_23(part, input))),
24 => Some(format!("{}", day_24::day_24(part, input))),
25 => Some(format!("{}", day_25::day_25(input))),
_ => None,
}
}
Expand Down Expand Up @@ -243,4 +245,10 @@ mod tests {
assert_eq!(day_24::day_24_v1(input), 430);
assert_eq!(day_24::day_24_v2(input), 700);
}

#[test]
fn day_25() {
let input = include_str!("../inputs/year_2016/day_25_input");
assert_eq!(day_25::day_25(input), 192);
}
}
127 changes: 86 additions & 41 deletions src/year_2016/assembunny.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl ValueOrRegister {
}
}

#[derive(Debug)]
#[derive(Debug, Clone)]
enum Instruction {
// cpy x y copies x (either an integer or the value of a register) into register y.
Copy(ValueOrRegister, Register),
Expand All @@ -28,6 +28,8 @@ enum Instruction {
JumpNotZero(ValueOrRegister, ValueOrRegister),
// tgl x toggles the instruction x away (pointing at instructions like jnz does: positive means forward; negative means backward):
Toggle(Register),
// out x transmits x (either an integer or the value of a register) as the next value for the clock signal.
Out(ValueOrRegister),
Nop(),
}

Expand All @@ -50,54 +52,86 @@ impl Assembunny {
self.registers[reg_id as usize] = value;
}

pub fn run(&mut self) {
while (self.pc as usize) < self.instructions.len() {
match &self.instructions[self.pc as usize] {
Instruction::Copy(vor, register) => {
self.registers[*register as usize] = self.value_of(*vor);
self.pc += 1;
}
Instruction::Increment(register) => {
self.registers[*register as usize] += 1;
fn execute(&mut self) -> Option<Value> {
match &self.instructions[self.pc as usize] {
Instruction::Copy(vor, register) => {
self.registers[*register as usize] = self.value_of(*vor);
self.pc += 1;
}
Instruction::Increment(register) => {
self.registers[*register as usize] += 1;
self.pc += 1;
}
Instruction::Decrement(register) => {
self.registers[*register as usize] -= 1;
self.pc += 1;
}
Instruction::JumpNotZero(vor, offset) => {
let value = self.value_of(*vor);
let offset = self.value_of(*offset);
if value != 0 {
self.pc = ((self.pc as i64) + offset) as usize;
} else {
self.pc += 1;
}
Instruction::Decrement(register) => {
self.registers[*register as usize] -= 1;
}
Instruction::Toggle(register) => {
let target = (self.pc as Value + self.registers[*register as usize]) as usize;
if target >= self.instructions.len() {
self.pc += 1;
return None;
}
Instruction::JumpNotZero(vor, offset) => {
let value = self.value_of(*vor);
let offset = self.value_of(*offset);
if value != 0 {
self.pc = ((self.pc as i64) + offset) as usize;
} else {
self.pc += 1;
}
}
Instruction::Toggle(register) => {
let target = (self.pc as Value + self.registers[*register as usize]) as usize;
if target >= self.instructions.len() {
self.pc += 1;
continue;
self.instructions[target] = match self.instructions[target] {
Instruction::Copy(vor, register) => {
Instruction::JumpNotZero(vor, ValueOrRegister::Register(register))
}
self.instructions[target] = match self.instructions[target] {
Instruction::Copy(vor, register) => {
Instruction::JumpNotZero(vor, ValueOrRegister::Register(register))
}
Instruction::Increment(register) => Instruction::Decrement(register),
Instruction::Decrement(register) => Instruction::Increment(register),
Instruction::JumpNotZero(vor, offset) => match offset {
ValueOrRegister::Register(register) => Instruction::Copy(vor, register),
_ => Instruction::Nop(),
},
Instruction::Toggle(offset) => Instruction::Increment(offset as u8),
Instruction::Nop() => Instruction::Nop(),
};
self.pc += 1;
Instruction::Increment(register) => Instruction::Decrement(register),
Instruction::Decrement(register) => Instruction::Increment(register),
Instruction::JumpNotZero(vor, offset) => match offset {
ValueOrRegister::Register(register) => Instruction::Copy(vor, register),
_ => Instruction::Nop(),
},
Instruction::Toggle(offset) => Instruction::Increment(offset as u8),
Instruction::Out(vor) => match vor {
ValueOrRegister::Register(register) => Instruction::Increment(register),
_ => Instruction::Nop(),
},
Instruction::Nop() => Instruction::Nop(),
};
self.pc += 1;
}
Instruction::Out(vor) => {
let value = self.value_of(*vor);
self.pc += 1;
return Some(value);
}
Instruction::Nop() => {}
}
None
}

pub fn run(&mut self) {
while (self.pc as usize) < self.instructions.len() {
self.execute();
}
}

pub fn output(&mut self) -> bool {
let mut output: Vec<bool> = Vec::from([true]);
while (self.pc as usize) < self.instructions.len() {
if output.len() >= 10 {
return true;
}
if let Some(signal) = self.execute() {
let last_signal = output.last().unwrap();
match (signal, last_signal) {
(0, true) => output.push(false),
(1, false) => output.push(true),
_ => return false,
}
Instruction::Nop() => {}
}
}
false
}

fn register(register: &str) -> u8 {
Expand Down Expand Up @@ -142,6 +176,11 @@ impl Assembunny {
let register = Self::register(parts[1]);
instructions.push(Instruction::Toggle(register));
}
// out x transmits x (either an integer or the value of a register) as the next value for the clock signal.
"out" => {
let vor = ValueOrRegister::parse(parts[1]);
instructions.push(Instruction::Out(vor));
}
_ => panic!("Invalid instruction: {}", line),
}
}
Expand All @@ -151,4 +190,10 @@ impl Assembunny {
instructions: instructions,
}
}

pub fn reset(&mut self) -> &mut Self {
self.pc = 0;
self.registers = [0; 4];
self
}
}
13 changes: 13 additions & 0 deletions src/year_2016/day_25.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use super::assembunny::Assembunny;

pub fn day_25(input: impl Into<String>) -> u64 {
let mut bunny: Assembunny = Assembunny::from_input(&input.into());
let mut cnt = 0;
loop {
bunny.reset().set_register("a", cnt);
if bunny.output() {
return cnt as u64;
}
cnt += 1;
}
}

0 comments on commit 7a47db4

Please sign in to comment.