This commit is contained in:
rhiannon morris 2022-12-04 06:45:57 +01:00
parent b1bc7ef4b6
commit 3c76445fcc
2 changed files with 56 additions and 0 deletions

2
aoc.m
View file

@ -35,6 +35,8 @@ solution(1, day1.run).
solution(2, day2.run).
:- import_module day3.
solution(3, day3.run).
:- import_module day4.
solution(4, day4.run).
:- pred run_day(int, part, list(string), univ).
:- mode run_day(in, in, in, out) is cc_multi.

54
day4.m Normal file
View file

@ -0,0 +1,54 @@
:- 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).