What I have so far is
julia> import Base: iterate, length
julia> using StaticArrays
julia> struct OrderedTuples{N, K} end
julia> function iterate(iter::OrderedTuples{N, K}) where {N, K}
state = MVector{K,Int}(ntuple(i -> i, K))
state.data, state
end
iterate (generic function with 214 methods)
julia> length(iter::OrderedTuples{N,K}) where {N,K} = binomial(N, K)
length (generic function with 87 methods)
julia> function iterate(iter::OrderedTuples{N, K}, state::MVector{K, Int}) where {N, K}
state[1] == N - K + 1 && return nothing
i = 0
while state[K - i] == N - i
i += 1
end
@inbounds state[K-i] += 1
@inbounds for j in 1:i state[K-i+j] = state[K-i]+j end
state.data, state
end
iterate (generic function with 215 methods)
julia> for (k, i) in enumerate(OrderedTuples{5, 3}())
@show k i
end
k = 1
i = (1, 2, 3)
k = 2
i = (1, 2, 4)
k = 3
i = (1, 2, 5)
k = 4
i = (1, 3, 4)
k = 5
i = (1, 3, 5)
k = 6
i = (1, 4, 5)
k = 7
i = (2, 3, 4)
k = 8
i = (2, 3, 5)
k = 9
i = (2, 4, 5)
k = 10
i = (3, 4, 5)
julia> function test(iter)
i = 0
for x in iter
i += x[2]
end
i
end
test (generic function with 1 method)
julia> using BenchmarkTools
julia> iter = OrderedTuples{14, 4}()
OrderedTuples{14,4}()
julia> @btime test($iter)
14.317 μs (1002 allocations: 46.97 KiB)
6006
But this doesn’t really feel efficient (I don’t like the many allocations for example).
How could I achieve the same more efficiently?
EDIT: Corrected length and test function, thanks @mauro3