60 lines
2.0 KiB
Nix
60 lines
2.0 KiB
Nix
with import ../../util.nix;
|
|
|
|
let
|
|
# read input
|
|
cmdOuts = splitString "\n$ " (removePrefix "$ " (readFile ./input));
|
|
|
|
fileTree =
|
|
let
|
|
start = { cwd = []; tree = {}; };
|
|
|
|
applyCmd = acc: cmdOut:
|
|
let
|
|
# parse cmd + cmd output
|
|
lines = splitString "\n" cmdOut;
|
|
cmd = splitString " " (head lines);
|
|
out = tail lines;
|
|
|
|
# apply cmds
|
|
applyCd = cwd: param:
|
|
if param == ".." then dropLast cwd
|
|
else if param == "/" then []
|
|
else cwd ++ [param];
|
|
applyLs = cwd: param:
|
|
let
|
|
parseFileDir = splitLine:
|
|
if head splitLine == "dir" then { ${last splitLine} = {}; }
|
|
else { ${last splitLine} = toInt (head splitLine); };
|
|
makeSubTree = combineAttrs (map (line: parseFileDir (splitString " " line)) param);
|
|
in
|
|
setAttrByPath cwd makeSubTree;
|
|
in
|
|
if head cmd == "cd" then
|
|
{ inherit (acc) tree; cwd = applyCd acc.cwd (last cmd); }
|
|
else # ls
|
|
{ inherit (acc) cwd; tree = recursiveUpdate acc.tree (applyLs acc.cwd out); };
|
|
in (foldl applyCmd start cmdOuts).tree;
|
|
|
|
sizeOfDir = dir:
|
|
sum (map (v: if isAttrs v then sizeOfDir v else v) (attrValues dir));
|
|
|
|
# a flat list of sizes for all directories
|
|
dirSizes = recurisveVisitAttrs (n: v: if isAttrs v then sizeOfDir v else 0) fileTree;
|
|
|
|
# a list of sizes for small directories
|
|
smallDirSizes =
|
|
foldl (acc: size: if size < 100000 && size != 0 then acc ++ [size] else acc) [] dirSizes;
|
|
|
|
totalUsedSize = sizeOfDir fileTree;
|
|
|
|
# smallest directory to delete to free target size
|
|
minDirOfAtLeastSize = targetSize: foldl (acc: s: if s >= targetSize && s < acc then s else acc) totalUsedSize dirSizes;
|
|
|
|
totalFsSize = 70000000;
|
|
fsSizeNeeded = 30000000;
|
|
availableSpace = totalFsSize - totalUsedSize;
|
|
spaceNeeded = fsSizeNeeded - availableSpace;
|
|
in rec {
|
|
part1 = sum smallDirSizes;
|
|
part2 = minDirOfAtLeastSize spaceNeeded;
|
|
} |