(2022>README,1,5)+literate code for problem 1 rewrite,~minor changes to 5

Making README.org a literate document for my code to better describe
my process.
This commit is contained in:
2023-06-27 21:00:04 +01:00
parent 3d8c645541
commit 1041984da0
3 changed files with 123 additions and 20 deletions

102
2022/README.org Normal file
View File

@@ -0,0 +1,102 @@
#+title: 2022 advent of code
#+author: Aryadev Chavali
#+description: Description
#+date: 2023-06-26
Doing this ridiculously late. Insert joke about Christmas in the summertime.
* Problem 1
:PROPERTIES:
:header-args:lisp: :session problem_1 :tangle puzzle-1.lisp
:END:
Simple summing of sublists problem. Not very difficult, though found
out that Common Lisps semantics around parsing are kinda weird.
** Round 1
*** Getting input and defining the separator
To get input, use ~uiop:read-file-string~ (comes with ASDF,
quicklisp, so in most common lisp systems).
#+begin_src lisp
(defvar input (uiop:read-file-string "2022/1-input"))
#+end_src
Each "bag" in the data is separated by two newlines, so let's define
that as a constant.
#+begin_src lisp
(defvar *sep (format nil "~%~%"))
#+end_src
*** Parse procedure for any one bag
A bag is a set of lines of numbers representing the food in that bag.
So all we need to do, given an input bag, is to convert each line into
an integer. We can use ~with-input-from-string~ to leverage
~read-line~:
#+begin_src lisp
(defun parse-entity (inp)
(with-input-from-string (s inp)
(loop for line = (read-line s nil)
while line
collect (parse-integer line))))
#+end_src
*** Recursive procedure to parse all input
Each bag is separated by ~*sep~, so all we need to do is:
+ search for the next separator in the input
+ parse it
+ cons what we made with a recursive call for the rest of the input
#+begin_src lisp
(defun get-lists (input)
(let* ((pos (search *sep input))
(converted (parse-entity (subseq input 0 pos))))
(if (null pos)
(list converted)
(cons converted
(get-lists (subseq input (+ pos 2)))))))
#+end_src
*** Get sums and sort them
To sum each bag, we just need to perform a reduce on each list by
~#'+~. To sort we can use the inbuilt ~sort~ function which takes an
ordering function. Easy stuff.
#+begin_src lisp
(defvar sums (sort (mapcar (lambda (lst) (reduce #'+ lst)) (get-lists input))
#'>))
#+end_src
*** Finish the round
We want the largest sum, which is literally the top of the sorted
list.
#+begin_src lisp
(format t "Round 1: ~a~%" (car sums))
#+end_src
** Round 2
Not actually that much harder, we want the top 3 largest bags. This
is really easy, as we've already sorted the list so we just need the
first 3 elements! For this I use a ~destructuring-bind~ just to be
fancy, though I could easily use a ~subseq~ instead.
#+begin_src lisp
(destructuring-bind (first second third &rest _) sums
(format t "Round 2: ~a,~a,~a:>~a" first second third
(+ first second third)))
#+end_src
* Problem 2
Rock paper scissors simulation, but very basic. You're essentially
given a log of rounds and their outcomes, and you have to interpret
the data and produce a scoring (based on an arbitrary metric). Pretty
simple once again.
* Problem 3
Kinda involved mostly because I don't have a good understanding of
Common Lisps core library. More involved parsing routine in order to
find shared elements between sets. Round 2 extends this to 3 sets,
but some interesting extensions to the problem include going to
arbitrary n set inclusion testing.
* Problem 4
Checking if you know how bounds work, testing if
$[a,b]\subset{[c,d]}$. Pretty easy maths.
* Problem 5
Basically the reason I started making this document, as it seems to be
the first really involved problem. I need to make a stack machine,
interpreting an initial layout of memory and an algorithm to perform
on the machine. Very interesting.

View File

@@ -1,26 +1,26 @@
(defvar input (uiop:read-file-string "2022/1-input"))
(defvar *sep (format nil "~%~%"))
(defun parse-entity (inp)
(with-input-from-string (s inp)
(loop for line = (read-line s nil)
while line
collect (parse-integer line))))
(defun get-lists (input)
(let ((pos (search *sep input)))
(with-input-from-string (s (subseq input 0 pos))
(let ((converted
(loop
for line = (read-line s nil nil)
while line
collect (parse-integer line))))
(if (null pos)
(list converted)
(cons converted
(get-lists (subseq input (+ pos 2)))))))))
(let* ((pos (search *sep input))
(converted (parse-entity (subseq input 0 pos))))
(if (null pos)
(list converted)
(cons converted
(get-lists (subseq input (+ pos 2)))))))
(defvar sums (sort (mapcar (lambda (lst) (reduce #'+ lst)) (get-lists input)) #'>))
(defvar sums (sort (mapcar (lambda (lst) (reduce #'+ lst)) (get-lists input))
#'>))
;; First challenge
(format t "Top snacks: ~a" (car sums))
(format t "Round 1: ~a~%" (car sums))
;; Second challenge
(let ((first (car sums))
(second (car (cdr sums)))
(third (car (cdr (cdr sums)))))
(format t "~a,~a,~a:>~a" first second third (+ first second third)))
(destructuring-bind (first second third &rest _) sums
(format t "Round 2: ~a,~a,~a:>~a" first second third
(+ first second third)))

View File

@@ -100,12 +100,13 @@ define this operation first! |#
(with-input-from-string (s instructions)
(loop
for line = (read-line s nil)
until (null line)
while line
collect
;; Parse each instruction then move the crates!
(destructuring-bind (n a b) (parse-instruction-str line)
(move-crates n a b)))))
;; The answer is simply the first top of each stack
(defun first-round ()
(setq state (default-state))
(parse-initial-state)