Untitled

mail@pastecode.io avatar
unknown
lisp
6 months ago
3.0 kB
1
Indexable
Never
(defun card-value (char)
  (case char
    ((?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9) (- char 48))
    ((?T) 10)
    ((?J) 11)
    ((?Q) 12)
    ((?K) 13)
    ((?A) 14)))

(defstruct hand values count-map max bid strength)

(defun n-of-a-kind-p (hand num)
  (some (lambda (n)
          (>= n num))
        (hash-table-values (hand-count-map hand))))

(defun 5-of-a-kind-p (hand) (n-of-a-kind-p hand 5))

(defun 4-of-a-kind-p (hand) (n-of-a-kind-p hand 4))

(defun 3-of-a-kind-p (hand) (n-of-a-kind-p hand 3))

(defun full-house-p (hand)
  (let ((vals (hash-table-values (hand-count-map hand))))
    (and (find 3 vals)
         (find 2 vals))))

(defun 2-pair-p (hand)
  (let ((vals (hash-table-values (hand-count-map hand))))
    (>= (count-if (lambda (n) (>= n 2))
                  vals)
        2)))

(defun 1-pair-p (hand)
  (let ((vals (hash-table-values (hand-count-map hand))))
    (find-if (lambda (n) (>= n 2)) vals)))

(defun less-than-p (card-list card-list2)
  (let ((next-l1 (car card-list))
        (next-l2 (car card-list2)))
    (cond ((null card-list) t)
          ((> next-l1 next-l2) nil)
          ((< next-l1 next-l2) t)
          (t (less-than-p (cdr card-list)
                          (cdr card-list2))))))

(defun strength (hand)
  (cond ((5-of-a-kind-p hand) 6)
        ((4-of-a-kind-p hand) 5)
        ((full-house-p hand) 4)
        ((3-of-a-kind-p hand) 3)
        ((2-pair-p hand) 2)
        ((1-pair-p hand) 1)
        (t 0)))

(defun compare (hand hand2)
  (let ((rank1 (hand-strength hand))
        (rank2 (hand-strength hand2)))
    (cond ((= rank1 rank2) (less-than-p (hand-values hand)
                                        (hand-values hand2)))
          ((< rank1 rank2) t)
          ((> rank1 rank2) nil))))

(defun line->hand (hand-str bid-str)
  (let ((hash (make-hash-table :test #'equal :size 5))
        (bid (string-to-number bid-str)))
    (multiple-value-bind (values max)
        (cl-loop for c across hand-str
                 do (incf (gethash (card-value c) hash 0) 1)
                 maximize (card-value c) into m
                 collect (card-value c) into cards
                 finally (return (values cards m)))
      (let ((hand (make-hand :values values
                             :count-map hash
                             :max max
                             :bid bid)))
        (setf (hand-strength hand) (strength hand))
        hand))))

(defun read-lines (filePath)
  (with-temp-buffer
    (insert-file-contents filePath)
    (split-string (buffer-string) "\n" t)))

(defun help-elves (filepath)
  (let ((hands (cl-loop for (hand-str bid-str)
                        in (mapcar #'split-string (read-lines filepath))
                        collect (line->hand hand-str bid-str) into h
                        finally (return (sort h #'compare)))))
    (cl-loop for i from 1 to (+ 1 (length hands))
             for h in hands
             do              (print (cons h i))
             sum (* (hand-bid h) i))))
Leave a Comment