:- module day1. :- interface. :- import_module basics. :- import_module io. :- import_module list. :- pred run(part::in, list(string)::in, io::di, io::uo) is det. :- implementation. :- import_module die. :- import_module std_util. :- import_module string. :- import_module int. run(Part, Args, !IO) :- if Args = [File] then ( read_named_file_as_lines(File, LinesM, !IO), need(LinesM, Lines), Totals = go(Lines), ( Part = one, format("%d\n", [i(det_head(Totals))], !IO) ; Part = two, Res = sum(take_upto(3, Totals)), format("%d\n", [i(Res)], !IO) ) ) else die("expected one readable file"). :- func go(list(string)) = list(int). go(Lines) = sort(converse(ordering), map(int_sum, gather(Lines))). :- func gather(list(string)::in) = (list(list(string))::out(non_empty_list)). gather([]) = [[]]. gather([X | Xs]) = Groups :- [Ys | Yss] = gather(Xs), (if X = "" then Groups = [[], Ys | Yss] else Groups = [[X | Ys] | Yss]). :- func sum(list(int)) = int. sum(Xs) = foldl(func(X, Y) = X + Y, Xs, 0). :- func int_sum(list(string)) = int. int_sum(Xs) = sum(map(det_to_int, Xs)). :- pred need(io.res(T)::in, T::out) is det. need(ok(X), X). need(error(E), _) :- die(error_message(E)).