day7
This commit is contained in:
parent
43830f4dd7
commit
2097ca09cd
2 changed files with 82 additions and 0 deletions
2
aoc.m
2
aoc.m
|
@ -44,6 +44,7 @@ run_day(Day, Part, Lines, Out) :-
|
||||||
:- import_module day4.
|
:- import_module day4.
|
||||||
:- import_module day5.
|
:- import_module day5.
|
||||||
:- import_module day6.
|
:- import_module day6.
|
||||||
|
:- import_module day7.
|
||||||
|
|
||||||
:- pred solution(int::in, sol::out(sol)) is semidet.
|
:- pred solution(int::in, sol::out(sol)) is semidet.
|
||||||
solution(1, day1.run).
|
solution(1, day1.run).
|
||||||
|
@ -52,3 +53,4 @@ solution(3, day3.run).
|
||||||
solution(4, day4.run).
|
solution(4, day4.run).
|
||||||
solution(5, day5.run).
|
solution(5, day5.run).
|
||||||
solution(6, day6.run).
|
solution(6, day6.run).
|
||||||
|
solution(7, day7.run).
|
||||||
|
|
80
day7.m
Normal file
80
day7.m
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
:- module day7.
|
||||||
|
:- interface.
|
||||||
|
:- import_module basics.
|
||||||
|
:- import_module univ.
|
||||||
|
|
||||||
|
:- pred run(part::in, lines::in, univ::out) is cc_multi.
|
||||||
|
|
||||||
|
:- implementation.
|
||||||
|
:- import_module int.
|
||||||
|
:- import_module string.
|
||||||
|
:- import_module list.
|
||||||
|
|
||||||
|
|
||||||
|
:- type words == list(string).
|
||||||
|
|
||||||
|
:- 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).
|
||||||
|
:- 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.
|
||||||
|
dir(dir(Name, Immed, Total, Files, Dirs)) -->
|
||||||
|
cd_down(Name),
|
||||||
|
["$ ls"], files(Files),
|
||||||
|
{Immed = foldl(func(File, Acc) = size(File) + Acc, Files, 0)},
|
||||||
|
dirs(Dirs),
|
||||||
|
{Total = foldl(func(Dir, Acc) = total(Dir) + Acc, Dirs, Immed)},
|
||||||
|
(["$ cd .."] ; []).
|
||||||
|
|
||||||
|
:- pred cd_down(string::out, lines::in, lines::out) is semidet.
|
||||||
|
cd_down(D) --> line(["$", "cd", D]).
|
||||||
|
|
||||||
|
:- pred files(files::out, lines::in, lines::out) is multi.
|
||||||
|
files([file(Name, Size) | Files]) -->
|
||||||
|
line([SSize, Name]), {to_int(SSize, Size)},
|
||||||
|
files(Files).
|
||||||
|
files(Files) -->
|
||||||
|
line([Dir, _]), {Dir = "dir"},
|
||||||
|
files(Files).
|
||||||
|
files([]) --> [].
|
||||||
|
|
||||||
|
:- pred dirs(dirs::out, lines::in, lines::out) is multi.
|
||||||
|
dirs([D | Ds]) --> dir(D), dirs(Ds).
|
||||||
|
dirs([]) --> [].
|
||||||
|
|
||||||
|
:- pred find(pred(dir)::(pred(in) is semidet), dir::in, list(dir)::out) is det.
|
||||||
|
find(P, Dir, Out) :-
|
||||||
|
map(find(P), dirs(Dir), Outs),
|
||||||
|
Children = condense(Outs),
|
||||||
|
(if P(Dir) then Out = [Dir | Children] else Out = Children).
|
||||||
|
|
||||||
|
:- pred size_lte(int::in, dir::in) is semidet.
|
||||||
|
size_lte(Size, Dir) :- total(Dir) =< Size.
|
||||||
|
|
||||||
|
:- pred size_gte(int::in, dir::in) is semidet.
|
||||||
|
size_gte(Size, Dir) :- total(Dir) >= Size.
|
||||||
|
|
||||||
|
:- func sort_size(list(dir)) = list(dir).
|
||||||
|
sort_size(Dirs) = sort(func(D1, D2) = ordering(total(D1), total(D2)), Dirs).
|
||||||
|
|
||||||
|
run(one, Lines, univ(Out)) :-
|
||||||
|
if dir(Top, Lines, []) then
|
||||||
|
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").
|
Loading…
Reference in a new issue