solve day 24
This commit is contained in:
parent
50477e7c7e
commit
776538165b
252
input/24.txt
Normal file
252
input/24.txt
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 12
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 7
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 13
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 8
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 13
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 10
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -2
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 4
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -10
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 4
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 13
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 6
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -14
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 11
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -5
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 13
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 15
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 1
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 15
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 8
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -14
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 4
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 1
|
||||||
|
add x 10
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 13
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -14
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 4
|
||||||
|
mul y x
|
||||||
|
add z y
|
||||||
|
inp w
|
||||||
|
mul x 0
|
||||||
|
add x z
|
||||||
|
mod x 26
|
||||||
|
div z 26
|
||||||
|
add x -5
|
||||||
|
eql x w
|
||||||
|
eql x 0
|
||||||
|
mul y 0
|
||||||
|
add y 25
|
||||||
|
mul y x
|
||||||
|
add y 1
|
||||||
|
mul z y
|
||||||
|
mul y 0
|
||||||
|
add y w
|
||||||
|
add y 14
|
||||||
|
mul y x
|
||||||
|
add z y
|
269
src/day24.rs
Normal file
269
src/day24.rs
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
// Beautiful explanation: https://github.com/dphilipson/advent-of-code-2021/blob/master/src/days/day24.rs
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Register {
|
||||||
|
X, Y, Z, W
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum Operand {
|
||||||
|
Register(Register),
|
||||||
|
Number(i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub enum Instruction {
|
||||||
|
Input(Register),
|
||||||
|
Add(Register, Operand),
|
||||||
|
Multiply(Register, Operand),
|
||||||
|
Divide(Register, Operand),
|
||||||
|
Modulo(Register, Operand),
|
||||||
|
Equal(Register, Operand)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
pub struct CPU {
|
||||||
|
rx: i32,
|
||||||
|
ry: i32,
|
||||||
|
rz: i32,
|
||||||
|
rw: i32,
|
||||||
|
input: Vec<i32>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CPU {
|
||||||
|
fn new() -> CPU {
|
||||||
|
CPU { rx: 0, ry: 0, rz: 0, rw: 0, input: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reg(&mut self, reg: Register) -> &mut i32 {
|
||||||
|
match reg {
|
||||||
|
Register::X => &mut self.rx,
|
||||||
|
Register::Y => &mut self.ry,
|
||||||
|
Register::Z => &mut self.rz,
|
||||||
|
Register::W => &mut self.rw,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn op(&mut self, op: Operand) -> i32 {
|
||||||
|
match op {
|
||||||
|
Operand::Register(reg) => *self.reg(reg),
|
||||||
|
Operand::Number(num) => num,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(&mut self, reg: Register, num: i32) {
|
||||||
|
*self.reg(reg) = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self, reg: Register, op: Operand) {
|
||||||
|
*self.reg(reg) += self.op(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiply(&mut self, reg: Register, op: Operand) {
|
||||||
|
*self.reg(reg) *= self.op(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn divide(&mut self, reg: Register, op: Operand) {
|
||||||
|
*self.reg(reg) /= self.op(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modulo(&mut self, reg: Register, op: Operand) {
|
||||||
|
*self.reg(reg) %= self.op(op);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equal(&mut self, reg: Register, op: Operand) {
|
||||||
|
let b = self.op(op);
|
||||||
|
let a = self.reg(reg);
|
||||||
|
*a = if *a == b { 1 } else { 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self, inst: &Instruction) {
|
||||||
|
use Instruction::*;
|
||||||
|
match *inst {
|
||||||
|
Input(a) => {
|
||||||
|
let b = self.input.pop().expect("Missing input");
|
||||||
|
self.input(a, b)
|
||||||
|
},
|
||||||
|
Add(a, b) => self.add(a, b),
|
||||||
|
Multiply(a, b) => self.multiply(a, b),
|
||||||
|
Divide(a, b) => self.divide(a, b),
|
||||||
|
Modulo(a, b) => self.modulo(a, b),
|
||||||
|
Equal(a, b) => self.equal(a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_register(input: &str) -> Register {
|
||||||
|
match input {
|
||||||
|
"x" => Register::X,
|
||||||
|
"y" => Register::Y,
|
||||||
|
"z" => Register::Z,
|
||||||
|
"w" => Register::W,
|
||||||
|
_ => panic!("Unknown variable '{}'", input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_operand(input: &str) -> Operand {
|
||||||
|
if let Ok(number) = input.parse::<i32>() {
|
||||||
|
Operand::Number(number)
|
||||||
|
} else {
|
||||||
|
Operand::Register(parse_register(input))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_input(input: &str) -> Vec<Instruction> {
|
||||||
|
let mut instructions = vec![];
|
||||||
|
for line in input.lines() {
|
||||||
|
if line.is_empty() { continue; }
|
||||||
|
let parts = line.split(' ').collect::<Vec<_>>();
|
||||||
|
let opcode = *parts.get(0).expect("Missing opcode");
|
||||||
|
let instruction = match opcode {
|
||||||
|
"inp" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
Instruction::Input(parse_register(op1))
|
||||||
|
},
|
||||||
|
"add" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
let op2 = parts.get(2).expect("Missing operand");
|
||||||
|
Instruction::Add(parse_register(op1), parse_operand(op2))
|
||||||
|
},
|
||||||
|
"mul" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
let op2 = parts.get(2).expect("Missing operand");
|
||||||
|
Instruction::Multiply(parse_register(op1), parse_operand(op2))
|
||||||
|
}
|
||||||
|
"div" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
let op2 = parts.get(2).expect("Missing operand");
|
||||||
|
Instruction::Divide(parse_register(op1), parse_operand(op2))
|
||||||
|
},
|
||||||
|
"mod" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
let op2 = parts.get(2).expect("Missing operand");
|
||||||
|
Instruction::Modulo(parse_register(op1), parse_operand(op2))
|
||||||
|
}
|
||||||
|
"eql" => {
|
||||||
|
let op1 = parts.get(1).expect("Missing variable");
|
||||||
|
let op2 = parts.get(2).expect("Missing operand");
|
||||||
|
Instruction::Equal(parse_register(op1), parse_operand(op2))
|
||||||
|
},
|
||||||
|
_ => panic!("Unexpected opcode '{}'", opcode)
|
||||||
|
};
|
||||||
|
instructions.push(instruction);
|
||||||
|
}
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(instructions: &[Instruction], monad: &[u8]) -> bool {
|
||||||
|
let mut cpu = CPU::new();
|
||||||
|
cpu.input = vec![];
|
||||||
|
for num in monad {
|
||||||
|
cpu.input.push(*num as i32);
|
||||||
|
}
|
||||||
|
cpu.input.reverse();
|
||||||
|
for inst in instructions {
|
||||||
|
cpu.run(inst);
|
||||||
|
}
|
||||||
|
cpu.rz == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze(instructions: &[Instruction]) -> Vec<(i32, i32, i32)> {
|
||||||
|
let mut result = vec![];
|
||||||
|
for (i, _) in instructions.iter().enumerate()
|
||||||
|
.filter(|(_, inst)| **inst == Instruction::Input(Register::W)) {
|
||||||
|
let a = match instructions.get(i+4) {
|
||||||
|
Some(Instruction::Divide(_, Operand::Number(num))) => *num,
|
||||||
|
_ => panic!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let b = match instructions.get(i+5) {
|
||||||
|
Some(Instruction::Add(_, Operand::Number(num))) => *num,
|
||||||
|
_ => panic!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let c = match instructions.get(i+15) {
|
||||||
|
Some(Instruction::Add(_, Operand::Number(num))) => *num,
|
||||||
|
_ => panic!()
|
||||||
|
};
|
||||||
|
|
||||||
|
result.push((a, b, c));
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze_requirements(instructions: &[Instruction]) -> Vec<(u8, u8, i8)> {
|
||||||
|
let mut requirements = vec![];
|
||||||
|
let result = analyze(instructions);
|
||||||
|
let mut stack = vec![];
|
||||||
|
for (i, (_, check, offset)) in result.iter().enumerate() {
|
||||||
|
if *check > 0 {
|
||||||
|
stack.push((i, offset))
|
||||||
|
} else {
|
||||||
|
let top = stack.pop().unwrap();
|
||||||
|
requirements.push((i as u8, top.0 as u8, (*check + top.1) as i8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requirements
|
||||||
|
}
|
||||||
|
|
||||||
|
fn concat_nums(nums: &[u8]) -> u64 {
|
||||||
|
let mut answer = 0u64;
|
||||||
|
for num in nums {
|
||||||
|
answer *= 10;
|
||||||
|
answer += *num as u64;
|
||||||
|
}
|
||||||
|
answer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part1(instructions: Vec<Instruction>) -> u64 {
|
||||||
|
let mut monad = [9u8; 14];
|
||||||
|
for (i, j, offset) in analyze_requirements(&instructions) {
|
||||||
|
if offset > 0 {
|
||||||
|
monad[j as usize] = (9 - offset) as u8;
|
||||||
|
} else {
|
||||||
|
monad[i as usize] = (9 + offset) as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(check(&instructions, &monad));
|
||||||
|
|
||||||
|
concat_nums(&monad)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(instructions: Vec<Instruction>) -> u64 {
|
||||||
|
let mut monad = [1u8; 14];
|
||||||
|
for (i, j, offset) in analyze_requirements(&instructions) {
|
||||||
|
if offset > 0 {
|
||||||
|
monad[i as usize] = (1 + offset) as u8;
|
||||||
|
} else {
|
||||||
|
monad[j as usize] = (1 - offset) as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(check(&instructions, &monad));
|
||||||
|
|
||||||
|
concat_nums(&monad)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn input_parsing() {
|
||||||
|
use Instruction::*;
|
||||||
|
use Register::*;
|
||||||
|
let instructions = parse_input(&[
|
||||||
|
"inp z",
|
||||||
|
"inp x",
|
||||||
|
"mul z 3",
|
||||||
|
"eql z x",
|
||||||
|
].join("\n"));
|
||||||
|
assert_eq!(instructions, vec![
|
||||||
|
Input(Z),
|
||||||
|
Input(X),
|
||||||
|
Multiply(Z, Operand::Number(3)),
|
||||||
|
Equal(Z, Operand::Register(X))
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ mod day20;
|
|||||||
mod day21;
|
mod day21;
|
||||||
mod day22;
|
mod day22;
|
||||||
mod day23;
|
mod day23;
|
||||||
|
mod day24;
|
||||||
mod day3;
|
mod day3;
|
||||||
mod day4;
|
mod day4;
|
||||||
mod day5;
|
mod day5;
|
||||||
@ -126,6 +127,8 @@ fn run(day: i32, part: i32, input_filename: &str) {
|
|||||||
"22.2" => println!("{}", day22::part2(day22::parse_input(&contents))),
|
"22.2" => println!("{}", day22::part2(day22::parse_input(&contents))),
|
||||||
"23.1" => println!("{}", day23::part1(day23::parse_input(&contents))),
|
"23.1" => println!("{}", day23::part1(day23::parse_input(&contents))),
|
||||||
"23.2" => println!("{}", day23::part2(day23::parse_input(&contents))),
|
"23.2" => println!("{}", day23::part2(day23::parse_input(&contents))),
|
||||||
|
"24.1" => println!("{}", day24::part1(day24::parse_input(&contents))),
|
||||||
|
"24.2" => println!("{}", day24::part2(day24::parse_input(&contents))),
|
||||||
_ => println!("Day {} part {} not found", day, part),
|
_ => println!("Day {} part {} not found", day, part),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user