-
Notifications
You must be signed in to change notification settings - Fork 177
Expand file tree
/
Copy pathcombinations.jl
More file actions
115 lines (93 loc) · 2.54 KB
/
combinations.jl
File metadata and controls
115 lines (93 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
@doc raw"""
combinations(n::Int, k::Int)
Return an iterator over all $k$-combinations of ${1,...,n}$, produced in
lexicographically ascending order.
# Examples
```jldoctest
julia> C = combinations(4, 3)
Iterator over the 3-combinations of 1:4
julia> collect(C)
4-element Vector{Combination{Int64}}:
[1, 2, 3]
[1, 2, 4]
[1, 3, 4]
[2, 3, 4]
```
"""
combinations(n::Int, k::Int) = Combinations(1:n, k)
@doc raw"""
combinations(v::AbstractVector, k::Int)
Return an iterator over all `k`-combinations of a given vector `v` produced in
lexicographically ascending order of the indices.
# Examples
```jldoctest
julia> C = combinations(['a', 'b', 'c', 'd'], 3)
Iterator over the 3-combinations of ['a', 'b', 'c', 'd']
julia> collect(C)
4-element Vector{Combination{Char}}:
['a', 'b', 'c']
['a', 'b', 'd']
['a', 'c', 'd']
['b', 'c', 'd']
```
"""
function combinations(v::AbstractVector{T}, k::Int) where T
return Combinations(v, k)
end
Combinations(v::AbstractArray{T}, k::Int) where T = Combinations(v, length(v), k)
@inline function Base.iterate(C::Combinations, state = [min(C.k - 1, i) for i in 1:C.k])
if C.k == 0 # special case to generate 1 result for k = 0
if isempty(state)
return Combination(eltype(C.v)[]), [0]
end
return nothing
end
for i in C.k:-1:1
state[i] += 1
if state[i] > (C.n - (C.k - i))
continue
end
for j in i+1:C.k
state[j] = state[j - 1] + 1
end
break
end
if state[1] > C.n - C.k + 1
return nothing
end
return Combination(C.v[state]), state
end
Base.length(C::Combinations) = binomial(C.n, C.k)
Base.eltype(::Type{Combinations{T}}) where {T} = Combination{eltype(T)}
function Base.show(io::IO, C::Combinations)
print(io, "Iterator over the ", C.k, "-combinations of ", C.v)
end
################################################################################
#
# Array-like functionality
#
################################################################################
function Base.show(io::IO, ::MIME"text/plain", P::Combination)
p = data(P)
if isempty(p)
print(io, "Empty combination")
return
end
print(io, p)
end
data(P::Combination) = P.v
function Base.size(P::Combination)
return size(data(P))
end
function Base.length(P::Combination)
return length(data(P))
end
function Base.getindex(P::Combination, i::IntegerUnion)
return getindex(data(P), Int(i))
end
function Base.setindex!(P::Combination, x::IntegerUnion, i::IntegerUnion)
return setindex!(data(P), x, i)
end
function Base.copy(P::Combination)
return Combination(copy(data(P)))
end