Advertisement
musifter

AoC 2021 day 16 (Smalltalk)

Dec 16th, 2021
2,173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. Collection extend [
  4.     sum   [ ^self inject: 0 into: [:a : b | a + b] ]
  5.     prod  [ ^self inject: 1 into: [:a : b | a * b] ]
  6.  
  7.     min   [ ^self inject: self first into: [:a :b | a min: b] ]
  8.     max   [ ^self inject: self first into: [:a :b | a max: b] ]
  9.  
  10.     greater  [ ^(self first > self second) asCBooleanValue ]
  11.     less     [ ^(self first < self second) asCBooleanValue ]
  12.     equal    [ ^(self first = self second) asCBooleanValue ]
  13. ]
  14.  
  15. Integer extend [
  16.     timesCollect: aBlock  [ ^(1 to: self) collect: [:x | aBlock value] ]
  17. ]
  18.  
  19. String extend [
  20.     asRadix: rad [ ^Number readFrom: (ReadStream on: self) radix: rad ]
  21. ]
  22.  
  23. Object subclass: BitStream [
  24.     | bits bitStream |
  25.  
  26.     BitStream class >> on: bitString [
  27.         ^super new init: bitString
  28.     ]
  29.  
  30.     init: bitString [
  31.         bits      := bitString.
  32.         bitStream := ReadStream on: bits.
  33.         ^self
  34.     ]
  35.  
  36.     " Streamlike access methods "
  37.     atEnd  [ ^bitStream atEnd ]
  38.  
  39.     next             [ ^bitStream next digitValue        ]
  40.     next: num        [ ^(bitStream next: num) asRadix: 2 ]
  41.     nextString: num  [ ^bitStream next: num              ]
  42.  
  43.     " Read an extended literal value from the stream: "
  44.     readExtended [
  45.         | ret extend |
  46.         ret := 0.
  47.         [
  48.             extend := self next.
  49.             ret := ret * 16 + (self next: 4).
  50.             (extend = 1)
  51.         ] whileTrue.
  52.  
  53.         ^ret
  54.     ]
  55. ]
  56.  
  57. Object subclass: PacketReader [
  58.     | bits verSum |
  59.  
  60.     operators := Dictionary from: {
  61.                      0 -> #sum.
  62.                      1 -> #prod.
  63.                      2 -> #min.
  64.                      3 -> #max.
  65.                      5 -> #greater.
  66.                      6 -> #less.
  67.                      7 -> #equal.
  68.                  }.
  69.  
  70.     PacketReader class >> on: bitStream [
  71.         ^super new init: bitStream
  72.     ]
  73.  
  74.     init: bitStream [
  75.         bits   := bitStream.
  76.         verSum := 0.
  77.         ^self
  78.     ]
  79.  
  80.     nextPacket [
  81.         | version type ret |
  82.         " read header "
  83.         verSum := verSum + (bits next: 3).
  84.         type   := bits next: 3.
  85.  
  86.         (type = 4) ifTrue: [
  87.             " read literal "
  88.             ret := bits readExtended.
  89.         ] ifFalse: [
  90.             | lenType vals num |
  91.             " read subpackets "
  92.             lenType := bits next.
  93.  
  94.             (lenType = 0) ifTrue: [
  95.                 | sub |
  96.                 num := bits next: 15.  " num bits to process packets from "
  97.  
  98.                 sub    := PacketReader on: (BitStream on: (bits nextString: num)).
  99.                 vals   := sub parsePackets.
  100.                 verSum := verSum + sub versionSum.
  101.  
  102.             ] ifFalse: [
  103.                 num  := bits next: 11. " num packets to collect "
  104.                 vals := num timesCollect: [self nextPacket].
  105.             ].
  106.  
  107.             ret := vals perform: (operators at: type).
  108.         ].
  109.         ^ret
  110.     ]
  111.  
  112.     parsePackets [
  113.         | vals |
  114.         vals := OrderedCollection new.
  115.         [ bits atEnd not ] whileTrue: [
  116.             vals add: self nextPacket.
  117.         ].
  118.         ^vals
  119.     ]
  120.  
  121.     versionSum  [ ^verSum ]
  122. ]
  123.  
  124. "
  125. | Mainline
  126. "
  127. input := stdin nextLine.
  128.  
  129. " Convert hex string into a bit string: "
  130. bitString := ((input asRadix: 16) radix: 2) allButFirst: 2.
  131.  
  132. " Add padding if needed: "
  133. padding := ((input findFirst: [:chr | chr ~= $0]) - 1) * 4.  " lead zeros "
  134. padding := padding + ((4 - bitString size) \\ 4).            " lead zeros in first nybble "
  135. bitString := (String new: padding withAll: $0), bitString.
  136.  
  137. reader := PacketReader on: (BitStream on: bitString).
  138. value  := reader nextPacket.
  139.  
  140. ('Part 1: %1' % {reader versionSum}) displayNl.
  141. ('Part 2: %1' % {value}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement