Advertisement
musifter

AoC 2022, day 14 (smalltalk)

Dec 14th, 2022
2,003
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 2.63 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.  
  7. String extend [
  8.     asPoint [
  9.         | coords |
  10.         coords := self substrings: ','.
  11.         ^coords first asNumber @ coords second asNumber
  12.     ]
  13. ]
  14.  
  15. "
  16. | Cover class for an Array to speed this up.
  17. | Using a Dictionary for the grid takes minutes (with all the garbage collection).
  18. | This gets all the allocation done up front, but puts a hardlimit on the size.
  19. "
  20. Object subclass: RockWall [
  21.     | grid Xstart Xwidth maxY |
  22.  
  23.     RockWall class >> new: maxDepth [
  24.         ^super new init: maxDepth
  25.     ]
  26.  
  27.     init: maxDepth [
  28.         maxY := maxDepth.
  29.         Xstart := 500 - maxY + 1.
  30.         Xwidth := maxY * 2 - 1.
  31.  
  32.         grid := Array new: (Xwidth * maxY) withAll: $..
  33.         ^self
  34.     ]
  35.  
  36.     at: pt           [ ^grid at: pt y * Xwidth + pt x - Xstart + 1 ]
  37.     at: pt put: chr  [ ^grid at: pt y * Xwidth + pt x - Xstart + 1 put: chr ]
  38.  
  39.     printOn: aStream [
  40.         (0 to: maxY - 1) do: [ :y |
  41.             (Xstart to: Xstart + Xwidth - 1) do: [ :x |
  42.                 aStream nextPut: (self at: x @ y).
  43.             ].
  44.             aStream nl.
  45.         ]
  46.     ]
  47. ]
  48.  
  49. "
  50. | Mainline
  51. "
  52. grid := RockWall new: 500.   " 500 should be way more than enough depth "
  53. maxY := 0.
  54.  
  55. " Load rock face: "
  56. stdin linesDo: [ :line |
  57.     corners := (line tokenize: ' -> ') apply: #asPoint.
  58.  
  59.     pos := corners first.
  60.     grid at: pos put: $#.
  61.     maxY := maxY max: pos y.
  62.  
  63.     corners allButFirst do: [ :next |
  64.         delta := (next x - pos x) sign @ (next y - pos y) sign.
  65.  
  66.         [ pos = next ] whileFalse: [
  67.             pos := pos + delta.
  68.             grid at: pos put: $#.
  69.         ].
  70.  
  71.         maxY := maxY max: pos y.
  72.     ].
  73. ].
  74.  
  75. maxY := maxY + 1.                  " Add distance to infinite floor "
  76. prec := { 0 @ 1. -1 @ 1. 1 @ 1 }.  " Order to check for falling sand "
  77.  
  78. path := OrderedCollection with: (500 @ 0).  " Path to avoid redoing work "
  79. sand := 0.
  80.  
  81. " Drop sand: "
  82. [ path notEmpty ] whileTrue: [
  83.     pos := path removeLast.
  84.  
  85.     falling := true.
  86.     [ falling and: [pos y < maxY] ] whileTrue: [
  87.         fall := prec detect: [:dir | (grid at: pos + dir) = $.] ifNone: [nil].
  88.  
  89.         (fall) ifNil:    [ falling := false ]
  90.                ifNotNil: [ path add: pos. pos := pos + fall ].
  91.     ].
  92.  
  93.     grid at: pos put: $o.
  94.     (part1 isNil and: [pos y = maxY]) ifTrue: [ part1 := sand ].
  95.  
  96.     sand := sand + 1.
  97.     (sand \\ 1000 = 0) ifTrue: [
  98.         stderr nextPutAll: ('Sand: %1' % {sand}); cr; flush.
  99.     ]
  100. ].
  101.  
  102. ('Part 1: %1 ' % {part1}) displayNl.
  103. ('Part 2: %1' % {sand}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement