changeset 28:5ba34a851816

Implement Day 19 workflows, skip part 2
author IBBoard <dev@ibboard.co.uk>
date Wed, 03 Jan 2024 11:34:54 +0000
parents 6b58ddfaed38
children 739415015d27
files day19.rb day19.txt
diffstat 2 files changed, 105 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day19.rb	Wed Jan 03 11:34:54 2024 +0000
@@ -0,0 +1,60 @@
+#! /usr/bin/env ruby
+
+if ARGV.length != 1
+        abort("Incorrect arguments - needs input file")
+elsif not File.exist? (ARGV[0])
+	abort("File #{ARGV[0]} did not exist")
+end
+
+file = ARGV[0]
+
+workflows = Hash.new
+Workflow = Struct.new(:name, :rules)
+Rule = Struct.new(:filter, :next)
+Filter = Struct.new(:field, :comparison, :value)
+objects = Array.new
+Object = Struct.new(:x, :m, :a, :s)
+
+File.open(file, "r").each_line(chomp: true) do |line|
+        if line == ""
+                next
+        end
+        bracket_pos = line.index("{")
+        if bracket_pos == 0
+                # Parse an object
+                match = line.match("\{x=([0-9]+),m=([0-9]+),a=([0-9]+),s=([0-9]+)\}")
+                objects << Object.new(x=match[1].to_i, m=match[2].to_i, a=match[3].to_i, s=match[4].to_i)
+        else
+                # Parse a workflow
+                workflow_name = line[0,bracket_pos]
+                rules = line[(bracket_pos+1)..-2].split(",").map do |rule|
+                        rule_parts = rule.split(":")
+                        if rule_parts.length > 1
+                                rule, next_workflow = rule_parts
+                                filter = Filter.new(rule[0].to_sym, rule[1].to_sym, rule[2..-1].to_i)
+                                Rule.new(filter, next_workflow)
+                        else
+                                Rule.new(Filter.new(:a, ">".to_sym, -1), rule_parts[0])
+                        end
+                end
+                workflows[workflow_name] = Workflow.new(name=workflow_name, rules=rules)
+        end
+end
+
+filtered_objects = objects.map do |obj|
+        workflow_name = "in"
+        while workflow_name != "R" and workflow_name != "A"
+                workflow = workflows[workflow_name]
+                workflow.rules.each do |rule|
+                        puts rule
+                        filter = rule.filter
+                        if obj.public_send(filter.field).public_send(filter.comparison, filter.value)
+                                workflow_name = rule.next
+                                break
+                        end
+                end
+        end
+        obj if workflow_name == "A"
+end.reject(&:nil?)
+puts "#{filtered_objects.to_a}"
+puts "#{filtered_objects.reduce(0) {|accum, obj| accum + obj.x + obj.m + obj.a + obj.s}}"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day19.txt	Wed Jan 03 11:34:54 2024 +0000
@@ -0,0 +1,45 @@
+--- Day 19: Aplenty ---
+
+Objects have three values - x, m, a and s.
+
+There are a number of workflows, which have a name and a set of rules.
+Each rule specifies a condition and the name of the next step.
+The first step is "in". The last steps are "A" (accepted) and "R" (rejected).
+Once it matches a rule in a workflow, no further rules in the workflow are evaluated.
+
+The input is a set of workflows, a blank line, and a set of objects.
+
+px{a<2006:qkq,m>2090:A,rfg}
+pv{a>1716:R,A}
+lnx{m>1548:A,A}
+rfg{s<537:gd,x>2440:R,A}
+qs{s>3448:A,lnx}
+qkq{x<1416:A,crn}
+crn{x>2662:A,R}
+in{s<1351:px,qqz}
+qqz{s>2770:qs,m<1801:hdj,R}
+gd{a>3333:R,R}
+hdj{m>838:A,pv}
+
+{x=787,m=2655,a=1222,s=2876}
+{x=1679,m=44,a=2067,s=496}
+{x=2036,m=264,a=79,s=2244}
+{x=2461,m=1339,a=466,s=291}
+{x=2127,m=1623,a=2188,s=1013}
+
+
+These five parts would go:
+
+    {x=787,m=2655,a=1222,s=2876}: in -> qqz -> qs -> lnx -> A
+    {x=1679,m=44,a=2067,s=496}: in -> px -> rfg -> gd -> R
+    {x=2036,m=264,a=79,s=2244}: in -> qqz -> hdj -> pv -> A
+    {x=2461,m=1339,a=466,s=291}: in -> px -> qkq -> crn -> R
+    {x=2127,m=1623,a=2188,s=1013}: in -> px -> rfg -> A
+
+The sum of the sum of the x, m, a and s scores for the accepted parts is 19114.
+
+--- Part Two ---
+
+Each value can be in the range 1 to 4000. In the example input,
+there are 167409079868000 combinations of values that would be accepted.
+No information is given about what this means or how it is calculated.
\ No newline at end of file