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() {
|
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 day13;
|
||||||
pub mod day14;
|
pub mod day14;
|
||||||
pub mod day15;
|
pub mod day15;
|
||||||
|
pub mod day16;
|
||||||
pub mod day17;
|
pub mod day17;
|
||||||
pub mod day18;
|
pub mod day18;
|
||||||
pub mod day20;
|
pub mod day20;
|
||||||
|
|||||||
Reference in New Issue
Block a user