Day 16 part 1.
This commit is contained in:
4261
input/day16.txt
Normal file
4261
input/day16.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
aoc_2018::tasks::day25::task1();
|
||||
aoc_2018::tasks::day16::task1();
|
||||
}
|
||||
|
||||
536
src/tasks/day16.rs
Normal file
536
src/tasks/day16.rs
Normal file
@@ -0,0 +1,536 @@
|
||||
use std::ops::{BitAnd, BitOr};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
pub fn task1() {
|
||||
let count = include_str!("../../input/day16.txt")
|
||||
.split_once("\n\n\n\n")
|
||||
.unwrap()
|
||||
.0
|
||||
.split("\n\n")
|
||||
.map(|sample_input| parse(sample_input))
|
||||
.map(matches_count)
|
||||
.filter(|count| *count >= 3)
|
||||
.count();
|
||||
println!("Day 16 part1: {count}");
|
||||
}
|
||||
|
||||
fn parse(sample: &str) -> Sample {
|
||||
let (before, instruction, after) = sample.lines().collect_tuple().unwrap();
|
||||
let before: Vec<_> = before
|
||||
.trim_start_matches("Before: [")
|
||||
.trim_end_matches("]")
|
||||
.split(", ")
|
||||
.collect();
|
||||
let before = Registers::from(before);
|
||||
let after: Vec<_> = after
|
||||
.trim_start_matches("After: [")
|
||||
.trim_end_matches("]")
|
||||
.split(", ")
|
||||
.collect();
|
||||
let after = Registers::from(after);
|
||||
let instruction: Vec<usize> = instruction.split(" ").map(|x| x.parse().unwrap()).collect();
|
||||
let instruction = Instruction {
|
||||
opcode: instruction[0],
|
||||
a: instruction[1],
|
||||
b: instruction[2],
|
||||
c: instruction[3],
|
||||
};
|
||||
|
||||
Sample(before, instruction, after)
|
||||
}
|
||||
|
||||
fn matches(sample: Sample, op: Op) -> bool {
|
||||
op.process(sample.0, sample.1) == sample.2
|
||||
}
|
||||
|
||||
fn matches_count(sample: Sample) -> usize {
|
||||
let vec = OPS.iter().filter(|op| matches(sample, **op)).collect_vec();
|
||||
vec.len()
|
||||
}
|
||||
|
||||
const OPS: &[Op] = &[
|
||||
Op::AddR,
|
||||
Op::AddI,
|
||||
Op::MulR,
|
||||
Op::MulI,
|
||||
Op::BanR,
|
||||
Op::BanI,
|
||||
Op::BorR,
|
||||
Op::BorI,
|
||||
Op::SetR,
|
||||
Op::SetI,
|
||||
Op::GtIR,
|
||||
Op::GtRI,
|
||||
Op::GtRR,
|
||||
Op::EqIR,
|
||||
Op::EqRI,
|
||||
Op::EqRR,
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum Op {
|
||||
AddR,
|
||||
AddI,
|
||||
MulR,
|
||||
MulI,
|
||||
BanR,
|
||||
BanI,
|
||||
BorR,
|
||||
BorI,
|
||||
SetR,
|
||||
SetI,
|
||||
GtIR,
|
||||
GtRI,
|
||||
GtRR,
|
||||
EqIR,
|
||||
EqRI,
|
||||
EqRR,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
fn process(&self, registers: Registers, instruction: Instruction) -> Registers {
|
||||
let mut result = registers.0.clone();
|
||||
|
||||
match self {
|
||||
Op::AddR => {
|
||||
result[instruction.c] = result[instruction.a] + result[instruction.b];
|
||||
}
|
||||
Op::AddI => {
|
||||
result[instruction.c] = result[instruction.a] + instruction.b as i32;
|
||||
}
|
||||
Op::MulR => {
|
||||
result[instruction.c] = result[instruction.a] * result[instruction.b];
|
||||
}
|
||||
Op::MulI => {
|
||||
result[instruction.c] = result[instruction.a] * instruction.b as i32;
|
||||
}
|
||||
Op::BanR => {
|
||||
result[instruction.c] = result[instruction.a].bitand(result[instruction.b]);
|
||||
}
|
||||
Op::BanI => {
|
||||
result[instruction.c] = result[instruction.a].bitand(instruction.b as i32);
|
||||
}
|
||||
Op::BorR => {
|
||||
result[instruction.c] = result[instruction.a].bitor(result[instruction.b]);
|
||||
}
|
||||
Op::BorI => {
|
||||
result[instruction.c] = result[instruction.a].bitor(instruction.b as i32);
|
||||
}
|
||||
Op::SetR => {
|
||||
result[instruction.c] = result[instruction.a];
|
||||
}
|
||||
Op::SetI => {
|
||||
result[instruction.c] = instruction.a as i32;
|
||||
}
|
||||
Op::GtIR => {
|
||||
result[instruction.c] = if instruction.a as i32 > result[instruction.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Op::GtRI => {
|
||||
result[instruction.c] = if result[instruction.a] > instruction.b as i32 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Op::GtRR => {
|
||||
result[instruction.c] = if result[instruction.a] > result[instruction.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Op::EqIR => {
|
||||
result[instruction.c] = if instruction.a as i32 == result[instruction.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Op::EqRI => {
|
||||
result[instruction.c] = if result[instruction.a] == instruction.b as i32 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
Op::EqRR => {
|
||||
result[instruction.c] = if result[instruction.a] == result[instruction.b] {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Registers(result)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Sample(Registers, Instruction, Registers);
|
||||
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
struct Registers([i32; 4]);
|
||||
|
||||
impl From<Vec<&str>> for Registers {
|
||||
fn from(value: Vec<&str>) -> Self {
|
||||
let values: Vec<_> = value.iter().map(|x| x.parse().unwrap()).collect();
|
||||
Registers([values[0], values[1], values[2], values[3]])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct Instruction {
|
||||
opcode: usize,
|
||||
a: usize,
|
||||
b: usize,
|
||||
c: usize,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::tasks::day16::{matches_count, parse, Instruction, Op, Registers};
|
||||
|
||||
#[test]
|
||||
fn example1() {
|
||||
let input = "Before: [3, 2, 1, 1]\n\
|
||||
9 2 1 2\n\
|
||||
After: [3, 2, 2, 1]";
|
||||
assert_eq!(matches_count(parse(input)), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_AddR() {
|
||||
let op = Op::AddR;
|
||||
let result = op.process(
|
||||
Registers([3, 4, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(7, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_AddI() {
|
||||
let op = Op::AddI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 1337,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1338, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_MulR() {
|
||||
let op = Op::MulR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(6, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_MulI() {
|
||||
let op = Op::MulI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1337,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(2 * 1337, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_BanR() {
|
||||
let op = Op::BanR;
|
||||
let result = op.process(
|
||||
Registers([0x10101, 0x10110, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0x10100, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_BanI() {
|
||||
let op = Op::BanI;
|
||||
let result = op.process(
|
||||
Registers([0x10101, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 0x10110,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0x10100, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_BorR() {
|
||||
let op = Op::BorR;
|
||||
let result = op.process(
|
||||
Registers([0x10101, 0x10110, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0x10111, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_BorI() {
|
||||
let op = Op::BorI;
|
||||
let result = op.process(
|
||||
Registers([0x10101, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 0,
|
||||
b: 0x10110,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0x10111, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_SetR() {
|
||||
let op = Op::SetR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(2, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_SetI() {
|
||||
let op = Op::SetI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1234,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1234, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtIR_true() {
|
||||
let op = Op::GtIR;
|
||||
let result = op.process(
|
||||
Registers([1, 29, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 30,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtIR_false() {
|
||||
let op = Op::GtIR;
|
||||
let result = op.process(
|
||||
Registers([1, 1337, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1337,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtRI_true() {
|
||||
let op = Op::GtRI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 2,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtRI_false() {
|
||||
let op = Op::GtRI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 2,
|
||||
b: 3,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtRR_true() {
|
||||
let op = Op::GtRR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 0,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_GtRR() {
|
||||
let op = Op::GtRR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqIR_true() {
|
||||
let op = Op::EqIR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 0,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqIR_false() {
|
||||
let op = Op::EqIR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqRI_true() {
|
||||
let op = Op::EqRI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 2,
|
||||
b: 3,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqRI_false() {
|
||||
let op = Op::EqRI;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqRR_true() {
|
||||
let op = Op::EqRR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 1,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(1, result.0[3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_EqRR_false() {
|
||||
let op = Op::EqRR;
|
||||
let result = op.process(
|
||||
Registers([1, 2, 3, 4]),
|
||||
Instruction {
|
||||
opcode: 0,
|
||||
a: 1,
|
||||
b: 2,
|
||||
c: 3,
|
||||
},
|
||||
);
|
||||
assert_eq!(0, result.0[3]);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ pub mod day12;
|
||||
pub mod day13;
|
||||
pub mod day14;
|
||||
pub mod day15;
|
||||
pub mod day16;
|
||||
pub mod day17;
|
||||
pub mod day18;
|
||||
pub mod day20;
|
||||
|
||||
Reference in New Issue
Block a user