reimplement day21 but still stuck

This commit is contained in:
Peter Tillemans 2024-12-22 23:45:11 +01:00
parent 28881608de
commit 669e47f572
2 changed files with 252 additions and 132 deletions

View file

@ -9,15 +9,16 @@
#:part2
#:key-to-pos
#:press-key
#:type-code
#:type-manual
#:complexity
#:combinations
#:press-key-combinations
#:path-invalid-p
#:easiest-to-type
#:easy-key-combinations
#:easy-type-code
#:decode
#:decode3
#:fewest-presses
#:fill-leg-table
))
(in-package :aoc/2024/21)
@ -71,121 +72,6 @@
;; - sum it.
(defun key-to-pos (c)
(cond
((eq c #\0) (make-pos :x 1 :y 0))
((eq c #\A) (make-pos :x 2 :y 0))
((eq c #\^) (make-pos :x 1 :y 0))
((eq c #\<) (make-pos :x 0 :y 1))
((eq c #\v) (make-pos :x 1 :y 1))
((eq c #\>) (make-pos :x 2 :y 1))
((digit-char-p c) (make-pos
:x (mod (1- (digit-char-p c)) 3)
:y (floor (/ (+ 2 (digit-char-p c)) 3))))
(t nil)))
(defun press-key (start target &optional (numeric t))
(let ((diff (pos-subtract
(key-to-pos target)
(key-to-pos start))))
(coerce
(append
(loop for x from 0 below (pos-x diff) collect #\>)
(loop for y from 0 below (pos-y diff) collect (if numeric #\^ #\v))
(loop for y from 0 below (- (pos-y diff)) collect (if numeric #\v #\^))
(loop for x from 0 below (- (pos-x diff)) collect #\<)
'(#\A))
'string)))
(defun type-code (code &optional (numeric t))
(let ((keys (coerce code 'list)))
(format
nil "~{~A~}"
(loop
for start in (cons #\A keys)
for target in keys
collect (press-key start target numeric)))))
(defun combinations (as bs &optional (acc '()))
(cond
((emptyp as) (list (append bs acc)))
((emptyp bs) (list (append as acc)))
(t (append
(combinations (cdr as) bs (cons (car as) acc))
(combinations as (cdr bs) (cons (car bs) acc))))))
(defun pos-step (pos c &optional (numeric t))
(case c
((#\< #\>) (pos-move pos c))
(#\^ (pos-move pos (if numeric #\v #\^)))
(#\v (pos-move pos (if numeric #\^ #\v)))))
(defun path-invalid-p (start moves &optional (numeric t))
(loop
for dir in moves
for pos = (pos-step (or pos start) dir numeric)
thereis (and (zerop (pos-x pos)) (zerop (pos-y pos)))))
(defun press-key-combinations (start target &optional (numeric t))
(let* ((start-pos (key-to-pos start))
(diff (pos-subtract
(key-to-pos target)
start-pos))
(hp (loop
for x from 0 below (abs (pos-x diff))
collect (if (plusp (pos-x diff)) #\> #\<)))
(vp (loop
for y from 0 below (abs (pos-y diff))
collect (if (equal numeric (plusp (pos-y diff))) #\^ #\v)))
)
(mapcar
#'(lambda (c) (coerce (append c '(#\A)) 'string))
(remove-if
#'(lambda (moves) (path-invalid-p start-pos moves))
(combinations hp vp)))
))
(defun easiest-to-type (codes &optional (numeric t))
(format t "~A ~A~%" codes numeric)
(let ((min-taps (loop
for code in codes
minimize (length (type-code (type-code code t) nil)))))
(loop
for code in codes
if (= min-taps (length (type-code (type-code code numeric))))
collect code)))
(defun easy-key-combinations (start target &optional (numeric t))
(easiest-to-type
(press-key-combinations start target numeric)
t))
(defun type-numpad (code)
(let ((keys (coerce code 'list)))
(format nil "~{~A~}"
(loop
for start in (cons #\A keys)
for target in keys
collect (first (easy-key-combinations start target t))))))
(defun type-dirpads (code n)
(loop
for i from 1 to n
do (setf code (type-code code nil))
finally (return code)))
(defun type-manual (code n)
(type-dirpads (type-numpad code) n))
(defun complexity (code n)
(let ((l (length (type-manual code n)))
(v (parse-integer (ppcre:scan-to-strings "\\d+" code))))
(* l v)))
(defun pos-to-key (pos &optional (numeric t))
(cond
((zerop (pos-y pos)) (if numeric
@ -226,17 +112,248 @@
nil)
t))
(defun part1 (data)
(defun decoden (code n numeric)
(if (zerop n)
(decode code numeric)
(decode (decoden code (1- n) nil) numeric))
)
(defun key-to-pos (c)
(cond
((eq c #\0) (make-pos :x 1 :y 0))
((eq c #\A) (make-pos :x 2 :y 0))
((eq c #\^) (make-pos :x 1 :y 0))
((eq c #\<) (make-pos :x 0 :y 1))
((eq c #\v) (make-pos :x 1 :y 1))
((eq c #\>) (make-pos :x 2 :y 1))
((digit-char-p c) (make-pos
:x (mod (1- (digit-char-p c)) 3)
:y (floor (/ (+ 2 (digit-char-p c)) 3))))
(t nil)))
(defun press-key (start target &optional (numeric t))
(let ((diff (pos-subtract
(key-to-pos target)
(key-to-pos start))))
(coerce
(append
(loop for x from 0 below (pos-x diff) collect #\>)
(loop for y from 0 below (pos-y diff) collect (if numeric #\^ #\v))
(loop for y from 0 below (- (pos-y diff)) collect (if numeric #\v #\^))
(loop for x from 0 below (- (pos-x diff)) collect #\<)
'(#\A))
'string)))
(defun pos-step (pos c &optional (numeric t))
(case c
((#\< #\>) (pos-move pos c))
(#\^ (pos-move pos (if numeric #\v #\^)))
(#\v (pos-move pos (if numeric #\^ #\v)))))
(defun path-invalid-p (start moves &optional (numeric t))
(loop
for dir in moves
for pos = (pos-step (or pos start) dir numeric)
thereis (and (zerop (pos-x pos)) (zerop (pos-y pos)))))
(defun press-key-combinations (start target &optional (numeric t))
(let* ((start-pos (key-to-pos start))
(diff (pos-subtract
(key-to-pos target)
start-pos))
(hp (loop
for x from 0 below (abs (pos-x diff))
collect (if (plusp (pos-x diff)) #\> #\<)))
(vp (loop
for y from 0 below (abs (pos-y diff))
collect (if (equal numeric (plusp (pos-y diff))) #\^ #\v)))
)
(mapcar
#'(lambda (moves) (coerce (append moves '(#\A)) 'string))
(remove-if
#'(lambda (moves) (path-invalid-p start-pos moves))
(list
(append hp vp)
(append vp hp))))
)
)
(defparameter *tl-cache* (make-hash-table :test #'equal))
(defun reset-cache ()
(setf *tl-cache* (make-hash-table :test #'equal)))
(defun _type-length (code level numeric)
(if (zerop level)
(length code)
(loop
for part in (list code)
sum (let ((keys (coerce code 'list)))
(loop
for start in (cons #\A keys)
for target in keys
sum (loop
for c in (press-key-combinations start target numeric)
minimizing (type-length c (1- level) nil)
)))
)
)
)
(defun type-length (code level numeric)
(multiple-value-bind (v found) (gethash (cons code level) *tl-cache*)
(if found
v
(let ((l (_type-length code level numeric)))
(setf (gethash (cons code level) *tl-cache*) l) ))))
(defun print-lengths (data)
(reset-cache)
(loop
for n from 1 to 26
do (format t "~%n: ~A~%" n)
(loop
for code in data
sum (complexity code 2)))
do (format t "~15A~%" (type-length code n t))
)))
(defparameter dir-map
(make-array
'(2 3) :initial-contents
#(
#(#\SPACE #\^ #\A)
#( #\< #\v #\>)
)))
(defparameter num-map
(make-array
'(4 3)
:initial-contents
#(
#(#\7 #\8 #\9)
#(#\4 #\5 #\6)
#(#\1 #\2 #\3)
#(#\SPACE #\0 #\A))))
(defun dir-pos (c)
(car (loop
for x from 0 below (array-dimension dir-map 1)
append (loop
for y from 0 below (array-dimension dir-map 0)
if (eq c (aref dir-map y x))
collect (cons x y)))))
(defun num-pos (c)
(car (loop
for x from 0 below (array-dimension num-map 1)
append (loop
for y from 0 below (array-dimension num-map 0)
if (eq c (aref num-map y x))
collect (cons x y)))))
(defvar leg-lengths (make-hash-table :test #'equal))
(defun fewest-presses (layer ks)
(loop
for ki in (cons #\A (coerce ks 'list))
for kf in (coerce ks 'list)
sum (let ((ll (gethash (list layer ki kf) leg-lengths)))
ll)))
(defun fill-leg-table (n-robots)
(setf leg-lengths (make-hash-table :test #'equal))
(loop
for ki from 0 below (array-total-size dir-map)
do (loop
for kf from 0 below (array-total-size dir-map)
do (setf
(gethash
(list
0
(row-major-aref dir-map ki)
(row-major-aref dir-map kf))
leg-lengths)
1)
))
(loop
for layer from 1 to n-robots
do (let* ((key-map (if (= layer n-robots) num-map dir-map))
(key-pos (if (= layer n-robots) #'num-pos #'dir-pos))
(space-pos (funcall key-pos #\SPACE)))
(loop
for i from 0 below (array-total-size key-map)
for ki = (row-major-aref key-map i)
for pos-i = (funcall key-pos ki)
for xi = (car pos-i)
for yi = (cdr pos-i)
do (loop
for j from 0 below (array-total-size key-map)
for kf = (row-major-aref key-map j)
for pos-f = (funcall key-pos kf)
for xf = (car pos-f)
for yf = (cdr pos-f)
do (let* (
(dx (- xf xi))
(dy (- yf yi))
(hp (loop
for x from 0 below (abs dx)
collect (if (plusp dx) #\> #\<)))
(vp (loop
for y from 0 below (abs dy)
collect (if (minusp dy) #\^ #\v)))
(hf (coerce (append hp vp '(#\A)) 'string))
(h-first (if (equal (cons xf yi) space-pos)
999
(fewest-presses (1- layer) hf)))
(vf (coerce (append vp hp '(#\A)) 'string))
(v-first (if (equal (cons xi yf) space-pos)
999
(fewest-presses (1- layer) vf))))
;;(format t "h ~A ~A ~A ~A~%" xi yf hf h-first)
;;(format t "v ~A ~A ~A ~A~%" xf yi vf v-first)
;;(format t "ll[~A ~A ~A] ~A~%" layer ki kf (min h-first v-first))
(setf
(gethash (list layer ki kf) leg-lengths)
(min h-first v-first)))))
))
)
(defun complexity (code n)
(let ((l (fewest-presses n code))
(v (parse-integer (ppcre:scan-to-strings "\\d+" code))))
(* l v)))
(defun print-llengths (data)
(reset-cache)
(loop
for n from 1 to 26
do (format t "~%n: ~A~%" n)
(fill-leg-table n)
(loop
for code in data
do (format t "~15A~%" (fewest-presses n code))
)))
(defun part1 (data)
(fill-leg-table 3)
(loop
for code in data
sum (complexity code 3)))
(defun part2 (data)
(fill-leg-table 26)
(loop
for code in data
sum (complexity code 25)))
sum (complexity code 26)))
(defun solve-day ()
(reset-cache)
(format t "part1: ~A~%" (part1 input-data))
(format t "part2: ~A~%" (part2 input-data)))

View file

@ -37,23 +37,26 @@
(define-test test-complexity
:parent suite-2024-21
(is = (* 68 29) (complexity "029A" 2))
(is = (* 60 980) (complexity "980A" 2))
(is = (* 68 179) (complexity "179A" 2))
(is = (* 64 456) (complexity "456A" 2))
(is = (* 64 379) (complexity "379A" 2)))
(is = (* 68 29) (complexity "029A" 3))
(is = (* 60 980) (complexity "980A" 3))
(is = (* 68 179) (complexity "179A" 3))
(is = (* 64 456) (complexity "456A" 3))
(is = (* 64 379) (complexity "379A" 3)))
(define-test test-manual
(define-test test-fewest-presses
:parent suite-2024-21
(is equal
"<v<A>>^AvA^A<vA<AA>>^AAvA<^A>AAvA^A<vA>^AA<A>A<v<A>A>^AAAvA<^A>A"
(type-manual "379A" 2)))
(fill-leg-table 3)
(is = 68 (fewest-presses 3 "029A"))
(is = 60 (fewest-presses 3 "980A"))
(is = 68 (fewest-presses 3 "179A"))
(is = 64 (fewest-presses 3 "456A"))
(is = 64 (fewest-presses 3 "379A")))
(define-test+run test-part1
:parent suite-2024-21
(is equal 126384 (part1 sample-data)))
(define-test+run test-part2
:parent suite-2024-21
(is equal nil (part2 sample-data)))
;; 143919110618572
;; 167389793580400