(ql:quickload '(fiveam arrows trivia str)) (defpackage #:day07 (:use #:cl) (:local-nicknames (#:f #:fiveam))) (in-package :day07) (defparameter eg-input "32T3K 765 T55J5 684 KK677 28 KTJJT 220 QQQJA 483") (defun occurences (str) (let ((bag (make-hash-table))) (loop for le across str do (incf (gethash le bag 0))) (sort (alexandria:hash-table-values bag) #'>))) (defun hand-type (str) (trivia:match (occurences str) ((list 5) 5) ((list 4 1) 4) ((list 3 2) 3) ((list 3 1 1) 2) ((list 2 2 1) 1) ((list 2 1 1 1) 0) ((list 1 1 1 1 1) -1))) (defun card-strength (card) (position card "23456789TJQKA")) (defun card-< (a b) (< (card-strength a) (card-strength b))) (defun hand-< (a b) (let ((a-t (hand-type a)) (b-t (hand-type b))) (cond ((< a-t b-t)) ((= a-t b-t) (loop for l across a for s across b unless (eq l s) return (card-< l s)))))) (f:test partial (f:is (equal '(3 1 1) (occurences "QJQAQ"))) (f:is (hand-< "2AAAA" "33332")) (f:is (hand-< "77788" "77888")) (f:is (hand-< "77788" "77778"))) (defun parse-input (str) (let ((data (arrows:->> (ppcre:split "\\s" str) (remove-if #'str:empty?)))) (loop for (hand bid) on data by #'cddr collect (cons hand (parse-integer bid))))) (defun total-win (sorted-hands) (loop for (hand . bid) in sorted-hands for c from 1 sum (* c bid))) (defun solver1 (lines) (arrows:-> (parse-input lines) (sort #'hand-< :key #'car) (total-win))) (f:test solutions (f:is (= 6440 (solver1 eg-input))) (f:is (= 253205868 (solver1 (uiop:read-file-string "input")))))