Skip to content

Commit 1403f71

Browse files
authored
Updates for Julia 0.6 and 0.7 (#62)
Also includes general stylistic cleanup and an overhaul of the Young diagram functionality to avoid type piracy. Fixes #61.
1 parent aaaf5f4 commit 1403f71

19 files changed

+534
-373
lines changed

.travis.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ language: julia
22
os:
33
- linux
44
julia:
5-
- 0.5
65
- 0.6
76
- nightly
87
sudo: false
98
notifications:
109
email: false
11-
script:
12-
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
13-
- julia -e 'Pkg.clone(pwd())'
14-
- julia -e 'Pkg.test("Combinatorics", coverage=true)'
10+
#script:
11+
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
12+
# - julia -e 'Pkg.clone(pwd())'
13+
# - julia -e 'Pkg.test("Combinatorics", coverage=true)'
1514
after_success:
1615
- julia -e 'Pkg.add("Coverage"); cd(Pkg.dir("Combinatorics")); using Coverage; Coveralls.submit(Coveralls.process_folder()); Codecov.submit(process_folder())'

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Combinatorics
22

3-
[![Combinatorics](http://pkg.julialang.org/badges/Combinatorics_0.5.svg)](http://pkg.julialang.org/?pkg=Combinatorics)
43
[![Combinatorics](http://pkg.julialang.org/badges/Combinatorics_0.6.svg)](http://pkg.julialang.org/?pkg=Combinatorics)
4+
[![Combinatorics](http://pkg.julialang.org/badges/Combinatorics_0.7.svg)](http://pkg.julialang.org/?pkg=Combinatorics)
55
[![Build Status](https://travis-ci.org/JuliaMath/Combinatorics.jl.svg?branch=master)](https://travis-ci.org/JuliaMath/Combinatorics.jl)
66
[![Coverage Status](https://coveralls.io/repos/github/JuliaMath/Combinatorics.jl/badge.svg?branch=master)](https://coveralls.io/github/JuliaMath/Combinatorics.jl?branch=master)
77
[![Codecov](https://codecov.io/gh/JuliaMath/Combinatorics.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaMath/Combinatorics.jl)

REQUIRE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
julia 0.5
2-
Compat 0.18.0
1+
julia 0.6
2+
Compat 0.59.0
33
Polynomials
44
IterTools

src/Combinatorics.jl

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,9 @@ __precompile__(true)
22

33
module Combinatorics
44

5-
using Compat, Polynomials, IterTools
6-
7-
import Base: start, next, done, length, eltype
8-
9-
#These 8 functions were removed from Julia 0.5 as part of JuliaLang/julia#13897,
10-
#so check if it's necessary to import them to overload the stub methods left in
11-
#Base. Only do this if on a version of Julia post-combinatorics removal.
12-
if isdefined(Base, :combinations) && VERSION >= v"0.5.0-dev+1204"
13-
import Base: combinations, partitions, prevprod, levicivita, nthperm,
14-
nthperm!, parity, permutations
15-
end
5+
using Compat
6+
using Polynomials
7+
using IterTools
168

179
include("numbers.jl")
1810
include("factorials.jl")

src/combinations.jl

Lines changed: 82 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -5,92 +5,93 @@ export combinations,
55

66
#The Combinations iterator
77

8-
immutable Combinations{T}
8+
struct Combinations{T}
99
a::T
1010
t::Int
1111
end
1212

13-
start(c::Combinations) = [1:c.t;]
14-
function next(c::Combinations, s)
13+
Base.start(c::Combinations) = collect(1:c.t)
14+
function Base.next(c::Combinations, s)
1515
comb = [c.a[si] for si in s]
1616
if c.t == 0
1717
# special case to generate 1 result for t==0
18-
return (comb,[length(c.a)+2])
18+
return (comb, [length(c.a)+2])
1919
end
2020
s = copy(s)
2121
for i = length(s):-1:1
2222
s[i] += 1
23-
if s[i] > (length(c.a) - (length(s)-i))
23+
if s[i] > (length(c.a) - (length(s) - i))
2424
continue
2525
end
26-
for j = i+1:endof(s)
26+
for j = i+1:lastindex(s)
2727
s[j] = s[j-1]+1
2828
end
2929
break
3030
end
31-
(comb,s)
31+
(comb, s)
3232
end
33-
done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a)-c.t+1
33+
Base.done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a) - c.t + 1
34+
35+
Base.length(c::Combinations) = binomial(length(c.a), c.t)
3436

35-
length(c::Combinations) = binomial(length(c.a),c.t)
37+
Base.eltype(::Type{Combinations{T}}) where {T} = Vector{eltype(T)}
3638

37-
eltype{T}(::Type{Combinations{T}}) = Vector{eltype(T)}
39+
"""
40+
combinations(a, n)
3841
39-
"Generate all combinations of `n` elements from an indexable object. Because the number of combinations can be very large, this function returns an iterator object. Use `collect(combinations(array,n))` to get an array of all combinations.
40-
"
42+
Generate all combinations of `n` elements from an indexable object `a`. Because the number
43+
of combinations can be very large, this function returns an iterator object.
44+
Use `collect(combinations(a, n))` to get an array of all combinations.
45+
"""
4146
function combinations(a, t::Integer)
4247
if t < 0
4348
# generate 0 combinations for negative argument
44-
t = length(a)+1
49+
t = length(a) + 1
4550
end
4651
Combinations(a, t)
4752
end
4853

4954

5055
"""
51-
generate combinations of all orders, chaining of order iterators is eager,
52-
but sequence at each order is lazy
56+
combinations(a)
57+
58+
Generate combinations of the elements of `a` of all orders. Chaining of order iterators
59+
is eager, but the sequence at each order is lazy.
5360
"""
54-
combinations(a) = chain([combinations(a,k) for k=1:length(a)]...)
61+
combinations(a) = IterTools.chain([combinations(a, k) for k = 1:length(a)]...)
5562

5663

5764

5865
# cool-lex combinations iterator
5966

6067
"""
61-
Produces (n,k)-combinations in cool-lex order
62-
63-
Implements the cool-lex algorithm to generate (n,k)-combinations
64-
@article{Ruskey:2009fk,
65-
Author = {Frank Ruskey and Aaron Williams},
66-
Doi = {10.1016/j.disc.2007.11.048},
67-
Journal = {Discrete Mathematics},
68-
Month = {September},
69-
Number = {17},
70-
Pages = {5305-5320},
71-
Title = {The coolest way to generate combinations},
72-
Url = {http://www.sciencedirect.com/science/article/pii/S0012365X07009570},
73-
Volume = {309},
74-
Year = {2009}}
68+
CoolLexCombinations
69+
70+
Produce ``(n,k)``-combinations in cool-lex order.
71+
72+
# Reference
73+
74+
Ruskey, F., & Williams, A. (2009). The coolest way to generate combinations.
75+
*Discrete Mathematics*, 309(17), 5305-5320.
7576
"""
76-
immutable CoolLexCombinations
77-
n :: Int
78-
t :: Int
77+
struct CoolLexCombinations
78+
n::Int
79+
t::Int
7980
end
8081

81-
immutable CoolLexIterState{T<:Integer}
82-
R0:: T
83-
R1:: T
84-
R2:: T
85-
R3:: T
82+
struct CoolLexIterState{T<:Integer}
83+
R0::T
84+
R1::T
85+
R2::T
86+
R3::T
8687
end
8788

88-
function start(C::CoolLexCombinations)
89+
function Base.start(C::CoolLexCombinations)
8990
if C.n < 0
90-
throw(DomainError())
91+
throw(DomainError(C.n))
9192
end
9293
if C.t 0
93-
throw(DomainError())
94+
throw(DomainError(C.t))
9495
end
9596

9697
#What integer size should I use?
@@ -103,7 +104,7 @@ function start(C::CoolLexCombinations)
103104
CoolLexIterState{T}(0, 0, T(1) << C.n, (T(1) << C.t) - 1)
104105
end
105106

106-
function next(C::CoolLexCombinations, S::CoolLexIterState)
107+
function Base.next(C::CoolLexCombinations, S::CoolLexIterState)
107108
R0 = S.R0
108109
R1 = S.R1
109110
R2 = S.R2
@@ -122,36 +123,36 @@ end
122123
#Converts an integer bit pattern X into a subset
123124
#If X & 2^k == 1, then k is in the subset
124125
function _cool_lex_visit(X::Integer)
125-
subset = Int[]
126-
n=1
127-
while X != 0
128-
if X & 1 == 1 push!(subset, n) end
129-
X >>= 1
130-
n += 1
131-
end
132-
subset
126+
subset = Int[]
127+
n = 1
128+
while X != 0
129+
X & 1 == 1 && push!(subset, n)
130+
X >>= 1
131+
n += 1
132+
end
133+
subset
133134
end
134135

135-
done(C::CoolLexCombinations, S::CoolLexIterState) = (S.R3 & S.R2 != 0)
136+
Base.done(C::CoolLexCombinations, S::CoolLexIterState) = (S.R3 & S.R2 != 0)
136137

137-
length(C::CoolLexCombinations) = max(0, binomial(C.n, C.t))
138+
Base.length(C::CoolLexCombinations) = max(0, binomial(C.n, C.t))
138139

139140

140-
immutable MultiSetCombinations{T}
141+
struct MultiSetCombinations{T}
141142
m::T
142143
f::Vector{Int}
143144
t::Int
144145
ref::Vector{Int}
145146
end
146147

147-
eltype{T}(::Type{MultiSetCombinations{T}}) = Vector{eltype(T)}
148+
Base.eltype(::Type{MultiSetCombinations{T}}) where {T} = Vector{eltype(T)}
148149

149-
function length(c::MultiSetCombinations)
150+
function Base.length(c::MultiSetCombinations)
150151
t = c.t
151152
if t > length(c.ref)
152153
return 0
153154
end
154-
p = [1; zeros(Int,t)]
155+
p = [1; zeros(Int, t)]
155156
for i in 1:length(c.f)
156157
f = c.f[i]
157158
if i == 1
@@ -167,7 +168,7 @@ function length(c::MultiSetCombinations)
167168
return p[t+1]
168169
end
169170

170-
function multiset_combinations{T<:Integer}(m, f::Vector{T}, t::Integer)
171+
function multiset_combinations(m, f::Vector{<:Integer}, t::Integer)
171172
length(m) == length(f) || error("Lengths of m and f are not the same.")
172173
ref = length(f) > 0 ? vcat([[i for j in 1:f[i] ] for i in 1:length(f)]...) : Int[]
173174
if t < 0
@@ -176,15 +177,19 @@ function multiset_combinations{T<:Integer}(m, f::Vector{T}, t::Integer)
176177
MultiSetCombinations(m, f, t, ref)
177178
end
178179

179-
"generate all combinations of size t from an array a with possibly duplicated elements."
180-
function multiset_combinations{T}(a::T, t::Integer)
180+
"""
181+
multiset_combinations(a, t)
182+
183+
Generate all combinations of size `t` from an array `a` with possibly duplicated elements.
184+
"""
185+
function multiset_combinations(a, t::Integer)
181186
m = unique(collect(a))
182187
f = Int[sum([c == x for c in a]) for x in m]
183188
multiset_combinations(m, f, t)
184189
end
185190

186-
start(c::MultiSetCombinations) = c.ref
187-
function next(c::MultiSetCombinations, s)
191+
Base.start(c::MultiSetCombinations) = c.ref
192+
function Base.next(c::MultiSetCombinations, s)
188193
ref = c.ref
189194
n = length(ref)
190195
t = c.t
@@ -195,7 +200,9 @@ function next(c::MultiSetCombinations, s)
195200
for i in t:-1:1
196201
if s[i] < ref[i + (n - t)]
197202
j = 1
198-
while ref[j] <= s[i]; j += 1; end
203+
while ref[j] <= s[i]
204+
j += 1
205+
end
199206
s[i] = ref[j]
200207
for l in (i+1):t
201208
s[l] = ref[j+=1]
@@ -210,23 +217,27 @@ function next(c::MultiSetCombinations, s)
210217
end
211218
(comb, s)
212219
end
213-
done(c::MultiSetCombinations, s) =
214-
(!isempty(s) && max(s[1], c.t) > length(c.ref)) || (isempty(s) && c.t > 0)
220+
Base.done(c::MultiSetCombinations, s) =
221+
(!isempty(s) && max(s[1], c.t) > length(c.ref)) || (isempty(s) && c.t > 0)
215222

216-
immutable WithReplacementCombinations{T}
223+
struct WithReplacementCombinations{T}
217224
a::T
218225
t::Int
219226
end
220227

221-
eltype{T}(::Type{WithReplacementCombinations{T}}) = Vector{eltype(T)}
228+
Base.eltype(::Type{WithReplacementCombinations{T}}) where {T} = Vector{eltype(T)}
229+
230+
Base.length(c::WithReplacementCombinations) = binomial(length(c.a) + c.t - 1, c.t)
222231

223-
length(c::WithReplacementCombinations) = binomial(length(c.a)+c.t-1, c.t)
232+
"""
233+
with_replacement_combinations(a, t)
224234
225-
"generate all combinations with replacement of size t from an array a."
235+
Generate all combinations with replacement of size `t` from an array `a`.
236+
"""
226237
with_replacement_combinations(a, t::Integer) = WithReplacementCombinations(a, t)
227238

228-
start(c::WithReplacementCombinations) = [1 for i in 1:c.t]
229-
function next(c::WithReplacementCombinations, s)
239+
Base.start(c::WithReplacementCombinations) = [1 for i in 1:c.t]
240+
function Base.next(c::WithReplacementCombinations, s)
230241
n = length(c.a)
231242
t = c.t
232243
comb = [c.a[si] for si in s]
@@ -249,4 +260,4 @@ function next(c::WithReplacementCombinations, s)
249260
end
250261
(comb, s)
251262
end
252-
done(c::WithReplacementCombinations, s) = !isempty(s) && s[1] > length(c.a) || c.t < 0
263+
Base.done(c::WithReplacementCombinations, s) = !isempty(s) && s[1] > length(c.a) || c.t < 0

0 commit comments

Comments
 (0)