Mercurial > repos > other > adventofcode2023
diff day20.rb @ 29:739415015d27
Implement Day 20 switches part 1
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Wed, 03 Jan 2024 11:35:22 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/day20.rb Wed Jan 03 11:35:22 2024 +0000 @@ -0,0 +1,73 @@ +#! /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}"