aoc2022/day3.m

60 lines
1.4 KiB
Mathematica
Raw Normal View History

2022-12-03 00:33:45 -05:00
:- module day3.
:- interface.
:- import_module basics.
:- import_module list.
:- import_module univ.
:- pred run(part::in, list(string)::in, univ::out) is cc_multi.
:- implementation.
:- import_module int.
:- import_module char.
:- import_module string.
:- import_module exception.
:- pred split(chars::in, chars::out, chars::out) is semidet.
split(X, L, H) :-
Len = length(X), even(Len),
split_list(Len / 2, X, L, H).
:- pred common(list(chars)::in, char::out) is nondet.
common([S | Ss], C) :- member(C, S), (Ss = [] ; common(Ss, C)).
2022-12-03 00:55:52 -05:00
:- func prio(char) = int.
prio(C) = I :-
2022-12-03 00:33:45 -05:00
if is_lower(C) then
I = to_int(C) - to_int('a') + 1
else
I = to_int(C) - to_int('A') + 27.
:- pred threes(list(T)::in, list(list(T))::out) is semidet.
threes([], []).
threes([X, Y, Z | Rest], [[X, Y, Z] | Groups]) :- threes(Rest, Groups).
:- pred go1(string::in, int::out) is cc_multi.
go1(Line, Out) :-
if split(to_char_list(Line), Fst, Snd),
common([Fst, Snd], C)
then
2022-12-03 00:55:52 -05:00
Out = prio(C)
2022-12-03 00:33:45 -05:00
else
die("invalid line: ""%s""", [s(Line)]).
:- pred go2(list(string)::in, int::out) is cc_multi.
2022-12-03 00:55:52 -05:00
go2(Lines, Prio) :-
2022-12-03 00:33:45 -05:00
if common(map(to_char_list, Lines), C) then
2022-12-03 00:55:52 -05:00
Prio = prio(C)
2022-12-03 00:33:45 -05:00
else
die("no item in common").
2022-12-03 00:55:52 -05:00
run(one, Lines, univ(sum(Prios))) :-
map(go1, Lines, Prios).
run(two, Lines, univ(sum(Prios))) :-
2022-12-03 00:33:45 -05:00
if threes(Lines, Groups) then
2022-12-03 00:55:52 -05:00
map(go2, Groups, Prios)
2022-12-03 00:33:45 -05:00
else
die("not a multiple of three lines").