diff --git a/Makefile b/Makefile index 7c01f0e..05728b7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -MMCFLAGS := -s asm_fast.par.gc.stseg +# this seems to break day7 for some absolutely bizarre reason +MMCFLAGS := # -s asm_fast.par.gc.stseg all: aoc diff --git a/aoc.m b/aoc.m index 8a9ffdc..cb7a7b4 100644 --- a/aoc.m +++ b/aoc.m @@ -23,11 +23,11 @@ main2(!IO) :- then read_lines_need(File, Lines, !IO), run_day(Day, Part, Lines, Out), - write_line(univ_value(Out), !IO) + output(Out, !IO) else die("expected day, part, filename")). -:- pred run_day(int, part, lines, univ). +:- pred run_day(int, part, lines, answer). :- mode run_day(in, in, in, out) is cc_multi. run_day(Day, Part, Lines, Out) :- if solution(Day, P) then @@ -35,7 +35,7 @@ run_day(Day, Part, Lines, Out) :- else die("no solution for day %d", [i(Day)]). -:- type sol == (pred(part, lines, univ)). +:- type sol == (pred(part, lines, answer)). :- inst sol == (pred(in, in, out) is cc_multi). :- import_module day1. @@ -47,6 +47,7 @@ run_day(Day, Part, Lines, Out) :- :- import_module day7. :- import_module day8. :- import_module day9. +:- import_module day10. :- pred solution(int::in, sol::out(sol)) is semidet. solution(1, day1.run). @@ -58,3 +59,4 @@ solution(6, day6.run). solution(7, day7.run). solution(8, day8.run). solution(9, day9.run). +solution(10, day10.run). diff --git a/basics.m b/basics.m index d5adbc6..a2890d4 100644 --- a/basics.m +++ b/basics.m @@ -1,5 +1,6 @@ :- module basics. :- interface. +:- import_module io. :- type part ---> one; two. :- pred part(string, part). @@ -8,8 +9,10 @@ :- func part(part, T, T) = T. +:- type answer ---> int(int); string(string); lines(list(string)). +:- pred output(answer::in, io::di, io::uo) is det. + -:- import_module io. :- import_module list. :- import_module string. @@ -52,6 +55,10 @@ part(one, X, _) = X. part(two, _, Y) = Y. +output(int(I), !IO) :- write_int(I, !IO), nl(!IO). +output(string(S), !IO) :- write_string(S, !IO), nl(!IO). +output(lines(Ss), !IO) :- write_list(Ss, "\n", write_string, !IO), nl(!IO). + :- import_module exception. :- type die ---> death(string). diff --git a/day1.m b/day1.m index 851ea34..aa10a24 100644 --- a/day1.m +++ b/day1.m @@ -1,9 +1,8 @@ :- module day1. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. :- import_module list. @@ -13,8 +12,8 @@ :- import_module int. :- pragma no_determinism_warning(run/3). -run(one, Lines, univ(det_head(go(Lines)))). -run(two, Lines, univ(sum(take_upto(3, go(Lines))))). +run(one, Lines, int(det_head(go(Lines)))). +run(two, Lines, int(sum(take_upto(3, go(Lines))))). :- func go(lines) = list(int). go(Lines) = diff --git a/day10.m b/day10.m new file mode 100644 index 0000000..8cb5af6 --- /dev/null +++ b/day10.m @@ -0,0 +1,66 @@ +:- module day10. +:- interface. +:- import_module basics. + +:- pred run(part::in, lines::in, answer::out) is cc_multi. + +:- implementation. +:- import_module int. +:- import_module string. +:- import_module list. +:- import_module char. + +:- type instr ---> noop; addx(int). + +:- pred line(instr::out, list(string)::in, list(string)::out) is semidet. +line(noop) --> ["noop"]. +line(addx(N)) --> ["addx", X], {to_int(X, N)}. + +:- pred line(string::in, instr::out) is semidet. +line(Str, I) :- line(I, words(Str), []). + + +:- type reg == int. +:- type cycle == int. +:- type signal == int. + +:- pred regs(reg::in, list(instr)::in, list(reg)::out) is det. +regs(_, [], []). +regs(R, [noop | Is], [R | Ss]) :- + regs(R, Is, Ss). +regs(R, [addx(N) | Is], [R, R | Ss]) :- + regs(R + N, Is, Ss). + +:- pred regs(lines::in, list(signal)::out) is semidet. +regs(Lines, Signals) :- + map(line, Lines, Instrs), + regs(1, Instrs, Signals). + +:- func signals(cycle, list(reg)) = list(reg). +signals(_, []) = []. +signals(C, [R | Rs]) = [C * R | signals(C + 1, Rs)]. + +:- func signals(list(reg)) = list(reg). +signals(Rs) = signals(1, Rs). + + +:- func render1(cycle, list(reg)) = list(char). +render1(_, []) = []. +render1(C, [R | Rs]) = [X | Xs] :- + (if abs(R - C) =< 1 then X = '█' else X = ' '), + Xs = render1((C + 1) mod 40, Rs). + +:- func render(list(reg)) = lines. +render(Rs) = map(from_char_list, chunk(render1(0, Rs), 40)). + +:- pragma no_determinism_warning(run/3). +run(Part, Lines, Out) :- + if regs(Lines, Regs) + then + ( Part = one, + Indices = [20, 60, 100, 140, 180, 220], + Out = int(sum(map(det_index1(signals(Regs)), Indices))) + ; Part = two, + Out = lines(render(Regs)) + ) + else die("bad input"). diff --git a/day2.m b/day2.m index 3a6dac3..a12016b 100644 --- a/day2.m +++ b/day2.m @@ -6,9 +6,8 @@ :- interface. :- import_module basics. :- import_module list. -:- import_module univ. -:- pred run(part::in, list(string)::in, univ::out) is cc_multi. +:- pred run(part::in, list(string)::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -97,5 +96,5 @@ run(Lines, P, F, Out) :- 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). +run(one, Lines, int(Out)) :- run(Lines, line1, score1, Out). +run(two, Lines, int(Out)) :- run(Lines, line2, score2, Out). diff --git a/day3.m b/day3.m index 77cd651..f2089d0 100644 --- a/day3.m +++ b/day3.m @@ -2,9 +2,8 @@ :- interface. :- import_module basics. :- import_module list. -:- import_module univ. -:- pred run(part::in, list(string)::in, univ::out) is cc_multi. +:- pred run(part::in, list(string)::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -60,9 +59,8 @@ go2(t(X, Y, Z), Prio) :- die("no item in common in:\n - %s\n - %s\n - %s", [s(X), s(Y), s(Z)]). -run(one, Lines, univ(sum(Prios))) :- - map(go1, Lines, Prios). -run(two, Lines, univ(sum(Prios))) :- +run(one, Lines, int(sum(Prios))) :- map(go1, Lines, Prios). +run(two, Lines, int(sum(Prios))) :- if threes(Lines, Groups) then map(go2, Groups, Prios) else diff --git a/day4.m b/day4.m index 97cc7a1..ef2e318 100644 --- a/day4.m +++ b/day4.m @@ -1,9 +1,8 @@ :- module day4. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- pred number(int::out, chars::in, chars::out) is semidet. @@ -50,5 +49,5 @@ go(P, Lines, 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). +run(one, Lines, int(Out)) :- go(all_overlap, Lines, Out). +run(two, Lines, int(Out)) :- go(any_overlap, Lines, Out). diff --git a/day5.m b/day5.m index a8e0342..1b93090 100644 --- a/day5.m +++ b/day5.m @@ -1,9 +1,8 @@ :- module day5. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -96,7 +95,7 @@ interp(Part, {Count, From, To}) --> take_n(From, Count, Res), put_n(Part, To, Res). :- pragma no_determinism_warning(run/3). -run(Part, Lines, univ(Out)) :- +run(Part, Lines, string(Out)) :- if input(Towers, Insts, Lines, []) then foldl(interp(Part), Insts, Towers, Res), from_char_list(map(det_head, Res), Out) diff --git a/day6.m b/day6.m index ee8f8b5..8fe8bcc 100644 --- a/day6.m +++ b/day6.m @@ -1,9 +1,8 @@ :- module day6. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -26,7 +25,7 @@ length(one) = 4. length(two) = 14. :- pragma no_determinism_warning(run/3). -run(Part, Lines, univ(Out)) :- +run(Part, Lines, int(Out)) :- if Lines = [Line] then Len = length(Part), (if start_index(Len, to_char_list(Line), Out0) diff --git a/day7.m b/day7.m index ab36eb8..17d5d2b 100644 --- a/day7.m +++ b/day7.m @@ -1,9 +1,8 @@ :- module day7. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -53,5 +52,5 @@ go(one, Top, sum(map(size, Found))) :- go(two, Top, det_head(sort(map(size, Found)))) :- find(size_gte(size(Top) - 40_000_000), Top, Found). -run(Part, Lines, univ(Out)) :- +run(Part, Lines, int(Out)) :- if dir(Top, Lines, []) then go(Part, Top, Out) else die("bad input"). diff --git a/day8.m b/day8.m index cdf3205..fdbbf00 100644 --- a/day8.m +++ b/day8.m @@ -1,9 +1,8 @@ :- module day8. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. diff --git a/day9.m b/day9.m index b570e9b..dbc5428 100644 --- a/day9.m +++ b/day9.m @@ -1,9 +1,8 @@ :- module day9. :- interface. :- import_module basics. -:- import_module univ. -:- pred run(part::in, lines::in, univ::out) is cc_multi. +:- pred run(part::in, lines::in, answer::out) is cc_multi. :- implementation. :- import_module int. @@ -95,7 +94,7 @@ run0(Part, Lines, Out) :- foldl2(next, condense(Dirs), Start, _, init, End), count(End, Out). -run(Part, Lines, univ(Out)) :- +run(Part, Lines, int(Out)) :- disable_warning [no_solution_disjunct] ( not run0(Part, Lines, Out) => die("bad input") ).