# How do you iterate over a vector of ranges of different lengths?

So I have an arbitrary vector of ranges

``````julia> kthNvals(k) = (1:(2^k))  .- 1;

julia> kthNvals.(1:4)
4-element Vector{UnitRange{Int64}}:
0:1
0:3
0:7
0:15
``````

I need to generate all the vectors where each index is a value in the relevant range.
The hardcoded version looks like this:

``````julia> l = [[a,b,c,d] for a in 0:1,b in 0:3,c in 0:7,d in 0:15][:]
1024-element Vector{Vector{Int64}}:
[0, 0, 0, 0]
[1, 0, 0, 0]
[0, 1, 0, 0]
[1, 1, 0, 0]
[0, 2, 0, 0]
[1, 2, 0, 0]
[0, 3, 0, 0]
⋮
[0, 1, 7, 15]
[1, 1, 7, 15]
[0, 2, 7, 15]
[1, 2, 7, 15]
[0, 3, 7, 15]
[1, 3, 7, 15]
``````

How do you make this for any `kthNvals.(1:k)`?

Would you do it with a recursive macro or some other metaprogramming feature?

If I understand correctly, this should answer the request

``````collect(Base.product(kthNvals.(1:4)...))[:]
``````
1 Like

The specific ranges given in the question, are easier to iterate over since they are powers of two, and essentially we can see each row as bit fields in a simple Int. This allows to randomly access this list and each entry in the list by direct caclulation. To make this observation concrete:

``````julia> [(i >> ((k*(k-1))>>1))&((1<<k)-1) for i in 0:20, k in 1:4]
21×4 Matrix{Int64}:
0  0  0  0
1  0  0  0
0  1  0  0
1  1  0  0
0  2  0  0
1  2  0  0
0  3  0  0
``````

or in Tuple form:

``````julia> [ntuple(k -> (i >> ((k*(k-1))>>1))&((1<<k)-1), Val(4)) for i in 0:20]
21-element Vector{NTuple{4, Int64}}:
(0, 0, 0, 0)
(1, 0, 0, 0)
(0, 1, 0, 0)
(1, 1, 0, 0)
(0, 2, 0, 0)
(1, 2, 0, 0)
(0, 3, 0, 0)
``````

or in iterator form:

``````julia> myiter = Iterators.map(i->ntuple(k -> (i >> ((k*(k-1))>>1))&((1<<k)-1), Val(4)), 0:(1<<(4*3÷2)))
Base.Generator{UnitRange{Int64}, var"#23#25"}(var"#23#25"(), 0:64)

julia> Iterators.take(myiter,7) |> collect
7-element Vector{NTuple{4, Int64}}:
(0, 0, 0, 0)
(1, 0, 0, 0)
(0, 1, 0, 0)
(1, 1, 0, 0)
(0, 2, 0, 0)
(1, 2, 0, 0)
(0, 3, 0, 0)
``````