diff options
Diffstat (limited to '2022/Day07/part-two.cl')
| -rw-r--r-- | 2022/Day07/part-two.cl | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/2022/Day07/part-two.cl b/2022/Day07/part-two.cl new file mode 100644 index 0000000..267cf48 --- /dev/null +++ b/2022/Day07/part-two.cl @@ -0,0 +1,52 @@ +;;; https://gitlab.com/Syndamia/senzill +(require :senzill) +(use-package :senzill.math) +(use-package :senzill.collections) +(use-package :senzill.io) + +(defconstant +filesystem-size+ 70000000) +(defconstant +needed-space+ 30000000) + +(ask-for-stream (prog-input) + ;;; Every 3 consecutive values (in FOLDERS) represent one folder, where + ;;; the first is it's name, second is size of all files inside and third is parent folder. + (let* ((folders '("/" 0 -1)) (current-folder 0) (temp-size 0)) + (defun parse-cd (loc) + "Updates CURRENT-FOLDER to point to index of chosen folder" + (if (string= loc "..") + (setf current-folder (nth (+ 2 current-folder) folders)) + (+= current-folder (position-if (lambda (x) (and (stringp x) (string= x loc))) + (nthcdr current-folder folders) + :from-end T)))) ; Dirty trick for not properly handling folders with same names in different locations + + (defun parse-dir (name) + "Adds a new folder inside FOLDERS" + (push-back name folders) + (push-back 0 folders) + (push-back current-folder folders)) + + ;;; Parses input lines + (doread-lines (inpt :read-line-options (prog-input NIL)) + ;; "$ ls" isn't parsed, because we don't need to + (cond ;; if we have "$ cd" + ((and (char= (char inpt 0) #\$) (char= (char inpt 2) #\c)) + (parse-cd (subseq inpt 5))) + ;; if we have "dir ..." + ((char= (char inpt 0) #\d) + (parse-dir (subseq inpt 4))) + ;; if we have "<NUMBER> <FILE_NAME>" + ((digit-char-p (char inpt 0)) + (setf temp-size (parse-integer inpt :junk-allowed T)) + ;;; Adds the file size to the current folder and all parent folders + ;;; This could be extracted to the final summation, but this way it's simpler + (loop for fol = current-folder then (nth (+ 2 fol) folders) + until (= fol -1) do + (+= (nth (+ 1 fol) folders) + temp-size))))) + + (let ((free-space (- +filesystem-size+ (second folders)))) + ;;; LREST is a tail of FOLDERS, where on each iteration it starts with the file size of each folder + (loop for lrest on (cdr folders) by #'cdddr + if (>= (+ free-space (car lrest)) +needed-space+) + minimize (car lrest) into result + finally (print result))))) |
