Advertisement
musifter

AoC 2023 day 3 (Smalltalk)

Dec 3rd, 2023 (edited)
1,217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 2.35 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. Collection extend [
  4.     apply: method  [ ^self collect: [:x | x perform: method] ]
  5.  
  6.     sum        [ ^self inject: 0 into: [:a :b | a + b] ]
  7.     product    [ ^self inject: 1 into: [:a :b | a * b] ]
  8. ]
  9.  
  10. SequenceableCollection extend [
  11.     " Return a list of ranges of the indices where aBlock is true "
  12.     findRanges: aBlock [
  13.         | res start |
  14.         res   := OrderedCollection new.
  15.         start := 0.
  16.         self keysAndValuesDo: [:i :item |
  17.             (aBlock value: item) ifTrue: [
  18.                 (start = 0)  ifTrue: [ start := i ]
  19.             ] ifFalse: [
  20.                 (start ~= 0) ifTrue: [ res add: (start to: i - 1). start := 0 ].
  21.             ]
  22.         ].
  23.         (start ~= 0) ifTrue: [ res add: (start to: self size) ].
  24.         ^res
  25.     ]
  26. ]
  27.  
  28. "
  29. | Mainline
  30. "
  31. " Load input into OrderedCollection of Strings, adding sentinel ring of . "
  32. grid := (stdin lines contents collect: [:line | '.', line, '.']) asOrderedCollection.
  33. grid addFirst: ($. * grid first size);
  34.      addLast:  ($. * grid first size).
  35.  
  36. part1 := 0.
  37. gears := Dictionary new.
  38.  
  39. " Scan grid "
  40. grid keysAndValuesDo: [ :y :line |
  41.     (line findRanges: [:c | c isDigit]) do: [ :part |
  42.        | range box num foundPart |
  43.         num   := (line atAll: part) asNumber.
  44.         range := part first - 1 to: part last + 1.
  45.  
  46.         " Get the surrounding box for our found number: "
  47.         box := (y-1 to: y+1) collect: [:i | ((grid at: i) atAll: range)].
  48.  
  49.  
  50.         foundPart := false.
  51.         box keysAndValuesDo: [ :i :row |
  52.             row keysAndValuesDo: [ :j :chr |
  53.                 " Any part symbol means this is a valid part number: "
  54.                 (chr isDigit not & (chr ~= $.)) ifTrue: [
  55.                     foundPart := true.
  56.                 ].
  57.  
  58.                 " For gears, add part number to list (tracked by gear location)"
  59.                 (chr = $*) ifTrue: [
  60.                     (gears at: (y + i - 1) @ (range first + j)
  61.                            ifAbsentPut: [OrderedCollection new]) add: num.
  62.                 ].
  63.             ]
  64.         ].
  65.  
  66.         foundPart ifTrue: [ part1 := part1 + num ].
  67.     ]
  68. ].
  69.  
  70. " Valid gears have only two numbers adjacent, multiply those for ratio and sum "
  71. part2 := ((gears select: [:g | g size = 2]) apply: #product) sum.
  72.  
  73. ('Part 1: %1' % {part1}) displayNl.
  74. ('Part 2: %1' % {part2}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement