feat: added day 17 part 1 and 2
All checks were successful
Build and run challenges / Challenge for day (1) (push) Successful in 3s
Build and run challenges / Challenge for day (10) (push) Successful in 3s
Build and run challenges / Challenge for day (11) (push) Successful in 3s
Build and run challenges / Challenge for day (12) (push) Successful in 3s
Build and run challenges / Challenge for day (13) (push) Successful in 3s
Build and run challenges / Challenge for day (14) (push) Successful in 3s
Build and run challenges / Challenge for day (17) (push) Successful in 3s
Build and run challenges / Challenge for day (6) (push) Successful in 5s
Build and run challenges / Challenge for day (3) (push) Successful in 11s
Build and run challenges / Challenge for day (7) (push) Successful in 4s
Build and run challenges / Challenge for day (15) (push) Successful in 3s
Build and run challenges / Challenge for day (16) (push) Successful in 3s
Build and run challenges / Challenge for day (2) (push) Successful in 3s
Build and run challenges / Challenge for day (4) (push) Successful in 4s
Build and run challenges / Challenge for day (5) (push) Successful in 5s
Build and run challenges / Challenge for day (8) (push) Successful in 3s
Build and run challenges / Challenge for day (9) (push) Successful in 3s

Signed-off-by: Louis Vallat <contact@louis-vallat.dev>
This commit is contained in:
Louis Vallat 2024-12-26 15:09:33 +01:00
parent 7542e61ed5
commit 83e13c5774
Signed by: louis
SSH Key Fingerprint: SHA256:usb9EA8eIADT+Bt0Ne8ZkISCbgPSOYkVgS2iZqdZj8s
3 changed files with 141 additions and 1 deletions

View File

@ -11,7 +11,7 @@ jobs:
name: Challenge for day
strategy:
matrix:
day_number: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
day_number: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
runs-on: rust-bookworm
steps:
- name: Check out repository code

6
day17/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "day17"
version = "0.1.0"
edition = "2021"
[dependencies]

134
day17/src/main.rs Normal file
View File

@ -0,0 +1,134 @@
use std::collections::HashSet;
use std::{env, fs};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd)]
enum Instruction {
Adv(u64), // Division A = A / 2^x
Bdv(u64), // Division B = A / 2^x
Cdv(u64), // Division C = A / 2^x
Bst(u64), // Combo % 8 B = x % 8
Jnz(u64), // Jump if not 0. if A != 0 { jump to x }
Out(u64), // Print x % 8 echo(x % 8)
Bxl(u64), // Bitwise XOR B = B XOR x
Bxc, // Bitwise XOR B = B XOR C
}
fn read_input(path: &str) -> String {
fs::read_to_string(path).expect("Cannot read file.")
}
fn parse_input(input: &str) -> (Vec<Instruction>, Vec<String>, u64, u64, u64) {
let mut instructions = Vec::new();
let mut lines = input.lines();
let a = lines.next().unwrap()[12..].parse::<u64>().unwrap();
let b = lines.next().unwrap()[12..].parse::<u64>().unwrap();
let c = lines.next().unwrap()[12..].parse::<u64>().unwrap();
lines.next();
let raw_program = lines.next().unwrap()[9..]
.split(',')
.map(|s| s.to_string())
.collect::<Vec<String>>();
for a in raw_program.chunks(2) {
let operand = a[1].parse().unwrap();
instructions.push(match a[0].as_str() {
"0" => Instruction::Adv(operand),
"1" => Instruction::Bxl(operand),
"2" => Instruction::Bst(operand),
"3" => Instruction::Jnz(operand),
"4" => Instruction::Bxc,
"5" => Instruction::Out(operand),
"6" => Instruction::Bdv(operand),
"7" => Instruction::Cdv(operand),
_ => unreachable!(),
})
}
(instructions, raw_program, a, b, c)
}
fn get_value_for_operand(operand: u64, a: u64, b: u64, c: u64) -> u64 {
match operand {
0..=3 => operand,
4 => a,
5 => b,
6 => c,
_ => unreachable!(),
}
}
fn run_program(instructions: &Vec<Instruction>, mut a: u64, mut b: u64, mut c: u64) -> Vec<String> {
let mut output = Vec::new();
let mut pc = 0;
while pc < instructions.len() {
let instruction = instructions[pc];
match instruction {
Instruction::Adv(x) => a = a / 2_u64.pow(get_value_for_operand(x, a, b, c) as u32),
Instruction::Bdv(x) => b = a / 2_u64.pow(get_value_for_operand(x, a, b, c) as u32),
Instruction::Cdv(x) => c = a / 2_u64.pow(get_value_for_operand(x, a, b, c) as u32),
Instruction::Bst(x) => b = get_value_for_operand(x, a, b, c) % 8,
Instruction::Out(x) => output.push((get_value_for_operand(x, a, b, c) % 8).to_string()),
Instruction::Bxl(x) => b = b ^ x,
Instruction::Bxc => b = b ^ c,
Instruction::Jnz(x) => {
if a != 0 {
pc = x as usize
}
}
}
match instruction {
Instruction::Jnz(_) => {
if a == 0 {
pc += 1
}
}
_ => pc += 1,
}
}
output
}
fn find_quine(instruction: &Vec<Instruction>, raw_program: &Vec<String>) -> u64 {
let mut solution = u64::MAX;
let mut seen = HashSet::new();
let mut queue = vec![0];
while let Some(mut possibility) = queue.pop() {
possibility <<= 3;
for x in possibility..(possibility + 8) {
let output = run_program(instruction, x, 0, 0);
if !output.is_empty()
&& *output.first().unwrap() == raw_program[raw_program.len() - output.len()]
{
if raw_program.len() == output.len() {
if x < solution {
solution = x;
}
} else if !seen.contains(&x) {
seen.insert(x);
queue.push(x);
}
}
}
}
solution
}
fn main() {
let args: Vec<String> = env::args().collect();
for arg in args.iter().skip(1) {
let input = read_input(&arg);
let (instructions, raw_program, a, b, c) = parse_input(&input);
println!("[{}]", &arg);
println!(
"\t[Part 1] => Answer is '{}'.",
run_program(&instructions, a, b, c).join(",")
);
println!(
"\t[Part 2] => Answer is '{}'.",
find_quine(&instructions, &raw_program)
);
}
}