aboutsummaryrefslogtreecommitdiff
path: root/2022/Day07/part-two.cl
diff options
context:
space:
mode:
Diffstat (limited to '2022/Day07/part-two.cl')
-rw-r--r--2022/Day07/part-two.cl52
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)))))