;; Original: https://www.codewars.com/kata/5270d0d18625160ada0000e4
;;
;;; A dice game played with five six-sided dice. Your mission, should you choose to accept it, is to score a throw according to these rules. You will always be given an array with five six-sided dice values.
;; Three 1's => 1000 points
;; Three 6's =>  600 points
;; Three 5's =>  500 points
;; Three 4's =>  400 points
;; Three 3's =>  300 points
;; Three 2's =>  200 points
;; One   1   =>  100 points
;; One   5   =>   50 point

let dice-game fn [throw] '(
  let bucket $ (list.fold {} fn [acc dice] '(
    let key $ string dice
    if (object.has key acc) $
      object.set key acc (+ (object.get key acc) 1) $
      object.set key acc 1
    acc
  )) throw

  let count-accumulative fn [triple-mod single-mod count] '(
    if (= count 3)  $
         triple-mod $
       (> count 3)  $
         (+ triple-mod (count $> % 3 $> * single-mod)) $
         (count $> % 3 $> * single-mod)
  )

  let three? $ <= 3
  let count-3 $ count-accumulative 1000 100
  let count-5 $ count-accumulative 500 50

  object.fold 0 (fn [acc [dice count]] '(
    + acc (match dice {
            :1 (count-3 count)
            :2 (if (three? count) 200 0)
            :3 (if (three? count) 300 0)
            :4 (if (three? count) 400 0)
            :5 (count-5 count)
            :6 (if (three? count) 600 0)
          })
  )) bucket
)


print "for [ 5 1 3 4 1 ] Expected: 250, got: {dice-game [ 5 1 3 4 1 ]}"
print "for [ 1 1 1 3 1 ] Expected: 1100, got: {dice-game [ 1 1 1 3 1 ]}"
print "for [ 2 4 4 5 4 ] Expected: 450, got: {dice-game [ 2 4 4 5 4 ]}"

