starting day 22
This commit is contained in:
parent
2f24bfbbe7
commit
a327aef2bf
9 changed files with 344 additions and 21 deletions
2
aoc.asd
2
aoc.asd
|
@ -51,6 +51,7 @@
|
|||
(:file "2024/day19")
|
||||
(:file "2024/day20")
|
||||
(:file "2024/day21")
|
||||
(:file "2024/day22")
|
||||
)))
|
||||
:description "Advent of Code challenges and solutions."
|
||||
:long-description "Solutions for the AOC challenges."
|
||||
|
@ -88,6 +89,7 @@
|
|||
(:file "2024/day19-test")
|
||||
(:file "2024/day20-test")
|
||||
(:file "2024/day21-test")
|
||||
(:file "2024/day22-test")
|
||||
)))
|
||||
:description "Test system for aoc"
|
||||
:perform (test-op (op c) (symbol-call :parachute :test :aoc/tests)))
|
||||
|
|
|
@ -1,35 +1,240 @@
|
|||
|
||||
(defpackage :aoc/2024/21
|
||||
(:use :cl :aoc :alexandria :trivia :lla)
|
||||
(:use :cl :aoc
|
||||
:aoc/maze :alexandria :lla :arrow-macros)
|
||||
(:export
|
||||
#:sample-data
|
||||
#:sample-data2
|
||||
#:part1
|
||||
#: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)
|
||||
|
||||
|
||||
(defun parse-line (line)
|
||||
line)
|
||||
|
||||
|
||||
(defun parse-input (lines)
|
||||
(mapcar #'parse-line lines))
|
||||
|
||||
(defparameter input-text (test-input 2024 21))
|
||||
(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
|
||||
(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)
|
||||
(length data))
|
||||
(loop
|
||||
for code in data
|
||||
sum (complexity code 2)))
|
||||
|
||||
(defun part2 (data)
|
||||
(length data))
|
||||
(loop
|
||||
for code in data
|
||||
sum (complexity code 25)))
|
||||
|
||||
(defun solve-day ()
|
||||
(format t "part1: ~A~%" (part1 input-data))
|
||||
|
|
42
src/2024/day22.lisp
Normal file
42
src/2024/day22.lisp
Normal 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))))
|
|
@ -8,10 +8,14 @@
|
|||
#:pos-x
|
||||
#:pos-y
|
||||
#:pos-move
|
||||
#:pos-add
|
||||
#:pos-subtract
|
||||
#:show-map
|
||||
#:get-pos
|
||||
#:set-pos
|
||||
#:find-tile
|
||||
#:rotate-left
|
||||
#:rotate-right
|
||||
#:manhattan-distance
|
||||
))
|
||||
|
||||
|
@ -38,6 +42,19 @@
|
|||
(#\> (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))
|
||||
(let ((w (array-dimension map 1))
|
||||
(h (array-dimension map 0)))
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
(define-test test-part2-maze2
|
||||
:parent suite-2024-16
|
||||
(is = 64 (solVe-part2 test-maze2)))
|
||||
(is = 64 (solve-part2 test-maze2)))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(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)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(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)
|
||||
|
||||
|
@ -7,20 +7,52 @@
|
|||
;:parent suite-2024
|
||||
)
|
||||
|
||||
(define-test test-foo
|
||||
(define-test test-key-to-pos
|
||||
: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
|
||||
(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
|
||||
:parent suite-2024-21
|
||||
(is equal nil (part1 sample-data)))
|
||||
(is equal 126384 (part1 sample-data)))
|
||||
|
||||
(define-test+run test-part2
|
||||
:parent suite-2024-21
|
||||
|
|
27
tests/2024/day22-test.lisp
Normal file
27
tests/2024/day22-test.lisp
Normal 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)))
|
|
@ -9,9 +9,7 @@
|
|||
:parent 'aoc-suite)
|
||||
|
||||
|
||||
(define-test test-day08
|
||||
:parent 'suite-2024
|
||||
(aoc/2024/08/tests:run-tests))
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue