60 lines
1.8 KiB
Nix
60 lines
1.8 KiB
Nix
{ lib, utils, ... }:
|
|
with lib;
|
|
with builtins;
|
|
with utils;
|
|
let
|
|
disk = map toIntBase10 (stringToCharacters (head (readLines ./input)));
|
|
files = genList (id:
|
|
let baseIndex = id * 2;
|
|
in {
|
|
size = elemAt disk baseIndex;
|
|
freeAfter = if (baseIndex + 1) < (length disk) then
|
|
elemAt disk (baseIndex + 1)
|
|
else
|
|
0;
|
|
inherit id;
|
|
}) ((length disk) / 2 + 1);
|
|
|
|
totalSize = listSumWith (getAttr "size") files;
|
|
# totalFree = listSumWith (getAttr "freeAfter") files;
|
|
|
|
diskExpanded = concatLists (map
|
|
(f: (genList (const f.id) f.size) ++ (genList (const null) f.freeAfter))
|
|
files);
|
|
# diskSemiExpanded = concatLists (map (f: [ (genList (const f.id) f.size) f.freeAfter ]) files);
|
|
|
|
toMove = reverseList (filter (invert isNull) (drop totalSize diskExpanded));
|
|
# base = take totalSize diskExpanded;
|
|
|
|
compress = files': toMove':
|
|
let f = head files';
|
|
in if toMove' == [ ] then
|
|
(genList (const f.id) f.size)
|
|
else
|
|
(genList (const f.id) f.size) ++ (take f.freeAfter toMove')
|
|
++ (compress (tail files') (drop f.freeAfter toMove'));
|
|
|
|
compressed = take totalSize (compress files toMove);
|
|
# compressed = compress files toMove;
|
|
|
|
checksum = imap0 mul compressed;
|
|
|
|
in {
|
|
# part1 = listSum checksum;
|
|
# inherit files;
|
|
# test = listSumLog (sublist 0 50000 checksum);
|
|
part1 = listSumLog checksum;
|
|
# inherit chunks;
|
|
# inherit compressed;
|
|
# lenCompressed = length compressed;
|
|
# compressedHead = head compressed;
|
|
# inherit totalSize totalFree;
|
|
# inherit diskExpanded;
|
|
# moveLen = length toMove;
|
|
# nullsInBase = count isNull base;
|
|
# inherit disk;
|
|
# sumTest = listSumLog [1 2 3 4 5];
|
|
|
|
diskSize = listSum disk; # TOO DAMN LARGE FOR LINEAR RECURSION!
|
|
fileCount = length files; # TOO DAMN LARGE FOR LINEAR RECURSION!
|
|
}
|