diff --git a/src/2024/day09.lisp b/src/2024/day09.lisp index 6ee3ed5..f6dfe47 100644 --- a/src/2024/day09.lisp +++ b/src/2024/day09.lisp @@ -69,29 +69,39 @@ if (inode-p n) maximize (inode-id n))) +(defun fs-move-file (fs inode inode-pos freespace free-pos) + "moves a file into a freespace. If the file is too large it will move as much as fits." + (strip-freespace-at-end + (append + (subseq fs 0 free-pos) + ;; move file into freespace + (list (make-inode + :id (inode-id inode) + :start (freespace-start freespace) + :length (min (freespace-length freespace) (inode-length inode)))) + ;; update freespace if any remaining + (if (> (freespace-length freespace) (inode-length inode)) + (list (make-freespace + :length (- (freespace-length freespace) (inode-length inode)) + :start (+ (freespace-start freespace) (inode-length inode))))) + ;; skip to where file was originally + (subseq fs (1+ free-pos) inode-pos) + ;; if any of the file remaining update the length + (if (< (freespace-length freespace) (inode-length inode)) + (list (make-inode + :id (inode-id inode) + :start (inode-start inode) + :length (- (inode-length inode) (freespace-length freespace))))) + ;; copy rest of fs + (subseq fs (1+ inode-pos))))) + (defun fs-compact-step (fs) (let* ((first-free (find-if #'freespace-p fs)) (free-pos (position first-free fs)) (last-inode (find-if #'inode-p (reverse fs))) (inode-pos (position last-inode fs))) (if first-free - (strip-freespace-at-end - (append - (subseq fs 0 free-pos) - (list (make-inode - :id (inode-id last-inode) - :start (freespace-start first-free) - :length (min (freespace-length first-free) (inode-length last-inode)))) - (if (> (freespace-length first-free) (inode-length last-inode)) - (list (make-freespace - :length (- (freespace-length first-free) (inode-length last-inode)) - :start (+ (freespace-start first-free) (inode-length last-inode))))) - (subseq fs (1+ free-pos) inode-pos) - (if (< (freespace-length first-free) (inode-length last-inode)) - (list (make-inode - :id (inode-id last-inode) - :start (inode-start last-inode) - :length (- (inode-length last-inode) (freespace-length first-free))))))) + (fs-move-file fs last-inode inode-pos first-free free-pos) fs))) (defun fs-compact (fs) @@ -126,18 +136,7 @@ (freespace-pos (position freespace fs)) ) (if (and freespace (> inode-pos freespace-pos)) - (append - (subseq fs 0 freespace-pos) - (list (make-inode - :id id - :start (freespace-start freespace) - :length (inode-length inode))) - (if (> (freespace-length freespace) (inode-length inode)) - (list (make-freespace - :start (+ (freespace-start freespace) (inode-length inode)) - :length (- (freespace-length freespace) (inode-length inode))))) - (subseq fs (1+ freespace-pos) inode-pos) - (subseq fs (1+ inode-pos))) + (fs-move-file fs inode inode-pos freespace freespace-pos) fs))) (defun fs-optimize (fs) diff --git a/tests/2024/day09-test.lisp b/tests/2024/day09-test.lisp index fe75d80..5e382c4 100644 --- a/tests/2024/day09-test.lisp +++ b/tests/2024/day09-test.lisp @@ -9,7 +9,7 @@ (define-test test-blocks-to-fs :parent suite-2024-09 - (let ((fs (blocks-to-fs sample-data))) + (let ((fs sample-data)) (is equalp (make-inode :id 0 :start 0 :length 2) (nth 0 fs)) (is equalp (make-freespace :start 2 :length 3) (nth 1 fs)) (is equalp (make-inode :id 1 :start 5 :length 3) (nth 2 fs))