aboutsummaryrefslogtreecommitdiffstats
path: root/AoC2023/day07/solver.lisp
blob: 3a1fe8a92350541a0f159afd48f7e897e4215ea1 (plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
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")))))