aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day07/solver.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'AoC2023/day07/solver.lisp')
-rw-r--r--AoC2023/day07/solver.lisp80
1 files changed, 80 insertions, 0 deletions
diff --git a/AoC2023/day07/solver.lisp b/AoC2023/day07/solver.lisp
new file mode 100644
index 0000000..3a1fe8a
--- /dev/null
+++ b/AoC2023/day07/solver.lisp
@@ -0,0 +1,80 @@
+(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")))))