I'm trying to build a lazy list that evaluates the n'th m-tuple or subset of a given list using Mathematicas ordering without calculating all the Tuples. The purpose is to allow for example the traversal of very large spaces of tuples without fist having to calculate the complete space of tuples. So far I have defined a function that calcluates which elements goes where for the n'th tuple:
tupleIndexes[l_, t_, n_] := Table[Mod[Quotient[n - 1, l^m] + 1, l, 1], {m, t - 1, 0, -1}]
And have used this to define a lazy list by defining a SubValue
for when Part is applied.
lazyTuple /:Part[lazyTuple[list_, t_], n_Integer] /; 0 < n <= Length[lazyTuple[list, t]]:=
list[[tupleIndexes[Length[list], t, n]]]
The result is that lazyTuple[{1,2,3,4},2]
remains unevaluted but lazyTuple[{1,2,3,4},2][[2]]
returns {1,2}
as expected.
For testing I've defined a function to iterate through the list and return them all:
lazyTuple /: Length[lazyTuple[list_, t_]] := Length[list]^t
lazyTuple /: lazyTakeAll[a_lazyTuple] /; (NumericQ@Length@a) := Table[a[[i]], {i, Length@a}]
And it seems to check out:
lazyTakeAll[lazyTuple[Range@6, 3]] == Tuples[Range@6, 3]
True
Now my question is firstly if I'm making any subtle mistakes means this isn't returning the correct order with respect to Tuples
. But more importantly, how would one go about defining a similar function for lazySubsets[]
RankSubset[]
andUnrankSubset[]
inCombinatorica`
? $\endgroup$Subsets
, which return entire collection at once, may be too strong a requirement). $\endgroup$lazySublists
andSublists
, however you could iterate though this in any order you wish. An added benefit of having a function that returns the iteration indices for the n'th subset is that you can for instance carry out a maximization that finds that the 42231'th subset was best, and you automatically know which set it is, without having to put in hooks to retrieve the actual subset alongside the maximization. $\endgroup$