d8p2 final optimized general solution
This commit is contained in:
		
							
								
								
									
										62
									
								
								08/part2.pl
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								08/part2.pl
									
									
									
									
									
								
							| @@ -5,51 +5,32 @@ 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). | ||||
|     routes(Starts, [Route1 | RestOfRoutes]), | ||||
|     foldl(unify2, RestOfRoutes, Route1, Answer). | ||||
|  | ||||
| % 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) :- | ||||
| unify2(Route1, Route2, 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), | ||||
|     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). | ||||
|     natnum(X2), | ||||
|     pick([Dests1, Dests2], [Dest1-Z1, Dest2-Z2]), | ||||
|     0 is (Stride2*X2 + Offset2 + Dest2 - Offset1 - Dest1) mod Stride1, | ||||
|     Len is Stride2*X2 + Offset2 + Dest2, | ||||
|     atom_concat(A1, A2, NewA), atom_concat(Z1, Z2, NewZ). | ||||
|  | ||||
| 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 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]), | ||||
| @@ -81,3 +62,10 @@ 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). | ||||
|  | ||||
| % 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. | ||||
|   | ||||
| @@ -8,4 +8,12 @@ nna to nnb-xxx. | ||||
| nnb to nnc-nnc. | ||||
| nnc to nnz-nnz. | ||||
| 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. | ||||
|  | ||||
| % 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]). | ||||
|   | ||||
		Reference in New Issue
	
	Block a user