aoc2022/day10.m

53 lines
1.4 KiB
Mathematica

:- 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 signal == int.
:- 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)].
:- func regs(list(instr)) = list(reg).
regs(Is) = regs(1, Is).
:- func signals(list(reg)) = list(reg).
signals(Rs) = map_index(func(I, R) = (I+1) * R, Rs).
:- func render(list(reg)) = lines.
render(Rs) = map(from_char_list, chunk(map_index(Render1, Rs), 40)) :-
Render1 = (func(C, R) = ite(abs(R - C mod 40) =< 1, '', ' ')).
:- pragma no_determinism_warning(run/3).
run(Part, Lines, Out) :-
if map(line, Lines, Instrs) then
Regs = regs(Instrs),
require_complete_switch [Part]
( 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").