git.alexw.nyc home about git garden
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
f<< /lib/array.fs
f<< /lib/str.fs

1000 const num-hands 
74 const Joker \ ascii J
0 value jokermode

create scores ," 23456789TJQKA"

: cmp ( n n -- 1/0/-1 ) 2dup > if 2drop 1 exit then < if -1 exit then 0 ;
: cpoint ( c -- n ) >r scores >r begin V1 V2 c@ <> while to1+ V2 repeat V2 scores - 2rdrop ;
: hand-cards< ( a[5b]  a[5b] -- f ) 
  >r >r 
  begin V1 c@ cpoint V2 c@ cpoint cmp dup 0 = while 
  drop to1+ V1 to1+ V2 repeat 1+ 2rdrop ;

\ hand score = 2 digit number: top and 2nd most common value. 
\ eg full house 32, pair 21 
create handbuf 128 allot
: hand ( a[5b] -- u1 u2 ) 
  5 rfor i c@ handbuf + 8b 1+! next 
  \ V1 top V2 second
  1 >r 1 >r 128 for i 
  case 
    Joker = jokermode and? of endof \ skip adding joker
    handbuf + c@ V1 >= of V1 to V2 r@ handbuf + c@ to V1 endof 
    handbuf + c@ V2 >= of r@ handbuf + c@ to V2 endof 
    drop
  endcase next V1 jokermode if handbuf Joker + c@ + then 10 * V2 + 
  dup 61 = if drop 51 then \ Special case: JJJJJ 
  2rdrop handbuf 128 0 fill ; 

\ bet (cell) hand (5 bytes)
3 cells num-hands Array :new structbind Array hands 

: hand< ( a[5b] a[5b] -- f ) 
  >r >r V2 hand V1 hand swap cmp
  case 
    1 = of 1 endof
    -1 = of 0 endof
    drop V2 V1 hand-cards< 
  endcase 2rdrop ;

: insert-hand ( a[5b] u -- ) over >r 
  hands cnt dup 0 swap for2 
  i hands :' cell + V1 swap hand< if drop i break then next 
  1 swap hands :insert !+ 5 move rdrop ;

0 value total
: sum-scores ( -- ) 
   0 hands cnt for2 i hands :' dup @ i 1+ * to+ total cell + 5 next ;

: solve
  f" /aoc/input" 0 to total
  begin file :readline ?dup while 
  c@+ 6 - over 6 + swap parsedec drop insert-hand
  repeat sum-scores ;

: solveb 
  1 to jokermode
  S" J23456789TQKA" 1+ scores 13 move
  hands cnt 0 hands :delete 
  solve ;

solve total . nl>
solveb total . nl>