slim it down

This commit is contained in:
rhiannon morris 2022-12-07 10:03:27 +01:00
parent 2097ca09cd
commit f892834fa6

73
day7.m
View file

@ -10,42 +10,27 @@
:- import_module string. :- import_module string.
:- import_module list. :- import_module list.
:- type dir ---> dir(size :: int, dirs :: dirs).
:- type words == list(string). :- func size(dir) = int.
:- type file ---> file(name :: string, size :: int).
:- type files == list(file).
:- type dir --->
dir(name :: string,
immed :: int, total :: int,
files :: files, dirs :: dirs).
:- type dirs == list(dir). :- type dirs == list(dir).
:- func total(dir) = int.
:- pred line(words::out, lines::in, lines::out) is semidet.
line(words(Line)) --> [Line].
:- pred dir(dir::out, lines::in, lines::out) is nondet. :- pred dir(dir::out, lines::in, lines::out) is nondet.
dir(dir(Name, Immed, Total, Files, Dirs)) --> dir(dir(Size, Dirs)) -->
cd_down(Name), [Cd], {append("$ cd ", _, Cd)},
["$ ls"], files(Files), ["$ ls"],
{Immed = foldl(func(File, Acc) = size(File) + Acc, Files, 0)}, files(Files),
dirs(Dirs), dirs(Dirs),
{Total = foldl(func(Dir, Acc) = total(Dir) + Acc, Dirs, Immed)}, {Size = Files + sum(map(size, Dirs))},
(["$ cd .."] ; []). (["$ cd .."] ; []).
:- pred cd_down(string::out, lines::in, lines::out) is semidet. :- pred files(int::out, lines::in, lines::out) is multi.
cd_down(D) --> line(["$", "cd", D]). files(Size + Rest) -->
[Line], {to_int(head(words(Line)), Size)},
:- pred files(files::out, lines::in, lines::out) is multi. files(Rest).
files([file(Name, Size) | Files]) --> files(Size) -->
line([SSize, Name]), {to_int(SSize, Size)}, [Dir], {append("dir ", _, Dir)},
files(Files). files(Size).
files(Files) --> files(0) --> [].
line([Dir, _]), {Dir = "dir"},
files(Files).
files([]) --> [].
:- pred dirs(dirs::out, lines::in, lines::out) is multi. :- pred dirs(dirs::out, lines::in, lines::out) is multi.
dirs([D | Ds]) --> dir(D), dirs(Ds). dirs([D | Ds]) --> dir(D), dirs(Ds).
@ -53,28 +38,20 @@ dirs([]) --> [].
:- pred find(pred(dir)::(pred(in) is semidet), dir::in, list(dir)::out) is det. :- pred find(pred(dir)::(pred(in) is semidet), dir::in, list(dir)::out) is det.
find(P, Dir, Out) :- find(P, Dir, Out) :-
map(find(P), dirs(Dir), Outs), map(find(P), dirs(Dir), Outs), Children = condense(Outs),
Children = condense(Outs),
(if P(Dir) then Out = [Dir | Children] else Out = Children). (if P(Dir) then Out = [Dir | Children] else Out = Children).
:- pred size_lte(int::in, dir::in) is semidet. :- pred size_lte(int::in, dir::in) is semidet.
size_lte(Size, Dir) :- total(Dir) =< Size. size_lte(Size, Dir) :- size(Dir) =< Size.
:- pred size_gte(int::in, dir::in) is semidet. :- pred size_gte(int::in, dir::in) is semidet.
size_gte(Size, Dir) :- total(Dir) >= Size. size_gte(Size, Dir) :- size(Dir) >= Size.
:- func sort_size(list(dir)) = list(dir). :- pred go(part::in, dir::in, int::out) is det.
sort_size(Dirs) = sort(func(D1, D2) = ordering(total(D1), total(D2)), Dirs). go(one, Top, sum(map(size, Found))) :-
find(size_lte(100_000), Top, Found).
go(two, Top, det_head(sort(map(size, Found)))) :-
find(size_gte(size(Top) - 40_000_000), Top, Found).
run(one, Lines, univ(Out)) :- run(Part, Lines, univ(Out)) :-
if dir(Top, Lines, []) then if dir(Top, Lines, []) then go(Part, Top, Out) else die("bad input").
find(size_lte(100_000), Top, Found),
Out = sum(map(total, Found))
else
die("bad input").
run(two, Lines, univ(Out)) :-
if dir(Top, Lines, []) then
find(size_gte(total(Top) - 40_000_000), Top, Found),
Out = det_head(sort(map(total, Found)))
else
die("bad input").