Is there any way to instruct Complement to skip the sorting part? If the answer is no (likely), the next question would be: how can I remove from a sorted list another sorted list (in an efficient way)?
I would like the output of the following code to be {1,3} as in the usual Complement function:
universe = {1, 2, 3};
subst = {2} ;
myComplement[universe, subst]
But the output of the following code should be {3, 2, 1} because it stopped trying to remove terms after it realized thatsubst[[1]] > universe[[1]].
universe = {3, 2, 1};
subst = {2};
myComplement[universe, subst]
This question is different from a simple use of Complement or DeleteCases because we must use the fact that the lists are (assumed) sorted for efficiency. In the example below, the list universe has $2^{25}-1$ elements.
The motivation for this question.
While answering this post, I tried to go from listing the classes of equivalence of 4x4 matrices (as requested by the original question) to 5x5 case (just to push it). My answer solved the 4x4 case in 4 seconds. But the same algorithm, I estimated, will take 3 hours for the 5x5 case.
toMatrix = Partition[IntegerDigits[#, 2, 25], 5] &;
toInteger = FromDigits[Flatten[#], 2] &;
allSyms =
Module[{s1, s3, s4, s6}, {#, s1 = Reverse[#, {2}], Reverse[#],
s3 = Transpose[#], s4 = Reverse[s3, {2}],
Reverse[Transpose[s1], {2}], s6 = Reverse[Transpose[s4], {2}],
Reverse[Transpose[s6], {2}]}] &;
casesToCheck = Range[0, 2^25 - 1];
Timing[answer = {MatrixForm@toMatrix@First[#],
Length[#]} & /@ (Reap[
NestWhile[
Complement[#,
Sow[Union[toInteger /@ allSyms[toMatrix[#[[1]]]]]]] &,
casesToCheck, (n = Length[#]) > 0 &]][[2, 1]]); Length[answer]]
Obviously, there is a major bottleneck that is triggered now. I guess it is because Complement sorts the input. Instead of sorting a list of 65536 integers, the 5x5 case deals with a list of 33554432 integers.
DeleteCases[universe, Alternatives @@ subst]should do what you want (no clue about performance). – Yves Klett Aug 14 '13 at 08:22DeleteCases[{3, 5, 7, 1, 4, 5}, 3 | 2 | 7]does. On the other hand there is a faster method for a true complement which I have posted in an answer. – Mr.Wizard Aug 14 '13 at 08:32DeleteDuplicates. – Yves Klett Aug 14 '13 at 08:48orderedComplementis much faster thanoc2[all_List, i__List] := DeleteCases[DeleteDuplicates @ all, Alternatives @@ Union[i]]-- can you confirm in a later version? – Mr.Wizard Aug 14 '13 at 08:56{3,2,1}and{2}be{3,1}or{3,2,1}(which does not really make sense) and edit the question accordingly? – Yves Klett Aug 15 '13 at 07:22Sortto an already sorted list is quite fast (your 2^25 example takes under 1.5 second here) I doubt you're going to be able to beatComplementby much. If both lists are sorted and internally free of duplicates this code may be a little faster thanComplement:DeleteDuplicates[Join@##] ~Drop~ Length[#] &[subst, universe]. Do you have reason to believe a faster method is even possible? – Mr.Wizard Aug 15 '13 at 13:27Complement. – Hector Aug 15 '13 at 13:36Complement. I'm afraid you're seeking the impossible here, but I'm always happy to be proven wrong if I can learn from it. – Mr.Wizard Aug 15 '13 at 13:38Complementconstructs a new list each time it is invoked. This makes your algorithm's running time quadratic in the size ofcasesToCheck, even ifComplementruns in constant time. Since your goal is to pull out equivalence classes, it would be better to traversecasesToCheckonce, sowing each element which is the first element in its (presorted) equivalence class. This is a linear- – Tobias Hagge Aug 15 '13 at 14:59