From 3c76445fccb67274d9df548cad7721bc0747a272 Mon Sep 17 00:00:00 2001 From: rhiannon morris Date: Sun, 4 Dec 2022 06:45:57 +0100 Subject: [PATCH] day4 --- aoc.m | 2 ++ day4.m | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 day4.m diff --git a/aoc.m b/aoc.m index ef32f1d..9bd6492 100644 --- a/aoc.m +++ b/aoc.m @@ -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. diff --git a/day4.m b/day4.m new file mode 100644 index 0000000..3e29d45 --- /dev/null +++ b/day4.m @@ -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).