61 lines
1.5 KiB
Prolog
61 lines
1.5 KiB
Prolog
:- use_module(library(dcg/basics)).
|
|
|
|
direction(left) --> "L".
|
|
direction(right) --> "R".
|
|
|
|
directions([]) --> [].
|
|
directions([D|Ds]) --> direction(D), directions(Ds).
|
|
|
|
label(L) -->
|
|
alpha_to_lower(A), alpha_to_lower(B), alpha_to_lower(C),
|
|
{atom_codes(L, [A,B,C])}.
|
|
|
|
line(A-B-C) -->
|
|
label(A), blanks, "=", blanks, "(", label(B), ",", blanks, label(C), ")".
|
|
|
|
lines([]) --> blanks.
|
|
lines([L|Ls]) --> line(L), blanks, lines(Ls).
|
|
|
|
file(Ds, Ls) --> directions(Ds), blanks, lines(Ls).
|
|
|
|
set_map(Map) :- reset_map, maplist(assert_map1, Map).
|
|
reset_map :- abolish(left/2), abolish(right/2).
|
|
assert_map1(A-B-C) :- assertz(left(A, B)), assertz(right(A, C)).
|
|
:- dynamic left/2, right/2.
|
|
|
|
loop_with(P, N, N, _, _, Z) :- call(P, Z), !.
|
|
loop_with(P, N, I, [D|Ds], All, Here) :-
|
|
call(D, Here, Next),
|
|
I1 is I + 1,
|
|
loop_with(P, N, I1, Ds, All, Next).
|
|
loop_with(P, N, I, [], All, Here) :-
|
|
loop_with(P, N, I, All, All, Here).
|
|
|
|
go(N, Ds) :- loop_with(=(zzz), N, 0, Ds, Ds, aaa).
|
|
|
|
part1(File) :-
|
|
phrase_from_file(file(Ds, Map), File),
|
|
set_map(Map),
|
|
go(N, Ds),
|
|
writeln(N).
|
|
|
|
|
|
is_start(S) :- atom_chars(S, [_, _, a]).
|
|
is_final(S) :- atom_chars(S, [_, _, z]).
|
|
|
|
starts(Xs) :- setof(X, Y^(left(X, Y), is_start(X)), Xs).
|
|
|
|
loop_multi(Ds, Here, N) :- loop_with(is_final, N, 0, Ds, Ds, Here).
|
|
|
|
go_multi(Ns, Ds) :- starts(Ss), maplist(loop_multi(Ds), Ss, Ns).
|
|
|
|
lcm(M, N, L) :- L is lcm(M, N).
|
|
|
|
part2(File) :-
|
|
phrase_from_file(file(Ds, Map), File),
|
|
set_map(Map),
|
|
go_multi(Ns, Ds),
|
|
foldl(lcm, Ns, 1, N),
|
|
writeln(N).
|
|
|
|
% vim: set ft=prolog :
|