Advertisement
Guest User

Untitled

a guest
Dec 20th, 2023
187
0
212 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 2.74 KB | None | 0 0
  1. data = File.read('input.txt')
  2.  
  3. # initialize the modules.
  4. def initstate(txt)
  5.   modules = txt
  6.     .split("\n")
  7.     .map{_1.split(' -> ')}
  8.     .map{{("%&".include?(_1[0]) ? _1[1..] : _1) =>
  9.       {type: _1[0], state: _1[0] == '&' ? {} : false, targets: _2.split(', ')}}}
  10.     .reduce({}, :merge)
  11.  
  12.   # initialize memory of conjunction modules
  13.   modules.each do |m, v|
  14.     v[:targets].each do |k|
  15.       next if not modules[k]
  16.       modules[k][:state][m] = false if modules[k][:type] == '&'
  17.     end
  18.   end
  19.  
  20.   modules
  21. end
  22.  
  23. def pulse(from, to, signal, modules, q)
  24.   return if not modules[to]
  25.   case modules[to][:type]
  26.   when '&'
  27.     # conjunction
  28.     # remember signal from this input
  29.     modules[to][:state][from] = signal
  30.     # sends high signal by default
  31.     # UNLESS all signals from remembered inputs are high, then low
  32.     signal = modules[to][:state].values.uniq == [true] ? false : true
  33.   when '%'
  34.     # flip flop
  35.     # high pulse does nothing
  36.     return if signal
  37.     # low pulse flips state and sends current state
  38.     modules[to][:state] = !modules[to][:state]
  39.     signal = modules[to][:state]
  40.   when 'b'
  41.     # broadcaster
  42.   end
  43.   modules[to][:targets].each {
  44.     # print to.to_s, " ", signal ? "-high" : "-low" , " -> ", _1, "\n"
  45.     q.push [to, _1, signal]
  46.   }
  47. end
  48.  
  49. def run(txt, cnt, name)
  50.   # part 1
  51.   modules = initstate(txt)
  52.   q = []
  53.   cnthigh = 0
  54.   cntlow = 0
  55.   presses = 0
  56.  
  57.   cnt.times do
  58.     presses += 1
  59.     # count the initial pulse of button press to broadcaster!
  60.     cntlow += 1
  61.     pulse(nil, 'broadcaster', false, modules, q)
  62.     while not q.empty?
  63.       from, to, signal = q.shift
  64.       signal ? cnthigh += 1 : cntlow += 1
  65.       pulse(from, to, signal, modules, q)
  66.       return presses if name and to == name and signal == false
  67.     end
  68.   end
  69.   return cntlow*cnthigh
  70. end
  71.  
  72. # part 1
  73. p run(data, 1000, nil)
  74.  
  75. # Hmmmmm...part 2
  76. # Brute force running the loop doesn't work because it takes too long.
  77. # Instead, notice that rx receives its input from only cx, which is a
  78. # conjunction module that receives its input from four sources: kh,
  79. # lz, tg, and hn. In order for cx to go low and output a low to
  80. # rx, all four of the inputs to cx must go low. Let's look...
  81.  
  82. #p run(data, 5000, "kh")
  83. #p run(data, 5000, "lz")
  84. #p run(data, 5000, "tg")
  85. #p run(data, 5000, "hn")
  86.  
  87. # So each of the four inputs goes low on a cycle. In order for all four
  88. # of them to be low at the same time, they need to align, which happens
  89. # at the lowest common multiple for all of them. Thanks to reddit
  90. # for the hint on how to do all this. Doubt I would have figured it
  91. # out on my own.
  92.  
  93. p [
  94.     run(data, 5000, "kh"),
  95.     run(data, 5000, "lz"),
  96.     run(data, 5000, "tg"),
  97.     run(data, 5000, "hn")
  98.   ].reduce(1, :lcm)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement