Compare commits
No commits in common. "5926b5cd3f563f6fc92e7e264aafe00e61a5f2e0" and "ae69d78d643630b565868b380771500cdca2f61b" have entirely different histories.
5926b5cd3f
...
ae69d78d64
2 changed files with 90 additions and 25 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
(defpackage :aoc/2024/19
|
(defpackage :aoc/2024/19
|
||||||
(:use :cl :aoc :alexandria :trivia :lla)
|
(:use :cl :aoc :alexandria :trivia :lla)
|
||||||
(:export
|
(:export
|
||||||
|
@ -43,13 +44,72 @@ bbrgwb"))
|
||||||
(defparameter sample-data
|
(defparameter sample-data
|
||||||
(parse-input sample-text))
|
(parse-input sample-text))
|
||||||
|
|
||||||
(defvar *pattern-cache* (make-hash-table :test #'equal))
|
(defstruct node
|
||||||
(defvar *valid-cache* (make-hash-table :test #'equal))
|
name
|
||||||
(defvar *possible-cache* (make-hash-table :test #'equal))
|
terminates
|
||||||
|
next)
|
||||||
|
|
||||||
|
(defun towel-tree (towels word)
|
||||||
|
(let ((towel-tree (make-hash-table))
|
||||||
|
(terminates nil))
|
||||||
|
(loop
|
||||||
|
for towel in towels
|
||||||
|
if (emptyp towel
|
||||||
|
do (setf terminates t)
|
||||||
|
else
|
||||||
|
do (setf (gethash (char towel 0) towel-tree)
|
||||||
|
(sort
|
||||||
|
(let ((r (subseq towel 1)))
|
||||||
|
(cons r (gethash (char towel 0) towel-tree)))
|
||||||
|
#'(lambda (a b)
|
||||||
|
(cond
|
||||||
|
((< (length a) (length b)) t)
|
||||||
|
((> (length a) (length b)) nil)
|
||||||
|
(t (string-lessp a b)))
|
||||||
|
))))
|
||||||
|
(loop
|
||||||
|
for k being the hash-keys in towel-tree
|
||||||
|
for v being the hash-values in towel-tree
|
||||||
|
do (setf (gethash k towel-tree) (towel-tree v (concatenate 'string word (list k))))
|
||||||
|
)
|
||||||
|
(make-node
|
||||||
|
:name word
|
||||||
|
:terminates terminates
|
||||||
|
:next towel-tree)))
|
||||||
|
|
||||||
|
(defun show-tree (tree &optional (depth 0))
|
||||||
|
(loop
|
||||||
|
for k being the hash-keys in (node-next tree)
|
||||||
|
for v being the hash-values in (node-next tree)
|
||||||
|
do (format t "~v@{~A~:*~}" depth " ")
|
||||||
|
(format t "~A(~A)~%" k (if (node-terminates v) " OK" ""))
|
||||||
|
(show-tree v (1+ depth))))
|
||||||
|
|
||||||
|
(defun valid-pattern-p-old (og-tree pattern)
|
||||||
|
(defun check (tree pattern word words)
|
||||||
|
(let ((terminate (node-terminates tree)))
|
||||||
|
(if (emptyp pattern)
|
||||||
|
terminate
|
||||||
|
(let* ((c (char pattern 0))
|
||||||
|
(np (subseq pattern 1))
|
||||||
|
(nw (concatenate 'string word (list c))))
|
||||||
|
(or
|
||||||
|
(if-let ((nt (gethash c (node-next tree))))
|
||||||
|
(check nt np nw words))
|
||||||
|
(and terminate
|
||||||
|
(if-let ((nt (gethash c (node-next og-tree))))
|
||||||
|
(check nt np "" (cons word words))
|
||||||
|
))
|
||||||
|
)))))
|
||||||
|
(check og-tree pattern "" '()))
|
||||||
|
|
||||||
|
(defvar *patterns* (make-hash-table :test #'equal))
|
||||||
|
(defvar *valid-patterns* (make-hash-table :test #'equal))
|
||||||
|
(defvar *possible-patterns* (make-hash-table :test #'equal))
|
||||||
(defun reset-patterns ()
|
(defun reset-patterns ()
|
||||||
(setf *pattern-cache* (make-hash-table :test #'equal))
|
(setf *patterns* (make-hash-table :test #'equal))
|
||||||
(setf *valid-cache* (make-hash-table :test #'equal))
|
(setf *valid-patterns* (make-hash-table :test #'equal))
|
||||||
(setf *possible-cache* (make-hash-table :test #'equal))
|
(setf *possible-patterns* (make-hash-table :test #'equal))
|
||||||
)
|
)
|
||||||
|
|
||||||
(defun string-prefix-p (prefix string)
|
(defun string-prefix-p (prefix string)
|
||||||
|
@ -59,20 +119,20 @@ bbrgwb"))
|
||||||
|
|
||||||
(defun remaining-patterns (towels pattern)
|
(defun remaining-patterns (towels pattern)
|
||||||
(or
|
(or
|
||||||
(gethash pattern *pattern-cache*)
|
(gethash pattern *patterns*)
|
||||||
(let ((remaining (loop
|
(let ((remaining (loop
|
||||||
for towel in towels
|
for towel in towels
|
||||||
if (string-prefix-p towel pattern)
|
if (string-prefix-p towel pattern)
|
||||||
collect (subseq pattern (length towel))
|
collect (subseq pattern (length towel))
|
||||||
)))
|
)))
|
||||||
(setf (gethash pattern *pattern-cache*) remaining))))
|
(setf (gethash pattern *patterns*) remaining))))
|
||||||
|
|
||||||
(defun valid-pattern-p (towels pattern)
|
(defun valid-pattern-p (towels pattern)
|
||||||
(multiple-value-bind (is-valid found)
|
(multiple-value-bind (is-valid found)
|
||||||
(gethash pattern *valid-cache*)
|
(gethash pattern *valid-patterns*)
|
||||||
(if found
|
(if found
|
||||||
is-valid
|
is-valid
|
||||||
(setf (gethash pattern *valid-cache*)
|
(setf (gethash pattern *valid-patterns*)
|
||||||
(if (emptyp pattern)
|
(if (emptyp pattern)
|
||||||
t
|
t
|
||||||
(if-let (ps (remaining-patterns towels pattern))
|
(if-let (ps (remaining-patterns towels pattern))
|
||||||
|
@ -86,7 +146,7 @@ bbrgwb"))
|
||||||
(defun towels-to-regex (onsen)
|
(defun towels-to-regex (onsen)
|
||||||
(format nil "^(~{~A~^|~})*$" (onsen-towels onsen)))
|
(format nil "^(~{~A~^|~})*$" (onsen-towels onsen)))
|
||||||
|
|
||||||
(defun valid-cache (onsen)
|
(defun valid-patterns (onsen)
|
||||||
(reset-patterns)
|
(reset-patterns)
|
||||||
(loop
|
(loop
|
||||||
for pattern in (onsen-patterns onsen)
|
for pattern in (onsen-patterns onsen)
|
||||||
|
@ -94,11 +154,12 @@ bbrgwb"))
|
||||||
collect pattern))
|
collect pattern))
|
||||||
|
|
||||||
(defun possible-patterns (towels pattern)
|
(defun possible-patterns (towels pattern)
|
||||||
(multiple-value-bind (n found)
|
(multiple-value-bind (is-valid found)
|
||||||
(gethash pattern *possible-cache*)
|
(gethash pattern *possible-patterns*)
|
||||||
|
(format t "~A ~A ~A~%" pattern is-valid found)
|
||||||
(if found
|
(if found
|
||||||
n
|
(if is-valid 1 0)
|
||||||
(setf (gethash pattern *possible-cache*)
|
(setf (gethash pattern *possible-patterns*)
|
||||||
(if (emptyp pattern)
|
(if (emptyp pattern)
|
||||||
1
|
1
|
||||||
(if-let (ps (remaining-patterns towels pattern))
|
(if-let (ps (remaining-patterns towels pattern))
|
||||||
|
@ -111,14 +172,10 @@ bbrgwb"))
|
||||||
))
|
))
|
||||||
|
|
||||||
(defun part1 (onsen)
|
(defun part1 (onsen)
|
||||||
(format nil "~A" (length (valid-cache onsen))))
|
(format nil "~A" (length (valid-patterns onsen))))
|
||||||
|
|
||||||
(defun part2 (data)
|
(defun part2 (data)
|
||||||
(reset-patterns)
|
(length data))
|
||||||
(format nil "~A"
|
|
||||||
(loop for p in (onsen-patterns data)
|
|
||||||
for n = (possible-patterns (onsen-towels data) p)
|
|
||||||
sum n)))
|
|
||||||
|
|
||||||
(defun solve-day ()
|
(defun solve-day ()
|
||||||
(format t "part1: ~A~%" (part1 input-data))
|
(format t "part1: ~A~%" (part1 input-data))
|
||||||
|
|
|
@ -64,13 +64,21 @@
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(define-test test-bar
|
||||||
|
:parent suite-2024-19
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define-test+run test-part1
|
(define-test+run test-part1
|
||||||
:parent suite-2024-19
|
:parent suite-2024-19
|
||||||
(is equal "6" (part1 sample-data)))
|
(is equal "6" (part1 sample-data)))
|
||||||
|
|
||||||
(define-test+run test-part2
|
(define-test+run test-part2
|
||||||
:parent suite-2024-19
|
:parent suite-2024-19
|
||||||
(is equal "16" (part2 sample-data)))
|
(is equal nil (part2 sample-data)))
|
||||||
|
|
||||||
(defun run-tests ()
|
(defun run-tests ()
|
||||||
(test 'suite-2024-19))
|
(test 'suite-2024-19))
|
||||||
|
|
Loading…
Add table
Reference in a new issue