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] ]
- Collection extend [ min [^self fold: [:a :b | a min: b]] ]
- Character extend [ + num [^self value + num] ]
- Integer extend [
- >> shift [^self bitShift: shift negated]
- << shift [^self bitShift: shift]
- ]
- Object subclass: VirtualMachine [
- | ip reg code buff |
- opcodes := Dictionary from: { 0 -> #adv:. 1 -> #bxl:. 2 -> #bst:. 3 -> #jnz:.
- 4 -> #bxc:. 5 -> #out:. 6 -> #bdv:. 7 -> #cdv: }.
- VirtualMachine class >> new: codeArray [^super new init: codeArray]
- init: codeArray [code := codeArray. ^self]
- " Code to run machine, with regA set, halting when haltOp is reached "
- run: regA halt: haltOp [
- | out inst |
- ip := 1.
- reg := Dictionary from: {#A -> regA. #B -> 0. #C -> 0}.
- buff := OrderedCollection new.
- [(ip < code size) and: [haltOp ~= (inst := opcodes at: (code at: ip))]] whileTrue: [
- self perform: inst with: (code at: ip+1).
- ip := ip + 2.
- ].
- ^buff
- ]
- " #nop is not a machine code, so this only halts when ip >= code size "
- run: regA [^self run: regA halt: #nop]
- " combo operand referencing: "
- combo: op [
- ^(op >= 4) ifTrue: [reg at: ($A + (op - 4)) asCharacter asSymbol]
- ifFalse: [op]
- ]
- " Op codes: "
- adv: op [reg at: #A put: ((reg at: #A) >> (self combo: op))]
- bdv: op [reg at: #B put: ((reg at: #A) >> (self combo: op))]
- cdv: op [reg at: #C put: ((reg at: #A) >> (self combo: op))]
- bxl: op [reg at: #B put: ((reg at: #B) bitXor: op)]
- bxc: op [reg at: #B put: ((reg at: #B) bitXor: (reg at: #C))]
- bst: op [reg at: #B put: ((self combo: op) \\ 8)]
- out: op [buff add: ((self combo: op) \\ 8)]
- jnz: op [((reg at: #A) ~= 0) ifTrue: [ip := op - 1]]
- ]
- "
- | Mainline
- "
- para := stdin contents tokenize: '\n\n'.
- numbers := para collect: [:p | ((p tokenize: '[^0-9]') reject: #isEmpty) collect: #asNumber].
- regs := numbers first.
- code := numbers second.
- vm := VirtualMachine new: code.
- " Part 1: "
- part1 := vm run: (regs first).
- ('Part 1: %1' % {(part1 collect: #asString) join: ','}) displayNl.
- " Part 2: "
- possible := Set with: 0.
- (code reverse) do: [:digit |
- next := Set new.
- possible do: [:prev |
- base := prev << 3.
- next addAll: ((base to: base+7) select: [:a | (vm run: a halt: #jnz) first == digit]).
- ].
- possible := next.
- ].
- ('Part 2: %1' % {possible min}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement