Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- Symbol extend [ value: arg [^arg perform: self] ]
- "
- | Classes for circuit components
- "
- Object subclass: Gate [ " Virtual parent class "
- | out in |
- Gate class >> new [ ^super new gateInit ]
- gateInit [ in := Set new. out := Set new. ^self ]
- addOuts: array [ ^out := array asSet ]
- getOuts [ ^out ]
- addIn: name [ ^in add: name ]
- getIns [ ^in ]
- pulse: level from: src [ ^self NotImplemented ]
- ]
- Gate subclass: FlipFlop [
- | state |
- FlipFlop class >> new [ ^(super new) init ]
- init [ state := false. ^self ]
- setState: level [ ^state := level ]
- printOn: stream [ stream nextPutAll: ('FlipFlop (%1)' % {state}) ]
- pulse: level from: src [
- level ifFalse: [ ^state := state not ].
- ^nil
- ]
- ]
- Gate subclass: NANDGate [
- NANDGate class >> new [ ^(super new) init ]
- init [ in := Dictionary new. ^self ]
- printOn: stream [ stream nextPutAll: ('NANDGate (%1)' % {in}) ]
- addIn: name [ ^in at: name put: false ]
- getIns [ ^in keys ]
- pulse: level from: src [
- in at: src put: level.
- ^(in values inject: true into: [:a :b | a & b]) not
- ]
- ]
- "
- | Mainline
- "
- input := stdin contents lines collect: [:line | line subStrings: '-> ,' ].
- " Read in circuit making forward links: "
- circuit := Dictionary new.
- input do: [ :line |
- | gate name |
- (line first = 'broadcaster') ifTrue: [
- gate := circuit at: #broadcaster put: FlipFlop new.
- ] ifFalse: [
- name := line first allButFirst asSymbol.
- (line first first = $%) ifTrue: [
- gate := circuit at: name put: FlipFlop new.
- ] ifFalse: [
- gate := circuit at: name put: NANDGate new.
- ]
- ].
- gate addOuts: (line allButFirst collect: #asSymbol).
- ].
- " Add back links: "
- circuit keys do: [ :src |
- (circuit at: src) getOuts do: [ :dest |
- | gate |
- gate := circuit at: dest ifAbsent: [circuit at: dest put: FlipFlop new].
- gate ifNotNil: [ gate addIn: src ]
- ]
- ].
- pulses := Bag new.
- collectors := (circuit at: ((circuit at: #rx) getIns anyOne)) getIns.
- cycle := OrderedCollection new.
- " Run machine: "
- (1 to: 4096) do: [ :press |
- ((press \\ 100) = 0) ifTrue: [
- stderr nextPutAll: ('Press: %1' % {press}) displayString; cr; flush.
- ].
- (circuit at: #broadcaster) setState: true.
- queue := OrderedCollection with: {false. #button. #broadcaster}.
- [queue isEmpty] whileFalse: [
- signal := queue removeFirst.
- level := signal first.
- src := signal second.
- curr := signal third.
- "('%1 -%<high|low>2-> %3' % {src. level. curr}) displayNl."
- pulses add: level.
- send := (circuit at: curr) pulse: level from: src.
- ((collectors includes: curr) and: [send]) ifTrue: [cycle add: press].
- send ifNotNil: [
- outs := (circuit at: curr) getOuts.
- queue addAll: (outs collect: [:next | {send. curr. next}])
- ]
- ].
- (press = 1000) ifTrue: [
- part1 := (pulses occurrencesOf: true) * (pulses occurrencesOf: false).
- ('Part 1: %1' % {part1}) displayNl.
- ].
- ].
- part2 := cycle fold: [:a :b | a lcm: b].
- ('Part 2: %1' % {part2}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement