view day19.rb @ 30:6de4f4d5404d

Implement Day 21 "possible spaces in a maze" Part 2 needs something like "find the repeats and lowest common multiple" that I'm not bothering with
author IBBoard <dev@ibboard.co.uk>
date Wed, 03 Jan 2024 12:01:18 +0000
parents 5ba34a851816
children
line wrap: on
line source

#! /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}}"