aoc2022/basics.m

161 lines
4.8 KiB
Mathematica

:- module basics.
:- interface.
:- import_module io.
:- type part ---> one; two.
:- pred part(string, part).
:- mode part(in, out) is semidet.
:- mode part(out, in) is det.
:- func part(part, T, T) = T.
:- type answer --->
int(int); string(string); lines(list(string));
some [T] other(T).
:- pred output(answer::in, io::di, io::uo) is det.
:- func ite((pred)::((pred) is semidet), T::in, T::in) = (T::out) is det.
:- import_module list.
:- import_module string.
:- type lines == list(string).
:- pred die(string::in) is erroneous.
:- pred die(string::in, list(poly_type)::in) is erroneous.
:- pred need(io.res(T)::in, T::out) is det.
:- pred read_lines_need(string::in, lines::out, io::di, io::uo) is det.
:- pred wrap_main(pred(io, io), io, io).
:- mode wrap_main(pred(di, uo) is cc_multi, di, uo) is cc_multi.
:- mode wrap_main(pred(di, uo) is det, di, uo) is cc_multi.
:- import_module char.
:- type chars == list(char).
:- func sum(list(int)) = int.
:- func prod(list(int)) = int.
:- func replicate(int, T) = list(T).
:- func rev_sort(list(T)) = list(T).
:- func map_index(func(int, T) = U, list(T)) = list(U).
:- pred map_index(pred(int, T, U), list(T), list(U)).
:- mode map_index(pred(in, in, out) is det, in, out) is det.
:- mode map_index(pred(in, di, uo) is det, di, uo) is det.
:- mode map_index(pred(in, in, out) is semidet, in, out) is semidet.
:- mode map_index(pred(in, in, out) is multi, in, out) is multi.
:- mode map_index(pred(in, in, out) is cc_multi, in, out) is cc_multi.
:- func foldl_index(func(int, T, U) = U, list(T), U) = U.
:- pred foldl_index(pred(int, T, U, U), list(T), U, U).
:- mode foldl_index(pred(in, in, in, out) is det, in, in, out) is det.
:- mode foldl_index(pred(in, in, di, uo) is det, in, di, uo) is det.
:- mode foldl_index(pred(in, di, di, uo) is det, di, di, uo) is det.
:- mode foldl_index(pred(in, in, in, out) is semidet, in, in, out) is semidet.
:- mode foldl_index(pred(in, in, in, out) is multi, in, in, out) is multi.
:- mode foldl_index(pred(in, in, in, out) is cc_multi, in, in, out) is cc_multi.
:- import_module maybe.
:- func to_int_may(string) = maybe(int).
:- implementation.
part("1", one).
part("2", two).
part(P, X, Y) = ite(unify(P, one), X, Y).
output(int(I), !IO) :- write_int(I, !IO), nl(!IO).
output(string(S), !IO) :- write_string(S, !IO), nl(!IO).
output(lines(Ss), !IO) :- write_list(Ss, "\n", write_string, !IO), nl(!IO).
output(other(X), !IO) :- write(X, !IO), nl(!IO).
ite(P, T, E) = X :- if P then X = T else X = E.
:- import_module exception.
:- type die ---> death(string).
die(Str) :- throw(death(Str)).
die(Fmt, Args) :- die(format(Fmt, Args)).
wrap_main(Main, !IO) :-
try [io(!IO)] Main(!IO)
then true
catch death(Err) ->
format("%s\n", [s(Err)], !IO),
set_exit_status(1, !IO).
need(ok(X), X).
need(error(E), _) :- die(error_message(E)).
read_lines_need(File, Lines, !IO) :-
read_named_file_as_lines(File, Res, !IO),
need(Res, Lines).
:- import_module int.
sum(Xs) = foldl(plus, Xs, 0).
prod(Xs) = foldl(times, Xs, 1).
replicate(N, X) = Out :-
if N = 0 then Out = [] else Out = [X | replicate(N - 1, X)].
:- import_module std_util.
rev_sort(Xs) = sort(converse(ordering), Xs).
:- pred map_index(int, pred(int, T, U), list(T), list(U)).
:- mode map_index(in, pred(in, in, out) is det, in, out) is det.
:- mode map_index(in, pred(in, di, uo) is det, di, uo) is det.
:- mode map_index(in, pred(in, in, out) is semidet, in, out) is semidet.
:- mode map_index(in, pred(in, in, out) is cc_multi, in, out) is cc_multi.
:- mode map_index(in, pred(in, in, out) is multi, in, out) is multi.
map_index(_, _, [], []).
map_index(I, P, [X | Xs], [Y | Ys]) :- P(I, X, Y), map_index(I, P, Xs, Ys).
map_index(P, Xs, Ys) :- map_index(0, P, Xs, Ys).
map_index(F, Xs) = Ys :-
P = (pred(I::in, X::in, Y::out) is det :- Y = F(I, X)),
map_index(P, Xs, Ys).
:- pred foldl_index(int, pred(int, T, U, U), list(T), U, U).
:- mode foldl_index(in, pred(in, in, in, out) is det, in, in, out) is det.
:- mode foldl_index(in, pred(in, in, di, uo) is det, in, di, uo) is det.
:- mode foldl_index(in, pred(in, di, di, uo) is det, di, di, uo) is det.
:- mode foldl_index(in, pred(in, in, in, out) is semidet, in, in, out) is semidet.
:- mode foldl_index(in, pred(in, in, in, out) is multi, in, in, out) is multi.
:- mode foldl_index(in, pred(in, in, in, out) is cc_multi, in, in, out) is cc_multi.
foldl_index(_, _, [], !Acc).
foldl_index(I, P, [X | Xs], !Acc) :-
P(I, X, !Acc),
foldl_index(I + 1, P, Xs, !Acc).
foldl_index(P, Xs, !Acc) :- foldl_index(0, P, Xs, !Acc).
foldl_index(F, Xs, Start) = End :-
P = (pred(I::in, X::in, A::in, B::out) is det :- B = F(I, X, A)),
foldl_index(P, Xs, Start, End).
to_int_may(Str) = Out :-
if to_int(Str, N) then Out = yes(N) else Out = no.