implement day 16 part 2
This commit is contained in:
parent
aac5c02b82
commit
7c8b242698
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue