Advertisement
musifter

AoC 2023 day 20 (Smalltalk)

Dec 21st, 2023
1,247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 3.42 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. Symbol extend [ value: arg [^arg perform: self] ]
  4.  
  5. "
  6. |  Classes for circuit components
  7. "
  8. Object subclass: Gate [  " Virtual parent class "
  9.     | out in |
  10.     Gate class >> new  [ ^super new gateInit ]
  11.     gateInit [ in := Set new. out := Set new. ^self ]
  12.  
  13.     addOuts: array  [ ^out := array asSet ]
  14.     getOuts         [ ^out                ]
  15.     addIn: name     [ ^in add: name       ]
  16.     getIns          [ ^in                 ]
  17.  
  18.     pulse: level from: src  [ ^self NotImplemented ]
  19. ]
  20.  
  21. Gate subclass: FlipFlop  [
  22.     | state |
  23.     FlipFlop class >> new  [ ^(super new) init     ]
  24.     init                   [ state := false. ^self ]
  25.  
  26.     setState: level [ ^state := level ]
  27.     printOn: stream [ stream nextPutAll: ('FlipFlop (%1)' % {state}) ]
  28.  
  29.     pulse: level from: src [
  30.         level ifFalse: [ ^state := state not ].
  31.         ^nil
  32.     ]
  33. ]
  34.  
  35. Gate subclass: NANDGate [
  36.     NANDGate class >> new  [ ^(super new) init           ]
  37.     init                   [ in := Dictionary new. ^self ]
  38.  
  39.     printOn: stream [ stream nextPutAll: ('NANDGate (%1)' % {in}) ]
  40.  
  41.     addIn: name  [ ^in at: name put: false ]
  42.     getIns       [ ^in keys                ]
  43.  
  44.     pulse: level from: src [
  45.         in at: src put: level.
  46.         ^(in values inject: true into: [:a :b | a & b]) not
  47.     ]
  48. ]
  49.  
  50. "
  51. | Mainline
  52. "
  53. input := stdin contents lines collect: [:line | line subStrings: '-> ,' ].
  54.  
  55. " Read in circuit making forward links: "
  56. circuit := Dictionary new.
  57. input do: [ :line |
  58.    | gate name |
  59.     (line first = 'broadcaster') ifTrue: [
  60.         gate := circuit at: #broadcaster put: FlipFlop new.
  61.  
  62.     ] ifFalse: [
  63.         name := line first allButFirst asSymbol.
  64.         (line first first = $%) ifTrue: [
  65.             gate := circuit at: name put: FlipFlop new.
  66.         ] ifFalse: [
  67.             gate := circuit at: name put: NANDGate new.
  68.         ]
  69.     ].
  70.  
  71.     gate addOuts: (line allButFirst collect: #asSymbol).
  72. ].
  73.  
  74. " Add back links: "
  75. circuit keys do: [ :src |
  76.     (circuit at: src) getOuts do: [ :dest |
  77.        | gate |
  78.         gate := circuit at: dest ifAbsent: [circuit at: dest put: FlipFlop new].
  79.         gate ifNotNil: [ gate addIn: src ]
  80.     ]
  81. ].
  82.  
  83. pulses := Bag new.
  84.  
  85. collectors := (circuit at: ((circuit at: #rx) getIns anyOne)) getIns.
  86. cycle := OrderedCollection new.
  87.  
  88. " Run machine: "
  89. (1 to: 4096) do: [ :press |
  90.     ((press \\ 100) = 0) ifTrue: [
  91.         stderr nextPutAll: ('Press: %1' % {press}) displayString; cr; flush.
  92.     ].
  93.  
  94.     (circuit at: #broadcaster) setState: true.
  95.     queue := OrderedCollection with: {false. #button. #broadcaster}.
  96.  
  97.     [queue isEmpty] whileFalse: [
  98.         signal := queue removeFirst.
  99.         level := signal first.
  100.         src   := signal second.
  101.         curr  := signal third.
  102.  
  103.         "('%1 -%<high|low>2-> %3' % {src. level. curr}) displayNl."
  104.         pulses add: level.
  105.  
  106.         send := (circuit at: curr) pulse: level from: src.
  107.  
  108.         ((collectors includes: curr) and: [send]) ifTrue: [cycle add: press].
  109.  
  110.         send ifNotNil: [
  111.             outs := (circuit at: curr) getOuts.
  112.             queue addAll: (outs collect: [:next | {send. curr. next}])
  113.         ]
  114.     ].
  115.  
  116.     (press = 1000) ifTrue: [
  117.         part1 := (pulses occurrencesOf: true) * (pulses occurrencesOf: false).
  118.         ('Part 1: %1' % {part1}) displayNl.
  119.     ].
  120. ].
  121.  
  122. part2 := cycle fold: [:a :b | a lcm: b].
  123. ('Part 2: %1' % {part2}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement