add day 23
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
#[cfg(debug_assertions)]
|
||||
const FILENAME: &str = "example.txt";
|
||||
#[cfg(not(debug_assertions))]
|
||||
const FILENAME: &str = "input.txt";
|
||||
|
||||
fn main() {
|
||||
let mut program: Vec<_> = std::fs::read_to_string(FILENAME)
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(Instruction::parse)
|
||||
.collect();
|
||||
|
||||
part1(&mut program);
|
||||
|
||||
let mut program: Vec<_> = std::fs::read_to_string(FILENAME)
|
||||
.unwrap()
|
||||
.lines()
|
||||
.map(Instruction::parse)
|
||||
.collect();
|
||||
|
||||
part2(&mut program);
|
||||
}
|
||||
|
||||
fn part2(program: &mut [Instruction]) {
|
||||
let mut registers = Registers::new();
|
||||
registers.set('a', &Value::Numeric(12));
|
||||
|
||||
run_program(program, &mut registers);
|
||||
|
||||
println!("{}", registers.registers[0]);
|
||||
}
|
||||
|
||||
fn part1(program: &mut [Instruction]) {
|
||||
let mut registers = Registers::new();
|
||||
registers.set('a', &Value::Numeric(7));
|
||||
|
||||
run_program(program, &mut registers);
|
||||
|
||||
println!("{}", registers.registers[0]);
|
||||
}
|
||||
|
||||
struct Registers {
|
||||
registers: [isize; 4],
|
||||
}
|
||||
|
||||
impl Registers {
|
||||
fn set(&mut self, register: char, value: &Value) {
|
||||
let address = Self::get_address(register);
|
||||
match value {
|
||||
Value::Register(from_register) => {
|
||||
let from_address = Self::get_address(*from_register);
|
||||
self.registers[address] = self.registers[from_address];
|
||||
}
|
||||
Value::Numeric(value) => self.registers[address] = *value,
|
||||
}
|
||||
}
|
||||
|
||||
fn inc(&mut self, register: char) {
|
||||
let address = Self::get_address(register);
|
||||
self.registers[address] += 1;
|
||||
}
|
||||
|
||||
fn dec(&mut self, register: char) {
|
||||
let address = Self::get_address(register);
|
||||
self.registers[address] -= 1;
|
||||
}
|
||||
|
||||
fn is_nonzero(&self, value: &Value) -> bool {
|
||||
match value {
|
||||
Value::Register(register) => {
|
||||
let address = Self::get_address(*register);
|
||||
self.registers[address] != 0
|
||||
}
|
||||
Value::Numeric(value) => *value != 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_address(register: char) -> usize {
|
||||
match register {
|
||||
'a' => 0,
|
||||
'b' => 1,
|
||||
'c' => 2,
|
||||
'd' => 3,
|
||||
_ => panic!("unknown register: {register}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
Self { registers: [0; 4] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Instruction {
|
||||
Cpy(Value, Value),
|
||||
Inc(Value),
|
||||
Dec(Value),
|
||||
Jnz(Value, Value),
|
||||
Tgl(Value),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
enum Value {
|
||||
Register(char),
|
||||
Numeric(isize),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn parse(s: &str) -> Self {
|
||||
let first_char = s.chars().next().unwrap();
|
||||
if first_char.is_ascii_digit() || first_char == '-' {
|
||||
Self::Numeric(s.parse().unwrap())
|
||||
} else {
|
||||
Self::Register(first_char)
|
||||
}
|
||||
}
|
||||
|
||||
// fn is_register(&self) -> bool {
|
||||
// match self {
|
||||
// Value::Register(_) => true,
|
||||
// Value::Numeric(_) => false,
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_numeric(&self) -> bool {
|
||||
// !self.is_register()
|
||||
// }
|
||||
}
|
||||
|
||||
impl Instruction {
|
||||
fn parse(s: &str) -> Self {
|
||||
let words: Vec<_> = s.split_whitespace().collect();
|
||||
match words[0] {
|
||||
"cpy" => Self::Cpy(Value::parse(words[1]), Value::parse(words[2])),
|
||||
"inc" => Self::Inc(Value::parse(words[1])),
|
||||
"dec" => Self::Dec(Value::parse(words[1])),
|
||||
"jnz" => Self::Jnz(Value::parse(words[1]), Value::parse(words[2])),
|
||||
"tgl" => Self::Tgl(Value::parse(words[1])),
|
||||
_ => panic!("unknown pattern: {s}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_program(program: &mut [Instruction], registers: &mut Registers) {
|
||||
let mut pointer = 0;
|
||||
|
||||
while let Some(instruction) = program.get(pointer) {
|
||||
match instruction {
|
||||
Instruction::Cpy(source, value) => {
|
||||
match value {
|
||||
Value::Register(r) => {
|
||||
registers.set(*r, source);
|
||||
}
|
||||
Value::Numeric(_) => (),
|
||||
}
|
||||
pointer += 1;
|
||||
}
|
||||
Instruction::Inc(value) => {
|
||||
match value {
|
||||
Value::Register(r) => {
|
||||
registers.inc(*r);
|
||||
}
|
||||
Value::Numeric(_) => (),
|
||||
}
|
||||
pointer += 1;
|
||||
}
|
||||
Instruction::Dec(value) => {
|
||||
match value {
|
||||
Value::Register(r) => {
|
||||
registers.dec(*r);
|
||||
}
|
||||
Value::Numeric(_) => (),
|
||||
}
|
||||
pointer += 1;
|
||||
}
|
||||
Instruction::Jnz(register, value) => {
|
||||
if registers.is_nonzero(register) {
|
||||
match value {
|
||||
Value::Register(r) => {
|
||||
let val = registers.registers[Registers::get_address(*r)];
|
||||
pointer = ((pointer as isize) + val) as usize;
|
||||
}
|
||||
Value::Numeric(n) => {
|
||||
pointer = ((pointer as isize) + *n) as usize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pointer += 1;
|
||||
}
|
||||
}
|
||||
Instruction::Tgl(value) => {
|
||||
let val = match value {
|
||||
Value::Register(r) => registers.registers[Registers::get_address(*r)],
|
||||
Value::Numeric(n) => *n,
|
||||
};
|
||||
let instruction = match program.get_mut((pointer as isize + val) as usize) {
|
||||
Some(instruction) => instruction,
|
||||
None => {
|
||||
pointer += 1;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
*instruction = match instruction {
|
||||
Instruction::Cpy(a, b) => Instruction::Jnz(*a, *b),
|
||||
Instruction::Inc(a) => Instruction::Dec(*a),
|
||||
Instruction::Dec(a) => Instruction::Inc(*a),
|
||||
Instruction::Jnz(a, b) => Instruction::Cpy(*a, *b),
|
||||
Instruction::Tgl(a) => Instruction::Inc(*a),
|
||||
};
|
||||
pointer += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user