marginally more readable d8p2
This commit is contained in:
parent
668be81650
commit
16733a03c8
51
08/part2.pl
51
08/part2.pl
@ -10,15 +10,16 @@ answer(Answer) :-
|
|||||||
|
|
||||||
% unify2 combines 2 routes into one with its own stride-offsets-dests
|
% unify2 combines 2 routes into one with its own stride-offsets-dests
|
||||||
unify2(Route1, Route2, NewRoute) :-
|
unify2(Route1, Route2, NewRoute) :-
|
||||||
|
writef('Combining %t + %t', [Route1, Route2]),
|
||||||
once(findnsols(2, S, converge(Route1, Route2, S), SolutionPair)),
|
once(findnsols(2, S, converge(Route1, Route2, S), SolutionPair)),
|
||||||
SolutionPair = [NewA-LenA-NewZ, _-LenB-_],
|
SolutionPair = [NewA-LenA-NewZ, _-LenB-_],
|
||||||
NewStride is LenB - LenA,
|
NewStride is LenB - LenA,
|
||||||
NewRoute = NewA-(NewStride-LenA-[0-NewZ]).
|
NewRoute = NewA-(NewStride-LenA-[0-NewZ]),
|
||||||
|
writef(' --> %t\n', [NewRoute]).
|
||||||
|
|
||||||
% Len = Stride1*X1 + Offset1 + Dest1 = Stride2*X2 + Offset2 + Dest2
|
% Len = Stride1*X1 + Offset1 + Dest1 = Stride2*X2 + Offset2 + Dest2
|
||||||
% For performance, Route1's Stride should =< Route2's Stride
|
% For performance, Route1's Stride should =< Route2's Stride
|
||||||
converge(Route1, Route2, NewA-Len-NewZ) :-
|
converge(Route1, Route2, NewA-Len-NewZ) :-
|
||||||
writef('Combining %t - %t\n', [Route1, Route2]),
|
|
||||||
Route1 = A1-(Stride1-Offset1-Dests1),
|
Route1 = A1-(Stride1-Offset1-Dests1),
|
||||||
Route2 = A2-(Stride2-Offset2-Dests2),
|
Route2 = A2-(Stride2-Offset2-Dests2),
|
||||||
natnum(X2),
|
natnum(X2),
|
||||||
@ -28,42 +29,38 @@ converge(Route1, Route2, NewA-Len-NewZ) :-
|
|||||||
atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ).
|
atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ).
|
||||||
|
|
||||||
routes(Starts, Routes) :-
|
routes(Starts, Routes) :-
|
||||||
maplist([S, S-Route]>>(zloop(S, Route)), Starts, Routes).
|
maplist([S, S-Route]>>(route_at(S, Route)), Starts, Routes).
|
||||||
|
|
||||||
% zloop builds a route (Stride-Offset-Internals) for a particular starting node.
|
% route_at(N, Node, Dests, AllDests) means going N steps will arrive at Node
|
||||||
zloop(Node, Route) :- zloop([], Node, 0, [], Route).
|
% passing through Dests.
|
||||||
zloop(_Direction, _Node, _Index, Zs, Stride-Offset-Dests) :-
|
route_at(Start, Route) :- route_at(0, Start, [], Route).
|
||||||
Zs = [FirstZIndex-Z | _], reverse(Zs, [LastZIndex-Z | ReversedZs]),
|
route_at(N, FirstZ, [FirstZN-FirstZ | Zs], Stride-Offset-AllZs) :-
|
||||||
DeltaZ is LastZIndex - FirstZIndex, DeltaZ =\= 0,
|
Stride is N - FirstZN, direction_looped(Stride),
|
||||||
direction_len(Len),
|
Offset is FirstZN,
|
||||||
divmod(DeltaZ, Len, _, 0),
|
maplist({Offset}/[N-X, M-X]>>(M is N-Offset), [FirstZN-FirstZ | Zs], AllZs),
|
||||||
Offset = FirstZIndex, Stride = DeltaZ,
|
|
||||||
foldl([Idx-Z, NewIdx-Z, Off, Off]>>(NewIdx is Idx - Off),
|
|
||||||
ReversedZs, ReversedDests, Offset, _),
|
|
||||||
reverse(ReversedDests, Dests),
|
|
||||||
!.
|
!.
|
||||||
zloop(Directions, Node, Index, Zs, Route) :-
|
route_at(N, At, Dests, AllDests) :-
|
||||||
( is_end(Node)
|
( is_end(At)
|
||||||
-> append(Zs, [Index-Node], NewZs)
|
-> append(Dests, [N-At], NextDests)
|
||||||
; NewZs = Zs
|
; NextDests = Dests),
|
||||||
),
|
Nplus1 is N + 1, step_at(N, Step), call(Step, At, NextNode),
|
||||||
next_step(Directions, Move, Remain),
|
route_at(Nplus1, NextNode, NextDests, AllDests).
|
||||||
G =.. [Move, Node, To], G,
|
|
||||||
NewIndex is Index + 1,
|
|
||||||
zloop(Remain, To, NewIndex, NewZs, Route).
|
|
||||||
|
|
||||||
starts(Starts) :- findall(X, X to _, Nodes), include(is_start, Nodes, Starts).
|
starts(Starts) :- findall(X, X to _, Nodes), include(is_start, Nodes, Starts).
|
||||||
|
|
||||||
is_start(Node) :- atom_chars(Node, [_, _, a]).
|
is_start(Node) :- atom_chars(Node, [_, _, a]).
|
||||||
is_end(Node) :- atom_chars(Node, [_, _, z]).
|
is_end(Node) :- atom_chars(Node, [_, _, z]).
|
||||||
|
|
||||||
next_step([Move | Remain], Move, Remain).
|
% Step is the N-th step (counting starts from 0).
|
||||||
next_step([], Move, Remain) :- direction_list([Move | Remain]).
|
step_at(N, Step) :-
|
||||||
|
direction_list(Dir), length(Dir, DirLen), Remainder is N mod DirLen,
|
||||||
|
nth0(Remainder, Dir, Step).
|
||||||
|
|
||||||
direction_list(Dir) :- direction(Str), atom_chars(Str, Dir).
|
direction_list(Dir) :- direction(Str), atom_chars(Str, Dir).
|
||||||
direction_len(Len) :- direction_list(D), length(D, Len).
|
direction_looped(Len) :- direction_list(D), length(D, DLen), 0 is Len mod DLen.
|
||||||
|
|
||||||
% pick([[1,2,3], [4], [5,6]], X). X = [1,4,5]; X = [1,4,6]; X = [2,4,5]; ...
|
% pick one item from each sublist of ListOfLists & put them into Items in order.
|
||||||
|
% [[1,2,3], [4], [5,6]] -> [1,4,5]; [1,4,6]; [2,4,5]; [2,4,6]; [3,4,5]; [3,4,6].
|
||||||
pick(ListOfLists, Items) :-
|
pick(ListOfLists, Items) :-
|
||||||
maplist([SubList, X]>>(member(X, SubList)), ListOfLists, Items).
|
maplist([SubList, X]>>(member(X, SubList)), ListOfLists, Items).
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user