diff --git a/aoc.bqn b/aoc.bqn index e68f9a3..c2d0006 100644 --- a/aoc.bqn +++ b/aoc.bqn @@ -1,6 +1,11 @@ +# a‿b Sub x: the b-length subarray starting at a +Sub ⇐ {a‿b𝕊𝕩:b↑a↓𝕩} + +# e Split xs: split xs on occurrences of e (default 0) +Split ⇐ {Sub⟜𝕩¨ ((1+») ⋈¨ ⊢-») /(𝕨⊣0)=𝕩} + Day1 ⇐ { - nums ← •BQN⎊0¨ •FLines 𝕩 - sums ← ∨ (+´ {𝕩↑𝕨↓nums}´)¨ (»⋈¨ ⊢-») /0=nums - ⟨⊑sums, +´ 3↑sums⟩ + sums ← ∨+´¨ Split •BQN⎊0¨ •FLines 𝕩 + ⟨⊑sums, +´3↑sums⟩ } •Show Day1 ⊑•args diff --git a/aoc.m b/aoc.m index 3d84b57..f108fa1 100644 --- a/aoc.m +++ b/aoc.m @@ -31,6 +31,8 @@ main2(!IO) :- :- pred solution(int::in, sol::out(sol)) is semidet. :- import_module day1. solution(1, day1.run). +:- import_module day2. +solution(2, day2.run). :- pred run_day(int, part, list(string), univ). :- mode run_day(in, in, in, out) is cc_multi. diff --git a/day2.m b/day2.m new file mode 100644 index 0000000..3354d15 --- /dev/null +++ b/day2.m @@ -0,0 +1,112 @@ +% this could be probably like ¼ the length +% but i wanted to write grammars and bidirectional predicates ok +% leave me alone + +:- module day2. +:- 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 pair. + +:- type move ---> rock; paper; scissors. +:- type moves == pair(move). + +:- type result ---> me; you; draw. +:- type move_res == pair(move, result). + +:- type chars == list(char). + +:- type parser(T) == (pred(T, chars, chars)). +:- mode parser(I) == (pred(out(I), in, out) is semidet). +:- mode parser == parser(ground). + +:- pred hand1(move::out, chars::in, chars::out) is semidet. +hand1(rock) --> ['A']. +hand1(paper) --> ['B']. +hand1(scissors) --> ['C']. + +:- pred hand2(move::out, chars::in, chars::out) is semidet. +hand2(rock) --> ['X']. +hand2(paper) --> ['Y']. +hand2(scissors) --> ['Z']. + +:- pred result(result::out, chars::in, chars::out) is semidet. +result(you) --> ['X']. +result(draw) --> ['Y']. +result(me) --> ['Z']. + +:- pred two(parser(T)::parser, parser(U)::parser, + T::out, U::out, + chars::in, chars::out) is semidet. +two(P, Q, A, B) --> P(A), [' '], Q(B). + +:- pred line1(moves::out, chars::in, chars::out) is semidet. +line1(A - B) --> two(hand1, hand2, A, B). + +:- pred line2(move_res::out, chars::in, chars::out) is semidet. +line2(A - B) --> two(hand1, result, A, B). + + +:- pred parse_line(parser(T)::parser, string::in, T::out) is semidet. +parse_line(P, Str, X) :- P(X, to_char_list(Str), []). + + +:- pred to_int(move, int). +:- mode to_int(in, out) is det. +:- mode to_int(out, in) is semidet. +to_int(rock, 1). +to_int(paper, 2). +to_int(scissors, 3). + +:- func to_int(move) = int. +to_int(A) = B :- to_int(A, B). + + +:- pred win(move, move, result). +:- mode win(in, in, out) is det. +:- mode win(in, out, in) is det. +% you me +win(rock, rock, draw). +win(rock, paper, me). +win(rock, scissors, you). +win(paper, rock, you). +win(paper, paper, draw). +win(paper, scissors, me). +win(scissors, rock, me). +win(scissors, paper, you). +win(scissors, scissors, draw). + +:- func win_score(result) = int. +win_score(me) = 6. +win_score(you) = 0. +win_score(draw) = 3. + +:- func score1(move, move) = int. +score1(You, Me) = to_int(Me) + win_score(Res) :- win(You, Me, Res). + +:- func score2(move, result) = int. +score2(You, Res) = to_int(Me) + win_score(Res) :- win(You, Me, Res). + +:- func sum(list(int)) = int. +sum(Xs) = foldl(plus, Xs, 0). + + +:- pred run(list(string)::in, parser(pair(T, U))::parser, + (func(T, U) = int)::in, int::out) is det. +run(Lines, P, F, Out) :- + if map(parse_line(P), Lines, Res) then + Out = sum(map(func(X - Y) = F(X, Y), Res)) + else + die("invalid input"). % lol + +:- pragma no_determinism_warning(run/3). +run(one, Lines, univ(Out)) :- run(Lines, line1, score1, Out). +run(two, Lines, univ(Out)) :- run(Lines, line2, score2, Out).