2022-12-10 01:05:22 -05:00
|
|
|
:- 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), []).
|
|
|
|
|
|
|
|
|
2022-12-10 03:42:22 -05:00
|
|
|
:- type reg == int.
|
2022-12-10 01:05:22 -05:00
|
|
|
:- type signal == int.
|
|
|
|
|
2022-12-10 03:42:22 -05:00
|
|
|
:- func regs(reg, list(instr)) = list(reg).
|
|
|
|
regs(_, []) = [].
|
|
|
|
regs(R, [noop | Is]) = [R | regs(R, Is)].
|
|
|
|
regs(R, [addx(N) | Is]) = [R, R | regs(R + N, Is)].
|
2022-12-10 01:05:22 -05:00
|
|
|
|
2022-12-10 03:42:22 -05:00
|
|
|
:- func regs(list(instr)) = list(reg).
|
|
|
|
regs(Is) = regs(1, Is).
|
2022-12-10 01:05:22 -05:00
|
|
|
|
|
|
|
:- func signals(list(reg)) = list(reg).
|
2022-12-10 03:42:22 -05:00
|
|
|
signals(Rs) = map_index(func(I, R) = (I+1) * R, Rs).
|
2022-12-10 01:05:22 -05:00
|
|
|
|
|
|
|
:- func render(list(reg)) = lines.
|
2022-12-10 03:42:22 -05:00
|
|
|
render(Rs) = map(from_char_list, chunk(map_index(Render1, Rs), 40)) :-
|
|
|
|
Render1 = (func(C, R) = ite(abs(R - C mod 40) =< 1, '█', ' ')).
|
2022-12-10 01:05:22 -05:00
|
|
|
|
|
|
|
:- pragma no_determinism_warning(run/3).
|
|
|
|
run(Part, Lines, Out) :-
|
2022-12-10 03:42:22 -05:00
|
|
|
if map(line, Lines, Instrs) then
|
|
|
|
Regs = regs(Instrs),
|
|
|
|
require_complete_switch [Part]
|
2022-12-10 01:05:22 -05:00
|
|
|
( 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").
|