Skip to content

Commit

Permalink
submit day 19 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
dcastil committed Jan 7, 2024
1 parent 52d1467 commit 7cc833b
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 14 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
| [Day 16](./src/bin/16.rs) | `1.8ms` | `474.9ms` |
| [Day 17](./src/bin/17.rs) | `99.6ms` | `278.9ms` |
| [Day 18](./src/bin/18.rs) | `5.0ms` | `41.7µs` |
| [Day 19](./src/bin/19.rs) | `245.4µs` | `-` |
| [Day 19](./src/bin/19.rs) | `239.3µs` | `265.0µs` |

**Total: 1965.56ms**
**Total: 1965.82ms**

<!--- benchmarking table --->

Expand Down
145 changes: 133 additions & 12 deletions src/bin/19.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cmp::Ordering, collections::HashMap};
use std::{cmp::Ordering, collections::HashMap, ops::Range};

advent_of_code::solution!(19);

Expand All @@ -23,8 +23,14 @@ pub fn part_one(input: &str) -> Option<u32> {
Some(sum)
}

pub fn part_two(input: &str) -> Option<u32> {
None
pub fn part_two(input: &str) -> Option<u64> {
let sum = WorkflowMap::from_input(input.split("\n\n").next().unwrap())
.accepted_object_ranges()
.iter()
.map(|object_range| object_range.count())
.sum();

Some(sum)
}

struct WorkflowMap<'a> {
Expand All @@ -46,7 +52,7 @@ impl WorkflowMap<'_> {
let mut command = &Command::Forward("in");

while let Command::Forward(workflow_name) = command {
command = self.next_command(workflow_name, &object);
command = self.next_command(workflow_name, object);
}

match command {
Expand All @@ -57,10 +63,53 @@ impl WorkflowMap<'_> {
}

fn next_command(&self, workflow_name: &str, object: &Object) -> &Command {
self.workflows
.get(workflow_name)
self.workflow(workflow_name).next_command(object)
}

fn workflow(&self, name: &str) -> &Workflow {
self.workflows.get(name).unwrap()
}

fn accepted_object_ranges(&self) -> Vec<ObjectRange> {
self.accepted_object_ranges_recursive(&Command::Forward("in"))
.unwrap()
.next_command(object)
}

fn accepted_object_ranges_recursive(&self, command: &Command) -> Option<Vec<ObjectRange>> {
match command {
Command::Reject => None,
Command::Accept => Some(vec![ObjectRange::new()]),
Command::Forward(workflow_name) => {
let workflow = self.workflow(workflow_name);

let mut object_ranges =
self.accepted_object_ranges_recursive(&workflow.final_command);

for rule in workflow.rules.iter().rev() {
if let Some(object_ranges) = &mut object_ranges {
for object_range in object_ranges {
object_range.subtract(&rule.condition);
}
}

if let Some(mut new_object_ranges) =
self.accepted_object_ranges_recursive(&rule.command)
{
for object_range in new_object_ranges.iter_mut() {
object_range.add(&rule.condition);
}

if let Some(object_ranges) = &mut object_ranges {
object_ranges.extend(new_object_ranges);
} else {
object_ranges = Some(new_object_ranges);
}
}
}

object_ranges
}
}
}
}

Expand Down Expand Up @@ -121,10 +170,7 @@ impl Rule<'_> {
}

fn applies_to(&self, object: &Object) -> bool {
self.condition.ordering
== object
.value(&self.condition.property)
.cmp(&self.condition.cmp_value)
self.condition.applies_to(object)
}
}

Expand Down Expand Up @@ -156,6 +202,10 @@ impl Condition {
cmp_value: string[2..].parse().unwrap(),
}
}

fn applies_to(&self, object: &Object) -> bool {
self.ordering == object.value(&self.property).cmp(&self.cmp_value)
}
}

enum Property {
Expand Down Expand Up @@ -211,6 +261,77 @@ impl Object {
}
}

struct ObjectRange {
x: Range<u32>,
m: Range<u32>,
a: Range<u32>,
s: Range<u32>,
}

impl ObjectRange {
fn new() -> ObjectRange {
ObjectRange {
x: (1..4001),
m: (1..4001),
a: (1..4001),
s: (1..4001),
}
}

fn range_mut(&mut self, property: &Property) -> &mut Range<u32> {
match property {
Property::X => &mut self.x,
Property::M => &mut self.m,
Property::A => &mut self.a,
Property::S => &mut self.s,
}
}

fn subtract(&mut self, condition: &Condition) {
let range = self.range_mut(&condition.property);

match condition.ordering {
Ordering::Less => {
if range.start < condition.cmp_value {
range.start = condition.cmp_value;
}
}
Ordering::Greater => {
if range.end > condition.cmp_value + 1 {
range.end = condition.cmp_value + 1;
}
}
_ => panic!("Invalid ordering"),
}
}

fn add(&mut self, condition: &Condition) {
let range = self.range_mut(&condition.property);

match condition.ordering {
Ordering::Less => {
if range.end > condition.cmp_value {
range.end = condition.cmp_value;
}
}
Ordering::Greater => {
if range.start <= condition.cmp_value {
range.start = condition.cmp_value + 1;
}
}
_ => panic!("Invalid ordering"),
}

if range.start.cmp(&condition.cmp_value) != condition.ordering {
range.start = condition.cmp_value;
}
}

fn count(&self) -> u64 {
self.x.len() as u64 * self.m.len() as u64 * self.a.len() as u64 * self.s.len() as u64
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -224,6 +345,6 @@ mod tests {
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
assert_eq!(result, Some(167409079868000));
}
}

0 comments on commit 7cc833b

Please sign in to comment.