Advertisement
musifter

AoC day 22 (pt2), Smalltalk

Dec 22nd, 2020
2,472
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. Object subclass: Game [
  4.     | deck1 deck2 states |
  5.  
  6.     Game class >> deck1: d1 deck2: d2 [
  7.         ^(super new) deck1: d1 deck2:d2.
  8.     ]
  9.  
  10.     deck1: d1 deck2: d2 [
  11.         deck1  := d1.
  12.         deck2  := d2.
  13.         states := LookupTable new.
  14.         ^self.
  15.     ]
  16.  
  17.     make_hash [
  18.         ^(String join: deck1 separatedBy: ','), ':', (String join: deck2 separatedBy: ',').
  19.     ]
  20.  
  21.     test_loop [
  22.         | hash |
  23.         hash := self make_hash.
  24.         (states keys includes: hash) ifTrue: [ ^true ].
  25.         states at: hash put: 1.
  26.         ^false.
  27.     ]
  28.  
  29.     score [
  30.         | win_deck score |
  31.         score := 0.
  32.         win_deck := (deck1 size > 0) ifTrue: [ deck1 ] ifFalse: [deck2 ].
  33.         win_deck := win_deck collect: [ :c | c asNumber ].
  34.         win_deck reverse keysAndValuesDo: [ :i :v | score := score + (i * v) ].
  35.         ^score.
  36.     ]
  37.  
  38.     play [
  39.         | curr_state win_hand card1 card2 sub new1 new2 |
  40.  
  41.         stdout nextPutAll: '.'; flush.
  42.  
  43.         [(deck1 size > 0) and: [deck2 size > 0]] whileTrue: [
  44.             (self test_loop) ifTrue: [ ^1 ].  " Player 1 wins infinite games "
  45.  
  46.             card1 := deck1 removeFirst asNumber.
  47.             card2 := deck2 removeFirst asNumber.
  48.  
  49.             ((card1 <= deck1 size) and: [card2 <= deck2 size]) ifTrue: [
  50.                 " Recurse into subgame "
  51.                 new1 := deck1 copyFrom: 1 to: card1.
  52.                 new2 := deck2 copyFrom: 1 to: card2.
  53.  
  54.                 sub := Game deck1: new1 deck2: new2.
  55.                 win_hand := sub play.
  56.             ] ifFalse: [
  57.                 win_hand := (card1 > card2) ifTrue: [1] ifFalse: [2].
  58.             ].
  59.  
  60.             (win_hand = 1) ifTrue: [
  61.                 deck1 addLast: card1 asString; addLast: card2 asString.
  62.             ] ifFalse: [
  63.                 deck2 addLast: card2 asString; addLast: card1 asString.
  64.             ].
  65.         ].
  66.  
  67.         ^(deck1 size > 0) ifTrue: [1] ifFalse: [2].
  68.     ]
  69. ]
  70.  
  71. "
  72. |  Mainline
  73. "
  74.  
  75. " Read decks "
  76. section := stdin contents tokenize: '\n\n'.
  77.  
  78. deck1 := ((section first)  tokenize: '\n') asOrderedCollection removeFirst; yourself.
  79. deck2 := ((section second) tokenize: '\n') asOrderedCollection removeFirst; yourself.
  80.  
  81.  
  82. " Play game "
  83. game := Game deck1: deck1 deck2: deck2.
  84.  
  85. stdout nextPutAll: 'Winner: ', game play asString; nl.
  86. stdout nextPutAll: 'Part 1: ', game score asString; nl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement