aoc2022/day4.m

55 lines
1.5 KiB
Mathematica
Raw Normal View History

2022-12-04 00:45:57 -05:00
:- module day4.
:- 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.
:- type ranges ---> r(int, int, int, int).
:- pred number(int::out, chars::in, chars::out) is semidet.
number(N) --> digits(S), {to_int(from_char_list(S), N)}.
:- pred digits(chars::out, chars::in, chars::out) is semidet.
digits([C | Cs]) -->
[C], {is_digit(C)},
(if digits(Cs2) then {Cs = Cs2} else {Cs = []}).
:- pred int_pair(int::out, int::out, chars::in, chars::out) is semidet.
int_pair(A, B) --> number(A), ['-'], number(B).
:- pred ranges(ranges::out, chars::in, chars::out) is semidet.
ranges(r(A, B, C, D)) --> int_pair(A, B), [','], int_pair(C, D).
:- pred ranges(string::in, ranges::out) is det.
ranges(Str, R) :-
if ranges(R2, to_char_list(Str), []) then R = R2
else die("invalid line: ""%s""", [s(Str)]).
:- pred all_overlap(ranges::in) is semidet.
all_overlap(r(A, B, C, D)) :- C >= A, D =< B ; D >= B, C =< A.
:- pred any_overlap(ranges::in) is semidet.
any_overlap(r(A, B, C, D)) :- A =< C, B >= C ; C =< A, D >= A.
:- pred go(pred(ranges)::(pred(in) is semidet),
list(string)::in, int::out) is det.
go(P, Lines, Out) :-
map(ranges, Lines, Ranges),
filter(P, Ranges, Overlaps),
length(Overlaps, Out).
:- pragma no_determinism_warning(run/3).
run(one, Lines, univ(Out)) :- go(all_overlap, Lines, Out).
run(two, Lines, univ(Out)) :- go(any_overlap, Lines, Out).