Mercurial > repos > other > adventofcode2023
view day20.rb @ 33:676461cc3a70
Day 23 - track segments, not each space
This allows us to explore the branches once then do quicker calculations
for valid route lengths. But still requires exploring 1,262,816 routes
to find the longest!
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 04 Jan 2024 14:52:24 +0000 |
parents | 739415015d27 |
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] FlipFlop = Struct.new(:state, :next) Conjunction = Struct.new(:state, :next) SignalMessage = Struct.new(:source, :state, :target) nodes = Hash.new broadcast = [] File.open(file, "r").each_line(chomp: true) do |line| input, output = line.split(" -> ") outputs = output.split(", ") if input[0] == "&" nodes[input[1..-1]] = Conjunction.new(Hash.new, outputs) elsif input[0] == "%" nodes[input[1..-1]] = FlipFlop.new(false, outputs) else broadcast = outputs end end nodes.each do |node_name, node| node.next.each do |target_name| target_node = nodes[target_name] if target_node.is_a?(Conjunction) target_node.state[node_name] = false end end end button_presses = 1000 high_count = 0 low_count = 0 button_presses.times do |press| low_count += 1 signals = [] processed = [] broadcast.each {|output| signals << SignalMessage.new("broadcast", false, output)} while signals.length > 0 #puts "#{signals}" signal = signals.shift() if signal.state high_count += 1 else low_count += 1 end target = nodes[signal.target] if target.nil? puts "Inactive node '#{signal.target}'" elsif target.is_a?(FlipFlop) # High signals stop here next if signal.state # Low signals affect state target.state = !target.state target.next.each {|output| signals << SignalMessage.new(signal.target, target.state, output)} elsif target.is_a?(Conjunction) target.state[signal.source] = signal.state all_high = target.state.values.all? target.next.each {|output| signals << SignalMessage.new(signal.target, !all_high, output)} end end end puts "Low: #{low_count}; High: #{high_count}; Score: #{low_count * high_count}"