Skip to content

Commit

Permalink
Merge pull request #4025 from JuliaLang/kms/combinatorics
Browse files Browse the repository at this point in the history
Combinatorics updates
  • Loading branch information
kmsquire committed Aug 12, 2013
2 parents 66734e6 + aa3512c commit f86f5ea
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 28 deletions.
6 changes: 3 additions & 3 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1161,10 +1161,10 @@ rotr90(A::AbstractMatrix, k::Integer) = rotl90(A,-k)
rot180(A::AbstractMatrix, k::Integer) = mod(k, 2) == 1 ? rot180(A) : copy(A)

reverse(v::StridedVector) = (n=length(v); [ v[n-i+1] for i=1:n ])
function reverse!(v::AbstractVector)
n = length(v)
reverse(v::StridedVector, s=1, n=length(v)) = [[v[i] for i=1:s-1], [v[n-i] for i = 0:n-s], [v[i] for i = n+1:endof(v)]]
function reverse!(v::AbstractVector, s=1, n=length(v))
r = n
for i=1:div(n,2)
for i=s:div(s+n-1,2)
v[i], v[r] = v[r], v[i]
r -= 1
end
Expand Down
50 changes: 42 additions & 8 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ immutable Combinations{T}
end

eltype(c::Combinations) = typeof(c.a)
eltype{T}(c::Combinations{Range1{T}}) = Array{T,1}
eltype{T}(c::Combinations{Range{T}}) = Array{T,1}

function combinations(a, t::Integer)
if t < 0
Expand All @@ -197,25 +199,57 @@ end

start(c::Combinations) = [1:c.t]
function next(c::Combinations, s)
comb = c.a[s]
if c.t == 0
# special case to generate 1 result for t==0
return (c.a[s],[length(c.a)+2])
return (comb,[length(c.a)+2])
end
sn = copy(s)
for i = length(sn):-1:1
sn[i] += 1
if sn[i] > (length(c.a) - (length(sn)-i))
for i = length(s):-1:1
s[i] += 1
if s[i] > (length(c.a) - (length(s)-i))
continue
end
for j = i+1:endof(sn)
sn[j] = sn[j-1]+1
for j = i+1:endof(s)
s[j] = s[j-1]+1
end
break
end
(c.a[s],sn)
(comb,s)
end
done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a)-c.t+1

immutable Permutations{T}
a::T
end

eltype(c::Permutations) = typeof(c.a)
eltype{T}(c::Permutations{Range1{T}}) = Array{T,1}
eltype{T}(c::Permutations{Range{T}}) = Array{T,1}

permutations(a) = Permutations(a)

start(p::Permutations) = [1:length(p.a)]
function next(p::Permutations, s)
if length(p.a) == 0
# special case to generate 1 result for len==0
return (p.a,[1])
end
perm = p.a[s]
k = length(s)-1
while k > 0 && s[k] > s[k+1]; k -= 1; end
if k == 0
s[1] = length(s)+1 # done
else
l = length(s)
while s[k] >= s[l]; l -= 1; end
s[k],s[l] = s[l],s[k]
reverse!(s,k+1)
end
(perm,s)
end
done(p::Permutations, s) = !isempty(s) && s[1] > length(p.a)


# Algorithm H from TAoCP 7.2.1.4
# Partition n into m parts
function integer_partitions{T<:Integer}(n::T, m::T)
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ export
parentindexes,
partitions,
pascal,
permutations,
permute!,
permutedims,
prod,
Expand Down
25 changes: 17 additions & 8 deletions doc/helpdb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4569,24 +4569,33 @@ popdisplay(d::Display)
"),

("Combinatorics","Base","reverse","reverse(v)
("Combinatorics","Base","reverse","reverse(v[, start=1[, stop=length(v)]])
Reverse vector \"v\".
Reverse vector \"v\", optionally from start to stop.
"),

("Combinatorics","Base","reverse!","reverse!(v) -> v
("Combinatorics","Base","reverse!","reverse!(v[, start=1[, stop=length(v)]]) -> v
In-place version of \"reverse()\".
"),

("Combinatorics","Base","combinations","combinations(array, n)
("Combinatorics","Base","combinations","combinations(itr, n)
Generate all combinations of \"n\" elements from a given array.
Because the number of combinations can be very large, this function
returns an iterator object. Use \"collect(combinations(a,n))\" to
get an array of all combinations.
Generate all combinations of \"n\" elements from a given iterable
object. Because the number of combinations can be very large, this
function returns an iterator object. Use
\"collect(combinations(a,n))\" to get an array of all combinations.
"),

("Combinatorics","Base","permutations","permutations(itr)
Generate all permutations of a given iterable object. Because the
number of permutations can be very large, this function returns an
iterator object. Use \"collect(permutations(a,n))\" to get an array
of all permutations.
"),

Expand Down
23 changes: 15 additions & 8 deletions doc/stdlib/base.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3108,20 +3108,27 @@ Combinatorics

In-place version of :func:`shuffle`.

.. function:: reverse(v)
.. function:: reverse(v [, start=1 [, stop=length(v) ]] )

Reverse vector ``v``.
Reverse vector ``v``, optionally from start to stop.

.. function:: reverse!(v) -> v
.. function:: reverse!(v [, start=1 [, stop=length(v) ]]) -> v

In-place version of :func:`reverse`.

.. function:: combinations(array, n)
.. function:: combinations(itr, n)

Generate all combinations of ``n`` elements from a given array. Because
the number of combinations can be very large, this function returns an
iterator object. Use ``collect(combinations(a,n))`` to get an array of all
combinations.
Generate all combinations of ``n`` elements from a given iterable
object. Because the number of combinations can be very large, this
function returns an iterator object. Use
``collect(combinations(a,n))`` to get an array of all combinations.

.. function:: permutations(itr)

Generate all permutations of a given iterable object. Because the
number of permutations can be very large, this function returns an
iterator object. Use ``collect(permutations(a,n))`` to get an array
of all permutations.

.. function:: integer_partitions(n, m)

Expand Down
3 changes: 2 additions & 1 deletion test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ TESTS = all core keywordargs numbers strings unicode collections hashing \
remote iostring arrayops linalg blas fft dsp sparse bitarray random \
math functional bigint sorting statistics spawn parallel arpack file \
git pkg pkg2 resolve resolve2 suitesparse complex version pollfd mpfr \
broadcast socket floatapprox priorityqueue readdlm regex float16
broadcast socket floatapprox priorityqueue readdlm regex float16 \
combinations

$(TESTS) ::
@$(PRINT_JULIA) $(call spawn,$(JULIA_EXECUTABLE)) ./runtests.jl $@
Expand Down
11 changes: 11 additions & 0 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -662,3 +662,14 @@ end

@test_throws (10.^[-1])[1] == 0.1
@test (10.^[-1.])[1] == 0.1

# reverse
@test reverse([2,3,1]) == [1,3,2]
@test reverse([1:10],1,4) == [4,3,2,1,5,6,7,8,9,10]
@test reverse([1:10],3,6) == [1,2,6,5,4,3,7,8,9,10]
@test reverse([1:10],6,10) == [1,2,3,4,5,10,9,8,7,6]
@test reverse!([1:10],1,4) == [4,3,2,1,5,6,7,8,9,10]
@test reverse!([1:10],3,6) == [1,2,6,5,4,3,7,8,9,10]
@test reverse!([1:10],6,10) == [1,2,3,4,5,10,9,8,7,6]


9 changes: 9 additions & 0 deletions test/combinatorics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

@test factorial(7) = 5040
@test factorial(7,3) == 7*6*5*4
@test binomial(5,3) == 10
@test isperm(shuffle([1:1000]))
a = randcycle(10)
@test ipermute!(permute!([1:10], a),a) == [1:10]
@test collect(combinations("abc",2)) == ["ab","ac","bc"]
@test collect(collect(permutations("abc"))) == ["abc","acb","bac","bca","cab","cba"]

0 comments on commit f86f5ea

Please sign in to comment.