starting day 22

This commit is contained in:
Peter Tillemans 2024-12-22 07:08:37 +01:00
parent 2f24bfbbe7
commit a327aef2bf
9 changed files with 344 additions and 21 deletions

View file

@ -51,6 +51,7 @@
(:file "2024/day19") (:file "2024/day19")
(:file "2024/day20") (:file "2024/day20")
(:file "2024/day21") (:file "2024/day21")
(:file "2024/day22")
))) )))
:description "Advent of Code challenges and solutions." :description "Advent of Code challenges and solutions."
:long-description "Solutions for the AOC challenges." :long-description "Solutions for the AOC challenges."
@ -88,6 +89,7 @@
(:file "2024/day19-test") (:file "2024/day19-test")
(:file "2024/day20-test") (:file "2024/day20-test")
(:file "2024/day21-test") (:file "2024/day21-test")
(:file "2024/day22-test")
))) )))
:description "Test system for aoc" :description "Test system for aoc"
:perform (test-op (op c) (symbol-call :parachute :test :aoc/tests))) :perform (test-op (op c) (symbol-call :parachute :test :aoc/tests)))

View file

@ -1,35 +1,240 @@
(defpackage :aoc/2024/21 (defpackage :aoc/2024/21
(:use :cl :aoc :alexandria :trivia :lla) (:use :cl :aoc
:aoc/maze :alexandria :lla :arrow-macros)
(:export (:export
#:sample-data #:sample-data
#:sample-data2 #:sample-data2
#:part1 #:part1
#:part2 #: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
)) ))
(in-package :aoc/2024/21) (in-package :aoc/2024/21)
(defun parse-line (line) (defun parse-line (line)
line) line)
(defun parse-input (lines) (defun parse-input (lines)
(mapcar #'parse-line lines)) (mapcar #'parse-line lines))
(defparameter input-text (test-input 2024 21)) (defparameter input-text (test-input 2024 21))
(defparameter input-data (parse-input input-text)) (defparameter input-data (parse-input input-text))
(defparameter sample-text (aoc:split-lines "")) (defparameter sample-text (aoc:split-lines "029A
980A
179A
456A
379A"))
(defparameter sample-data (defparameter sample-data
(parse-input sample-text)) (parse-input sample-text))
;; numerical pad:
;; +---+---+---+
;; | 7 | 8 | 9 |
;; +---+---+---+
;; | 4 | 5 | 6 |
;; +---+---+---+
;; | 1 | 2 | 3 |
;; +---+---+---+
;; | 0 | A |
;; +---+---+
;; directional pad:
;; +---+---+
;; | ^ | A |
;; +---+---+---+
;; | < | v | > |
;; +---+---+---+
;;
;; complexity = #moves/actions * numeric part
;;
;; observations:
;; - directional pad looks like an upside down truncated num pad
;; - no questions about the actual keystrokes, only amount
;; - keystrokes = manhattan distance (moves) + action press
;;
;; approach:
;; - ^ = 0; < = 1; v = 2; > = 3 --> dirpad to numpad
;; - 0-9A --> pos
;; - pos differences
;; - manhattan + 1
;; - 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
(case (pos-x pos)
(2 #\A)
(1 #\0)
(0 #\?))
(case (pos-x pos)
(2 #\A)
(1 #\^)
(0 #\?))))
((plusp (pos-y pos)) (if numeric
(digit-char
(+
(* 3 (1- (pos-y pos)))
(1+ (pos-x pos))))
(case (pos-x pos)
(2 #\>)
(1 #\v)
(0 #\<))))
(t #\? ))
)
(defun decode (code &optional (numeric t))
(let ((parts (ppcre:split "A" code))
(pos (key-to-pos #\A)))
(coerce
(loop
for sc in parts
do (loop for c across sc do (setf pos (pos-step pos c numeric)))
collect (pos-to-key pos numeric))
'string)))
(defun decode3 (code)
(decode
(decode
(decode code nil)
nil)
t))
(defun part1 (data) (defun part1 (data)
(length data)) (loop
for code in data
sum (complexity code 2)))
(defun part2 (data) (defun part2 (data)
(length data)) (loop
for code in data
sum (complexity code 25)))
(defun solve-day () (defun solve-day ()
(format t "part1: ~A~%" (part1 input-data)) (format t "part1: ~A~%" (part1 input-data))

42
src/2024/day22.lisp Normal file
View file

@ -0,0 +1,42 @@
(defpackage :aoc/2024/22
(:use :cl :aoc :alexandria :trivia :lla)
(:export
#:sample-data
#:sample-data2
#:part1
#:part2
))
(in-package :aoc/2024/22)
(defun parse-line (line)
line)
(defun parse-input (lines)
(mapcar #'parse-line lines))
(defparameter input-text (test-input 2024 22))
(defparameter input-data (parse-input input-text))
(defparameter sample-text (aoc:split-lines ""))
(defparameter sample-data
(parse-input sample-text))
(defun part1 (data)
(length data))
(defun part2 (data)
(length data))
(defun solve-day ()
(format t "part1: ~A~%" (part1 input-data))
(format t "part2: ~A~%" (part2 input-data)))
(defun submit ()
(let ((p1 (part1 input-data))
(p2 (part2 input-data)))
(if p1 (submit-part1 2024 22 p1))
(if p2 (submit-part2 2024 22 p2))))

View file

@ -8,10 +8,14 @@
#:pos-x #:pos-x
#:pos-y #:pos-y
#:pos-move #:pos-move
#:pos-add
#:pos-subtract
#:show-map #:show-map
#:get-pos #:get-pos
#:set-pos #:set-pos
#:find-tile #:find-tile
#:rotate-left
#:rotate-right
#:manhattan-distance #:manhattan-distance
)) ))
@ -38,6 +42,19 @@
(#\> (make-pos :x (1+ (pos-x pos)) :y (pos-y pos))) (#\> (make-pos :x (1+ (pos-x pos)) :y (pos-y pos)))
)) ))
(defun pos-add (a b)
(make-pos
:x (+ (pos-x a) (pos-x b))
:y (+ (pos-y a) (pos-y b))
))
(defun pos-subtract (a b)
(make-pos
:x (- (pos-x a) (pos-x b))
:y (- (pos-y a) (pos-y b))
))
(defun show-map (map &optional (dest t)) (defun show-map (map &optional (dest t))
(let ((w (array-dimension map 1)) (let ((w (array-dimension map 1))
(h (array-dimension map 0))) (h (array-dimension map 0)))

View file

@ -34,7 +34,7 @@
(define-test test-part2-maze2 (define-test test-part2-maze2
:parent suite-2024-16 :parent suite-2024-16
(is = 64 (solVe-part2 test-maze2))) (is = 64 (solve-part2 test-maze2)))

View file

@ -1,5 +1,5 @@
(defpackage :aoc/2024/18/tests (defpackage :aoc/2024/18/tests
(:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/18)) (:use :cl :aoc :aoc/maze :aoc/tests :aoc/2024/tests :parachute :aoc/2024/18))
(in-package :aoc/2024/18/tests) (in-package :aoc/2024/18/tests)

View file

@ -1,5 +1,5 @@
(defpackage :aoc/2024/21/tests (defpackage :aoc/2024/21/tests
(:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/21)) (:use :cl :aoc :aoc/tests :aoc/maze :aoc/2024/tests :parachute :aoc/2024/21))
(in-package :aoc/2024/21/tests) (in-package :aoc/2024/21/tests)
@ -7,20 +7,52 @@
;:parent suite-2024 ;:parent suite-2024
) )
(define-test test-foo (define-test test-key-to-pos
:parent suite-2024-21 :parent suite-2024-21
(is equalp (make-pos :x 1 :y 0) (key-to-pos #\0))
(is equalp (make-pos :x 2 :y 0) (key-to-pos #\A))
(is equalp (make-pos :x 0 :y 1) (key-to-pos #\1))
(is equalp (make-pos :x 1 :y 2) (key-to-pos #\5))
(is equalp (make-pos :x 2 :y 3) (key-to-pos #\9))
(is equalp (make-pos :x 1 :y 0) (key-to-pos #\^))
(is equalp (make-pos :x 0 :y 1) (key-to-pos #\<))
(is equalp (make-pos :x 1 :y 1) (key-to-pos #\v))
(is equalp (make-pos :x 2 :y 1) (key-to-pos #\>))
) )
(define-test test-bar
(define-test test-press-key
:parent suite-2024-21 :parent suite-2024-21
(is equal "<A" (press-key #\A #\0))
(is equal "^A" (press-key #\0 #\2))
(is equal ">^^A" (press-key #\2 #\9))
(is equal "vvvA" (press-key #\9 #\A))
) )
(define-test test-type-code
:parent suite-2024-21
(is equal "<A^A>^^AvvvA" (type-code "029A"))
(is equal "v<<A>>^A<A>AvA^<AA>Av<AAA>^A" (type-code (type-code "029A") nil)))
(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)))
(define-test test-manual
: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)))
(define-test+run test-part1 (define-test+run test-part1
:parent suite-2024-21 :parent suite-2024-21
(is equal nil (part1 sample-data))) (is equal 126384 (part1 sample-data)))
(define-test+run test-part2 (define-test+run test-part2
:parent suite-2024-21 :parent suite-2024-21

View file

@ -0,0 +1,27 @@
(defpackage :aoc/2024/22/tests
(:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/22))
(in-package :aoc/2024/22/tests)
(define-test suite-2024-22
;:parent suite-2024
)
(define-test test-foo
:parent suite-2024-22
)
(define-test test-bar
:parent suite-2024-22
)
(define-test+run test-part1
:parent suite-2024-22
(is equal nil (part1 sample-data)))
(define-test+run test-part2
:parent suite-2024-22
(is equal nil (part2 sample-data)))

View file

@ -9,9 +9,7 @@
:parent 'aoc-suite) :parent 'aoc-suite)
(define-test test-day08
:parent 'suite-2024
(aoc/2024/08/tests:run-tests))