diff --git a/aoc.bqn b/aoc.bqn index 9ee3e24..4df2e71 100644 --- a/aoc.bqn +++ b/aoc.bqn @@ -7,8 +7,9 @@ Split ⇐ {(⊏ ∾ 1⊸↓¨∘(1⊸↓)) Sub⟜𝕩¨ (» ⋈¨ ⊢-») /𝕨= Day1 ⇐ (⊑ ⋈ (+´3⊸↑))∘(∨+´¨)∘Split∘(•BQN⎊0¨)∘•FLines Day2 ⇐ { - Line ← -⟜"AX"∘∾ ' '⊸Split B ← ⊣ (A ← {1+𝕩+3×3|1+𝕩-𝕨}) {3|𝕨+𝕩-1} - +´˘⍉ (A≍B)´∘Line˘ >•FLines 𝕩 + +´˘⍉ (A≍B)´∘{a‿s‿b:⟨a-'A',b-'X'⟩}˘ >•FLines 𝕩 } -# •Show Day2 ⊑•args +•Show Day2 ⊑•args + +# day 3 maybe later diff --git a/aoc.m b/aoc.m index f108fa1..ef32f1d 100644 --- a/aoc.m +++ b/aoc.m @@ -33,6 +33,8 @@ main2(!IO) :- solution(1, day1.run). :- import_module day2. solution(2, day2.run). +:- import_module day3. +solution(3, day3.run). :- pred run_day(int, part, list(string), univ). :- mode run_day(in, in, in, out) is cc_multi. diff --git a/basics.m b/basics.m index 236595e..b28338b 100644 --- a/basics.m +++ b/basics.m @@ -23,6 +23,16 @@ :- mode wrap_main(pred(di, uo) is det, di, uo) is cc_multi. +:- import_module char. + +:- type chars == list(char). + + +:- import_module int. + +:- func sum(list(int)) = int. + + :- import_module maybe. :- func to_int_may(string) = maybe(int). @@ -57,5 +67,8 @@ read_lines_need(File, Lines, !IO) :- need(Res, Lines). +sum(Xs) = foldl(plus, Xs, 0). + + to_int_may(Str) = Out :- if to_int(Str, N) then Out = yes(N) else Out = no. diff --git a/day1.m b/day1.m index df3589d..3676d28 100644 --- a/day1.m +++ b/day1.m @@ -27,6 +27,3 @@ gather(Xs) = Ys :- gather(Xs, Ys). gather([], [[]]). gather([no | Xs], [[] | Yss]) :- gather(Xs, Yss). gather([yes(Y) | Xs], [[Y | Ys] | Yss]) :- gather(Xs, [Ys | Yss]). - -:- func sum(list(int)) = int. -sum(Xs) = foldl(plus, Xs, 0). diff --git a/day2.m b/day2.m index d291e4d..3a6dac3 100644 --- a/day2.m +++ b/day2.m @@ -22,8 +22,6 @@ :- 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). @@ -89,9 +87,6 @@ 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. diff --git a/day3.m b/day3.m new file mode 100644 index 0000000..d9a6745 --- /dev/null +++ b/day3.m @@ -0,0 +1,59 @@ +:- 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)). + +:- func score(char) = int. +score(C) = I :- + 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 + Out = score(C) + else + die("invalid line: ""%s""", [s(Line)]). + + +:- pred go2(list(string)::in, int::out) is cc_multi. +go2(Lines, Score) :- + if common(map(to_char_list, Lines), C) then + Score = score(C) + else + die("no item in common"). + + +run(one, Lines, univ(sum(Scores))) :- + map(go1, Lines, Scores). +run(two, Lines, univ(sum(Scores))) :- + if threes(Lines, Groups) then + map(go2, Groups, Scores) + else + die("not a multiple of three lines").