I have a big list AllCycles
with contains lists of non-repeating integers (and the first element is always the smallest). I want a function findReversePairs
to find all pairs of Reverse
lists.
For example:
AllCycles={{1, 2, 3, 4}, {1, 10, 2, 5}, {1, 4, 3, 2}, {1, 5, 2, 10}}
findReversePairs[AllCycles] (* {{{1, 2, 3, 4},1,3}, {{1, 10, 2, 5},2,4} *)
where the output is a list of all such pairs, with {list, index1, index2}
, where index1
and index2
is the index of the first and second item of the pair.
This can be simply done with two for-loops, but it is very slow therefore I am searching for a faster solution. My code is here:
(*Function for rearranging list such that smallest element is always the first element*)
StartListAtSmallest[llist_] := (
SLASpos = Position[llist, Min[llist]][[1, 1]];
SLASrl = Flatten[{llist[[SLASpos ;;]], llist[[1 ;; SLASpos]]}][[1 ;; -2]];
Return[SLASrl];
);
findReversePairs[list_] := (
CurrTime = AbsoluteTime[];
AllReverse = {};
For[index1 = 1, index1 <= Length[list] - 1, index1++,
RevCycle = StartListAtSmallest[Reverse[list[[index1]]]];
For[index2 = index1 + 1, index2 <= Length[list], index2++,
If[RevCycle == list[[index2]],
AppendTo[AllReverse, {list[[index1]], index1, index2}];
];
];
];
Return[AllReverse];
)
SeedRandom[42]
(*Make a list with 2500 entries*)
AllCycles = {};
For[ii = 1, ii <= 2500, ii++,
AppendTo[AllCycles, StartListAtSmallest[RandomSample[Range[13], 5]]];
];
ListReverse = findReversePairs[AllCycles];
Length[ListReverse] (*95 entries*)
Print[AbsoluteTime[] - CurrTime]; (*6.1841130 seconds*)
My code need roughly 6.2 seconds, and it scales quadratically with the number of list items, which is very unfortunate.
Do you know of a faster, more efficient solution?
GatherBy[AllCycles , Sort[Rest@#] &]
... then organize? $\endgroup$GatherBy
in a similar fashion as searching for Duplicates, but was not successful. Unfortunately, your solution gives a different result as my function:Length[GatherBy[AllCycles, Sort[Rest@#] &]] (* 477 *)
, instead it should be 95 entries. And I dont really understand what the idea of the suolution is -- could you please explain a few bits? Thank you!! $\endgroup$GatherBy[AllCycles , Sort[Rest@#] &]
allows the first entries ofc1
andc2
to be different and the other entries can be in any order as long as they have common elements. Perhaps a version withGather
would work. $\endgroup$GatherBy
but not successfully until now. Would really like to know how to exploit the syntax of these fancy functions to get that work. $\endgroup$ListReverse
on the timing experiment have length2
. However, for example, the three entries {{2, 13, 4, 5, 7}, {2, 7, 5, 4, 13}, {2, 7, 5, 4, 13}}` (these are the entries inAllCycles[[{56, 2139, 2140}]]
) satisfy your condition and the correct result should include{{2, 13, 4, 5, 7}, 56, 2139, 2140}
, don't you think? $\endgroup$