Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combinatorics updates #4025

Merged
merged 1 commit into from
Aug 12, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"]