implement day 16 part 2

This commit is contained in:
Jan Christian Grünhage 2021-12-16 14:42:27 +01:00
parent aac5c02b82
commit 7c8b242698
3 changed files with 84 additions and 33 deletions

View file

@ -15,31 +15,26 @@ pub fn part1(input: &Packet) -> usize {
input.sum_of_version_numbers()
}
//#[aoc(dayx, part2)]
//pub fn part2(input: &[Input]) -> usize {
// unimplemented!();
//}
#[aoc(day16, part2)]
pub fn part2(input: &Packet) -> usize {
input.calculate()
}
#[cfg(test)]
mod test {
const EXAMPLE_INPUT: &str = "A0016C880162017C3686B18A3D4780";
const RESULT_PART_1: usize = 31;
//const RESULT_PART_2: usize = 0;
#[test]
fn part1_example() {
let result = super::part1(&super::parse_input(EXAMPLE_INPUT));
assert_eq!(result, RESULT_PART_1);
}
//#[test]
//fn part2_example() {
// let result = super::part2(&super::parse_input(EXAMPLE_INPUT));
// assert_eq!(result, RESULT_PART_2);
//}
#[test]
fn parse_example() {
super::parse_input(EXAMPLE_INPUT);
fn part2_example() {
for (input, result) in [
("C200B40A82", 3),
("04005AC33890", 54),
("880086C3E88112", 7),
("CE00C43D881120", 9),
("D8005AC2A8F0", 1),
("F600BC2D8F", 0),
("9C005AC2F8F0", 0),
("9C0141080250320F1802104A08", 1),
] {
assert_eq!(super::part2(&super::parse_input(input)), result);
}
}
}

View file

@ -17,6 +17,39 @@ impl Packet {
Kind::LiteralValue(_) => self.version,
}
}
pub fn calculate(&self) -> usize {
match &self.kind {
Kind::Operator(op) => match op.operation {
Operation::Sum => op.sub_packets.iter().map(|p| p.calculate()).sum(),
Operation::Product => op.sub_packets.iter().map(|p| p.calculate()).product(),
Operation::Minimum => op.sub_packets.iter().map(|p| p.calculate()).min().unwrap(),
Operation::Maximum => op.sub_packets.iter().map(|p| p.calculate()).max().unwrap(),
Operation::GreaterThan => {
if op.sub_packets[0].calculate() > op.sub_packets[1].calculate() {
1
} else {
0
}
}
Operation::LessThan => {
if op.sub_packets[0].calculate() < op.sub_packets[1].calculate() {
1
} else {
0
}
}
Operation::EqualTo => {
if op.sub_packets[0].calculate() == op.sub_packets[1].calculate() {
1
} else {
0
}
}
},
Kind::LiteralValue(val) => *val,
}
}
}
#[derive(Debug, PartialEq)]
@ -27,7 +60,7 @@ pub enum Kind {
#[derive(Debug, PartialEq)]
pub struct Operator {
pub opcode: usize,
pub operation: Operation,
pub length: Length,
pub sub_packets: Vec<Packet>,
}
@ -37,3 +70,14 @@ pub enum Length {
Count(usize),
Length(usize),
}
#[derive(Debug, PartialEq)]
pub enum Operation {
Sum,
Product,
Minimum,
Maximum,
GreaterThan,
LessThan,
EqualTo,
}

View file

@ -9,6 +9,7 @@ use yap::Tokens;
use crate::day_16::model::Length;
use crate::day_16::Operator;
use super::model::Operation;
use super::{Kind, Packet};
pub fn parse_packet(tokens: &mut impl Tokens<Item = bool>) -> Option<Packet> {
@ -64,9 +65,7 @@ pub fn parse_operator(tokens: &mut impl Tokens<Item = bool>) -> Option<Packet> {
tokens.optional(|t| {
let (version, opcode) = parse_version_and_type(t)?;
if opcode == 4 {
return None;
}
let operation = get_op_from_code(opcode)?;
let length = match t.next()? {
true => Length::Count(read_number(t, 11)?),
@ -95,7 +94,7 @@ pub fn parse_operator(tokens: &mut impl Tokens<Item = bool>) -> Option<Packet> {
Some(Packet {
version,
kind: Kind::Operator(Operator {
opcode,
operation,
length,
sub_packets,
}),
@ -103,11 +102,24 @@ pub fn parse_operator(tokens: &mut impl Tokens<Item = bool>) -> Option<Packet> {
})
}
fn get_op_from_code(opcode: usize) -> Option<Operation> {
Some(match opcode {
0 => Operation::Sum,
1 => Operation::Product,
2 => Operation::Minimum,
3 => Operation::Maximum,
5 => Operation::GreaterThan,
6 => Operation::LessThan,
7 => Operation::EqualTo,
_ => return None,
})
}
pub fn parse_version_and_type(tokens: &mut impl Tokens<Item = bool>) -> Option<(usize, usize)> {
tokens.optional(|t| {
let version = read_number(t, 3)?;
let type_id = read_number(t, 3)?;
Some((version, type_id))
let opcode = read_number(t, 3)?;
Some((version, opcode))
})
}
@ -199,9 +211,9 @@ impl Tokens for BinTokens {
#[cfg(test)]
mod test {
use crate::day_16::model::Length;
use crate::day_16::model::{Length, Operation};
use super::super::{Kind, Operator, Packet};
use super::super::{Kind, Packet};
use super::BinTokens;
#[test]
@ -243,7 +255,7 @@ mod test {
super::parse_operator(&mut "38006F45291200".parse::<BinTokens>().unwrap()).unwrap();
assert_eq!(packet.version, 1);
if let Kind::Operator(operator) = packet.kind {
assert_eq!(operator.opcode, 6);
assert_eq!(operator.operation, Operation::LessThan);
assert_eq!(operator.length, Length::Length(27));
assert_eq!(operator.sub_packets.len(), 2);
} else {
@ -257,7 +269,7 @@ mod test {
super::parse_operator(&mut "EE00D40C823060".parse::<BinTokens>().unwrap()).unwrap();
assert_eq!(packet.version, 7);
if let Kind::Operator(operator) = packet.kind {
assert_eq!(operator.opcode, 3);
assert_eq!(operator.operation, Operation::Maximum);
assert_eq!(operator.length, Length::Count(3));
assert_eq!(operator.sub_packets.len(), 3);
} else {