solved day8 and improved submitting answers

This commit is contained in:
Peter Tillemans 2024-12-08 13:33:04 +01:00
parent f5b144ce21
commit f7bda050dd
5 changed files with 234 additions and 32 deletions

View file

@ -31,6 +31,7 @@
(:file "2024/day05") (:file "2024/day05")
(:file "2024/day06") (:file "2024/day06")
(:file "2024/day07") (:file "2024/day07")
(:file "2024/day08")
))) )))
: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."
@ -54,6 +55,7 @@
(:file "2024/day05-test") (:file "2024/day05-test")
(:file "2024/day06-test") (:file "2024/day06-test")
(:file "2024/day07-test") (:file "2024/day07-test")
(:file "2024/day08-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

@ -51,19 +51,21 @@
(defun mul-branch (equation) (defun mul-branch (equation)
"returns simplified equation after applying the * operator or nil if not possible"
(let ((r (equation-result equation)) (let ((r (equation-result equation))
(os (equation-operands equation))) (os (equation-operands equation)))
(if (= (gcd r (first os)) (first os)) (and (= (gcd r (first os)) (first os))
(make-equation :result (/ r (first os)) :operands (cdr os)) (make-equation :result (/ r (first os)) :operands (cdr os)))))
nil)))
(defun plus-branch (equation) (defun plus-branch (equation)
"returns simplified equation after applying the + operator or nil if not possible"
(let ((r (equation-result equation)) (let ((r (equation-result equation))
(os (equation-operands equation))) (os (equation-operands equation)))
(if (>= r(first os)) (and (>= r(first os))
(make-equation :result (- r (first os)) :operands (cdr os))))) (make-equation :result (- r (first os)) :operands (cdr os)))))
(defun solvedp (equation) (defun solvedp (equation)
"returns true if equation has been solved"
(let ((r (equation-result equation)) (let ((r (equation-result equation))
(os (equation-operands equation))) (os (equation-operands equation)))
(and (and
@ -71,6 +73,7 @@
(= r (first os))))) (= r (first os)))))
(defun valid-equation (equation) (defun valid-equation (equation)
"recursively determine if the equation is valid"
(if (equation-operands equation) (if (equation-operands equation)
(let ((mb (mul-branch equation)) (let ((mb (mul-branch equation))
(pb (plus-branch equation))) (pb (plus-branch equation)))
@ -80,7 +83,6 @@
(and pb (valid-equation pb)))) (and pb (valid-equation pb))))
nil)) nil))
(defun sum-valid-eqs (eqs) (defun sum-valid-eqs (eqs)
(loop (loop
for eq in eqs for eq in eqs

165
src/2024/day08.lisp Normal file
View file

@ -0,0 +1,165 @@
(defpackage :aoc/2024/08
(:use :cl :aoc :alexandria :trivia :lla)
(:export
#:sample-data
#:sample-data2
#:part1
#:part2
))
(in-package :aoc/2024/08)
;; a frequency node represents a location on the map
;; associated to a frequence, like an antenna or antinode
(defstruct frequency-node frequency position)
(defun parse-line (line)
"return an equation with the result and the operands in reverse order as in the text"
(loop
for x from 0 to (1- (length line))
for c = (aref line x)
if (not (or (eq c #\.) (eq c #\#)))
collect (list x c)))
(defstruct antenna-map bounds antennas)
(defun parse-input (lines)
(make-antenna-map
:bounds
(vector (length (first lines)) (length lines))
:antennas
(loop for y from 0 to (1- (length lines))
for line in lines
append (mapcar (lambda (a)
(make-frequency-node
:position (vector (first a) y)
:frequency (second a)))
(parse-line line)))))
(defparameter input-text (test-input 2024 8))
(defparameter input-data (parse-input input-text))
(defparameter sample-text (aoc:split-lines "............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............"))
(defparameter sample-data
(parse-input sample-text))
(defun antinode (ant1 ant2)
(and
(eq (frequency-node-frequency ant1) (frequency-node-frequency ant2))
(make-frequency-node
:frequency (frequency-node-frequency ant1)
:position (aops:each
(lambda (a b) (- (* 2 b) a))
(frequency-node-position ant1)
(frequency-node-position ant2)
))))
(defun group-by-frequency (fnodes)
(let ((groups (make-hash-table :test #'eq)))
(loop for n in fnodes
do (push n (gethash (frequency-node-frequency n) groups)))
groups))
(defun fnode-in-boundsp (map fnode)
(loop for x across (frequency-node-position fnode)
for bound across (antenna-map-bounds map)
always (< -1 x bound))
)
(defun antennas-antinodes (antennas)
(loop for a1 in antennas
append (loop for a2 in antennas
if (not (eq a1 a2))
collect (antinode a1 a2))))
(defun count-antinodes (map)
(let ((antennas-by-f (group-by-frequency (antenna-map-antennas map)))
(antinode-map (make-hash-table :test #'equalp))
)
(loop
for antennas being the hash-values of antennas-by-f
do (loop for n in (antennas-antinodes antennas)
if (and n (fnode-in-boundsp map n))
do (incf (gethash (frequency-node-position n) antinode-map 0))))
(length (hash-table-keys antinode-map)))
)
(defparameter sample-data2 (parse-input (aoc:split-lines "T....#....
...T......
.T....#...
.........#
..#.......
..........
...#......
..........
....#.....
..........
")))
(defun resonant-nodes (map ant1 ant2)
(unless
(or (equalp ant1 ant2)
(not (equal
(frequency-node-frequency ant1)
(frequency-node-frequency ant2))))
(loop for i from 1
for fn = (make-frequency-node
:frequency (frequency-node-frequency ant1)
:position (aops:each
(lambda (a b) (+ a (* i (- b a))))
(frequency-node-position ant1)
(frequency-node-position ant2)))
while (fnode-in-boundsp map fn)
collect fn)))
(defun antennas-resonant-nodes (map antennas)
(loop for a1 in antennas
append (loop for a2 in antennas
append (resonant-nodes map a1 a2))))
(defun count-resonant-nodes (map)
(let ((antennas-by-f (group-by-frequency (antenna-map-antennas map)))
(resonant-node-map (make-hash-table :test #'equalp))
)
(loop
for antennas being the hash-values of antennas-by-f
do (loop for n in (antennas-resonant-nodes map antennas)
if (fnode-in-boundsp map n)
do (incf (gethash (frequency-node-position n) resonant-node-map 0))))
(length (hash-table-keys resonant-node-map)))
)
(defun part1 (data)
(format nil "~A" (count-antinodes data)))
(defun part2 (data)
(format nil "~A" (count-resonant-nodes data)))
(defun solve-day ()
(format t "part1: ~A~%" (part1 input-data))
(format t "part2: ~A~%" (part2 input-data)))

View file

@ -8,26 +8,13 @@
#:clear-data-cache)) #:clear-data-cache))
(in-package :aoc) (in-package :aoc)
(defun load-ql-dependencies () (defun load-ql-dependencies ()
()) ())
(defparameter *aoc-url* "https://adventofcode.com")
(defvar *aoc-url* "https://adventofcode.com")
(defvar *cookie-jar* (defparameter *cookie-jar*
(cl-cookie:make-cookie-jar
:cookies (list
(cl-cookie:make-cookie
:name "session"
:value (uiop:getenv "AOC_SESSION")
:origin-host "adventofcode.com"
:path "/"
:domain ".adventofcode.com"
:secure-p t))))
(setf *cookie-jar*
(cl-cookie:make-cookie-jar (cl-cookie:make-cookie-jar
:cookies (list :cookies (list
(cl-cookie:make-cookie (cl-cookie:make-cookie
@ -42,24 +29,28 @@
(defun split-lines (s) (defun split-lines (s)
(cl-ppcre:split "\\n" s)) (cl-ppcre:split "\\n" s))
(defun fetch-input-data (year day) (defun fetch-input-data (year day)
(let ((url (format nil "~A/~D/day/~D/input" *aoc-url* year day))) (let ((url (format nil "~A/~D/day/~D/input" *aoc-url* year day)))
(multiple-value-bind (multiple-value-bind
(body) (body)
(dex:get url :cookie-jar *cookie-jar* :verbose t) (dex:get url :cookie-jar *cookie-jar*)
(split-lines body)))) (split-lines body))))
(defun print-articles (body)
(let* ((dom (plump:parse body))
(articles (plump:get-elements-by-tag-name dom "article")))
(loop for article in articles
do (format t "~A~%~%" (plump:render-text article)))))
(defun submit-answer (year day level answer) (defun submit-answer (year day level answer)
(let ((url (format nil "~A/~D/day/~D/answer" *aoc-url* year day))) (let ((url (format nil "~A/~D/day/~D/answer" *aoc-url* year day)))
(multiple-value-bind (multiple-value-bind
(body) (body)
(dex:post url :cookie-jar *cookie-jar* :verbose t (dex:post url :cookie-jar *cookie-jar*
:content `(("level" . ,level) :content `(("level" . ,level)
("answer" . ,answer) ("answer" . ,answer)
("submit" . "[Submit]"))) ("submit" . "[Submit]")))
body))) (print-articles body))))
(defun submit-part1 (year day answer) (defun submit-part1 (year day answer)
(submit-answer year day "1" answer)) (submit-answer year day "1" answer))
@ -67,6 +58,18 @@
(defun submit-part2 (year day answer) (defun submit-part2 (year day answer)
(submit-answer year day "2" answer)) (submit-answer year day "2" answer))
(defun show-articles (path)
(let ((url (format nil "~A/~A" *aoc-url* path)))
(multiple-value-bind
(body)
(dex:get url :cookie-jar *cookie-jar*)
(print-articles body))))
(defun private-leaderboard (year id)
(let ((path (format nil "~D/leaderboard/private/view/~D" year id)))
(show-articles path)))
(defvar *input-data-cache* (make-hash-table)) (defvar *input-data-cache* (make-hash-table))
(defun clear-data-cache () (defun clear-data-cache ()

View file

@ -0,0 +1,30 @@
(defpackage :aoc/2024/08/tests
(:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/08))
(in-package :aoc/2024/08/tests)
(define-test suite-2024-08
;:parent suite-2024
)
(define-test+run test-part1
:parent suite-2024-08
(true (equalp '( '()) (part1 sample-data))))
(define-test+run test-part2
:parent suite-2024-08
(true
(equalp "34" (part2 sample-data)))
(true
(equalp "9" (part2 sample-data2))))
(define-test test-parse-line
:parent suite-2024-08
(is equalp '() (parse-line (first sample-data)))
(is equalp '((8 #\0)) (parse-line (second sample-data)))
)