Skip to content

Commit 9a533d3

Browse files
committed
Give access to non-allocating combinations iterator
1 parent 0e0edc6 commit 9a533d3

File tree

3 files changed

+22
-25
lines changed

3 files changed

+22
-25
lines changed

src/combinations.jl

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,33 @@ export combinations,
55
powerset
66

77
#The Combinations iterator
8-
9-
struct Combinations{T}
10-
a::T
8+
struct Combinations
9+
n::Int
1110
t::Int
1211
end
1312

14-
function Base.iterate(c::Combinations, s = collect(1:c.t))
15-
(!isempty(s) && s[1] > length(c.a) - c.t + 1) && return
16-
17-
comb = [c.a[si] for si in s]
18-
if c.t == 0
19-
# special case to generate 1 result for t==0
20-
return (comb, [length(c.a)+2])
13+
function Base.iterate(c::Combinations, s = [min(c.t - 1, i) for i in 1:c.t])
14+
if c.t == 0 # special case to generate 1 result for t==0
15+
isempty(s) && return (s, [1])
16+
return
2117
end
22-
s = copy(s)
23-
for i = length(s):-1:1
18+
for i in c.t:-1:1
2419
s[i] += 1
25-
if s[i] > (length(c.a) - (length(s) - i))
20+
if s[i] > (c.n - (c.t - i))
2621
continue
2722
end
28-
for j = i+1:lastindex(s)
29-
s[j] = s[j-1]+1
23+
for j in i+1:c.t
24+
s[j] = s[j-1] + 1
3025
end
3126
break
3227
end
33-
(comb, s)
28+
s[1] > c.n - c.t + 1 && return
29+
(s, s)
3430
end
3531

36-
Base.length(c::Combinations) = binomial(length(c.a), c.t)
32+
Base.length(c::Combinations) = binomial(c.n, c.t)
3733

38-
Base.eltype(::Type{Combinations{T}}) where {T} = Vector{eltype(T)}
34+
Base.eltype(::Type{Combinations}) = Vector{Int}
3935

4036
"""
4137
combinations(a, n)
@@ -49,7 +45,8 @@ function combinations(a, t::Integer)
4945
# generate 0 combinations for negative argument
5046
t = length(a) + 1
5147
end
52-
Combinations(a, t)
48+
reorder(c) = [a[ci] for ci in c]
49+
(reorder(c) for c in Combinations(length(a), t))
5350
end
5451

5552

src/multinomials.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
export multiexponents
55

66
struct MultiExponents{T}
7-
c::Combinations{T}
7+
c::T
88
nterms::Int
99
end
1010

test/combinations.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
@test [combinations([])...] == []
2-
@test [combinations(['a', 'b', 'c'])...] == Any[['a'],['b'],['c'],['a','b'],['a','c'],['b','c'],['a','b','c']]
2+
@test [combinations(['a', 'b', 'c'])...] == [['a'],['b'],['c'],['a','b'],['a','c'],['b','c'],['a','b','c']]
33

4-
@test [combinations("abc",3)...] == Any[['a','b','c']]
5-
@test [combinations("abc",2)...] == Any[['a','b'],['a','c'],['b','c']]
6-
@test [combinations("abc",1)...] == Any[['a'],['b'],['c']]
7-
@test [combinations("abc",0)...] == Any[[]]
4+
@test [combinations("abc",3)...] == [['a','b','c']]
5+
@test [combinations("abc",2)...] == [['a','b'],['a','c'],['b','c']]
6+
@test [combinations("abc",1)...] == [['a'],['b'],['c']]
7+
@test [combinations("abc",0)...] == [[]]
88
@test [combinations("abc",-1)...] == []
99

1010
@test filter(x->iseven(x[1]),[combinations([1,2,3],2)...]) == Any[[2,3]]

0 commit comments

Comments
 (0)