d8p2 final optimized general solution
This commit is contained in:
parent
a997d00c89
commit
cd18e701c5
62
08/part2.pl
62
08/part2.pl
@ -5,51 +5,32 @@ From r To :- From to _-To.
|
|||||||
|
|
||||||
answer(Answer) :-
|
answer(Answer) :-
|
||||||
starts(Starts),
|
starts(Starts),
|
||||||
routes(Starts, Routes),
|
routes(Starts, [Route1 | RestOfRoutes]),
|
||||||
collapse_routes(Routes, _-(_-Answer-_)).
|
foldl(unify2, RestOfRoutes, Route1, _-(_-Answer-_)).
|
||||||
|
|
||||||
collapse_routes([X], X).
|
|
||||||
collapse_routes(Routes, Collapsed) :-
|
|
||||||
writef('Collapsing: %t\n', [Routes]),
|
|
||||||
sort(2, @=<, Routes, [Route1, Route2 | CdrRoutes]),
|
|
||||||
unify2(Route1, Route2, NewRoute),
|
|
||||||
collapse_routes([NewRoute | CdrRoutes], Collapsed).
|
|
||||||
|
|
||||||
% 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, Route12) :- unify2(Route1, Route2, 0-0-0-0, [], Route12).
|
unify2(Route1, Route2, NewRoute) :-
|
||||||
unify2(Route1, Route2, N1-Dest1-N2-Dest2, Founds, NewRoute) :-
|
once(findnsols(2, S, converge(Route1, Route2, S), SolutionPair)),
|
||||||
|
SolutionPair = [NewA-LenA-NewZ, _-LenB-_],
|
||||||
|
NewStride is LenB - LenA,
|
||||||
|
NewRoute = NewA-(NewStride-LenA-[0-NewZ]).
|
||||||
|
|
||||||
|
% Len = Stride1*X1 + Offset1 + Dest1 = Stride2*X2 + Offset2 + Dest2
|
||||||
|
% For performance, Route1's Stride should =< Route2's Stride
|
||||||
|
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),
|
||||||
nth0(Dest1, Dests1, C1-Z1),
|
natnum(X2),
|
||||||
nth0(Dest2, Dests2, C2-Z2),
|
pick([Dests1, Dests2], [Dest1-Z1, Dest2-Z2]),
|
||||||
Len1 is Offset1 + Stride1*N1 + C1,
|
0 is (Stride2*X2 + Offset2 + Dest2 - Offset1 - Dest1) mod Stride1,
|
||||||
Len2 is Offset2 + Stride2*N2 + C2,
|
Len is Stride2*X2 + Offset2 + Dest2,
|
||||||
next(Dests1, N1-Dest1, NextN1-NextDest1),
|
atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ).
|
||||||
( Len1 =:= Len2
|
|
||||||
-> ( Founds = [OldLen]
|
|
||||||
-> atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ),
|
|
||||||
NewStride is Len1 - OldLen,
|
|
||||||
NewRoute = NewA-(NewStride-OldLen-[0-NewZ]),
|
|
||||||
!
|
|
||||||
; unify2(Route1, Route2, NextN1-NextDest1-N2-Dest2, [Len1], NewRoute)
|
|
||||||
)
|
|
||||||
; Len1 < Len2
|
|
||||||
-> unify2(Route1, Route2, NextN1-NextDest1-N2-Dest2, Founds, NewRoute)
|
|
||||||
; next(Dests2, N2-Dest2, NextN2-NextDest2),
|
|
||||||
unify2(Route1, Route2, N1-Dest1-NextN2-NextDest2, Founds, NewRoute)
|
|
||||||
).
|
|
||||||
|
|
||||||
% next(Dests, NumberOfLoops-WhichInternalZ, NextNumberOfLoops-NextInternalZ)
|
|
||||||
next(Dests, NLoops-Dest, NextNLoops-NextDest) :-
|
|
||||||
length(Dests, DestsLen),
|
|
||||||
( Dest < DestsLen - 1
|
|
||||||
-> NextNLoops is NLoops, NextDest is Dest + 1
|
|
||||||
; NextNLoops is NLoops + 1, NextDest is 0).
|
|
||||||
|
|
||||||
routes(Starts, Routes) :-
|
routes(Starts, Routes) :-
|
||||||
maplist([S, S-Route]>>(zloop(S, Route)), Starts, Routes).
|
maplist([S, S-Route]>>(zloop(S, Route)), Starts, Routes).
|
||||||
|
|
||||||
% zloop builds a route (Stride-Offset-Internals for a particular starting node.
|
% zloop builds a route (Stride-Offset-Internals) for a particular starting node.
|
||||||
zloop(Node, Route) :- zloop([], Node, 0, [], Route).
|
zloop(Node, Route) :- zloop([], Node, 0, [], Route).
|
||||||
zloop(_Direction, _Node, _Index, Zs, Stride-Offset-Dests) :-
|
zloop(_Direction, _Node, _Index, Zs, Stride-Offset-Dests) :-
|
||||||
Zs = [FirstZIndex-Z | _], reverse(Zs, [LastZIndex-Z | ReversedZs]),
|
Zs = [FirstZIndex-Z | _], reverse(Zs, [LastZIndex-Z | ReversedZs]),
|
||||||
@ -81,3 +62,10 @@ next_step([], Move, Remain) :- direction_list([Move | Remain]).
|
|||||||
|
|
||||||
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_len(Len) :- direction_list(D), length(D, Len).
|
||||||
|
|
||||||
|
% pick([[1,2,3], [4], [5,6]], X). X = [1,4,5]; X = [1,4,6]; X = [2,4,5]; ...
|
||||||
|
pick(ListOfLists, Items) :-
|
||||||
|
maplist([SubList, X]>>(member(X, SubList)), ListOfLists, Items).
|
||||||
|
|
||||||
|
natnum(0).
|
||||||
|
natnum(N) :- natnum(N0), N is N0 + 1.
|
||||||
|
83
08/part2.unoptimized.pl
Normal file
83
08/part2.unoptimized.pl
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
:- op(700, xfx, l).
|
||||||
|
:- op(700, xfx, r).
|
||||||
|
From l To :- From to To-_.
|
||||||
|
From r To :- From to _-To.
|
||||||
|
|
||||||
|
answer(Answer) :-
|
||||||
|
starts(Starts),
|
||||||
|
routes(Starts, Routes),
|
||||||
|
collapse_routes(Routes, _-(_-Answer-_)).
|
||||||
|
|
||||||
|
collapse_routes([X], X).
|
||||||
|
collapse_routes(Routes, Collapsed) :-
|
||||||
|
writef('Collapsing: %t\n', [Routes]),
|
||||||
|
sort(2, @=<, Routes, [Route1, Route2 | CdrRoutes]),
|
||||||
|
unify2(Route1, Route2, NewRoute),
|
||||||
|
collapse_routes([NewRoute | CdrRoutes], Collapsed).
|
||||||
|
|
||||||
|
% unify2 combines 2 routes into one with its own stride-offsets-dests
|
||||||
|
unify2(Route1, Route2, Route12) :- unify2(Route1, Route2, 0-0-0-0, [], Route12).
|
||||||
|
unify2(Route1, Route2, N1-Dest1-N2-Dest2, Founds, NewRoute) :-
|
||||||
|
Route1 = A1-(Stride1-Offset1-Dests1),
|
||||||
|
Route2 = A2-(Stride2-Offset2-Dests2),
|
||||||
|
nth0(Dest1, Dests1, C1-Z1),
|
||||||
|
nth0(Dest2, Dests2, C2-Z2),
|
||||||
|
Len1 is Offset1 + Stride1*N1 + C1,
|
||||||
|
Len2 is Offset2 + Stride2*N2 + C2,
|
||||||
|
next(Dests1, N1-Dest1, NextN1-NextDest1),
|
||||||
|
( Len1 =:= Len2
|
||||||
|
-> ( Founds = [OldLen]
|
||||||
|
-> atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ),
|
||||||
|
NewStride is Len1 - OldLen,
|
||||||
|
NewRoute = NewA-(NewStride-OldLen-[0-NewZ]),
|
||||||
|
!
|
||||||
|
; unify2(Route1, Route2, NextN1-NextDest1-N2-Dest2, [Len1], NewRoute)
|
||||||
|
)
|
||||||
|
; Len1 < Len2
|
||||||
|
-> unify2(Route1, Route2, NextN1-NextDest1-N2-Dest2, Founds, NewRoute)
|
||||||
|
; next(Dests2, N2-Dest2, NextN2-NextDest2),
|
||||||
|
unify2(Route1, Route2, N1-Dest1-NextN2-NextDest2, Founds, NewRoute)
|
||||||
|
).
|
||||||
|
|
||||||
|
% next(Dests, NumberOfLoops-WhichInternalZ, NextNumberOfLoops-NextInternalZ)
|
||||||
|
next(Dests, NLoops-Dest, NextNLoops-NextDest) :-
|
||||||
|
length(Dests, DestsLen),
|
||||||
|
( Dest < DestsLen - 1
|
||||||
|
-> NextNLoops is NLoops, NextDest is Dest + 1
|
||||||
|
; NextNLoops is NLoops + 1, NextDest is 0).
|
||||||
|
|
||||||
|
routes(Starts, Routes) :-
|
||||||
|
maplist([S, S-Route]>>(zloop(S, Route)), Starts, Routes).
|
||||||
|
|
||||||
|
% zloop builds a route (Stride-Offset-Internals for a particular starting node.
|
||||||
|
zloop(Node, Route) :- zloop([], Node, 0, [], Route).
|
||||||
|
zloop(_Direction, _Node, _Index, Zs, Stride-Offset-Dests) :-
|
||||||
|
Zs = [FirstZIndex-Z | _], reverse(Zs, [LastZIndex-Z | ReversedZs]),
|
||||||
|
DeltaZ is LastZIndex - FirstZIndex, DeltaZ =\= 0,
|
||||||
|
direction_len(Len),
|
||||||
|
divmod(DeltaZ, Len, _, 0),
|
||||||
|
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) :-
|
||||||
|
( is_end(Node)
|
||||||
|
-> append(Zs, [Index-Node], NewZs)
|
||||||
|
; NewZs = Zs
|
||||||
|
),
|
||||||
|
next_step(Directions, Move, Remain),
|
||||||
|
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).
|
||||||
|
|
||||||
|
is_start(Node) :- atom_chars(Node, [_, _, a]).
|
||||||
|
is_end(Node) :- atom_chars(Node, [_, _, z]).
|
||||||
|
|
||||||
|
next_step([Move | Remain], Move, Remain).
|
||||||
|
next_step([], Move, Remain) :- direction_list([Move | Remain]).
|
||||||
|
|
||||||
|
direction_list(Dir) :- direction(Str), atom_chars(Str, Dir).
|
||||||
|
direction_len(Len) :- direction_list(D), length(D, Len).
|
@ -8,4 +8,12 @@ nna to nnb-xxx.
|
|||||||
nnb to nnc-nnc.
|
nnb to nnc-nnc.
|
||||||
nnc to nnz-nnz.
|
nnc to nnz-nnz.
|
||||||
nnz to nnb-nnb.
|
nnz to nnb-nnb.
|
||||||
|
ooa to ooz-oob.
|
||||||
|
oob to ood-ooc.
|
||||||
|
ooc to ooa-oox.
|
||||||
|
ood to ooz-ood.
|
||||||
|
ooz to oob-ooz.
|
||||||
xxx to xxx-xxx.
|
xxx to xxx-xxx.
|
||||||
|
|
||||||
|
% Routes = [mma-(2-2-[0-mmz]), nna-(6-3-[0-nnz, 3-nnz]), ooa-(8-1-[0-ooz, 1-ooz])].
|
||||||
|
% X = mmannaooa-(24-18-[0-mmznnzooz]).
|
||||||
|
Loading…
Reference in New Issue
Block a user