blob: 267cf48258919261281a308359e71ad0f321e119 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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)))))
|