Skip to content

Commit 8561614

Browse files
committed
Adds producers for combinations and noncrossing partitions
1 parent 2b68e5b commit 8561614

File tree

2 files changed

+101
-24
lines changed

2 files changed

+101
-24
lines changed

src/Catalan.jl

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ module Catalan
22

33
using Polynomial
44

5-
import Base: integer_partitions
6-
75
export bell,
86
catalan,
97
derangement,
@@ -20,6 +18,7 @@ export bell,
2018
stirlings1,
2119
subfactorial
2220

21+
include("partitions.jl")
2322
include("youngdiagrams.jl")
2423

2524
# Returns the n-th Bell number
@@ -152,26 +151,4 @@ function stirlings1(n::Integer, k::Integer)
152151
p[n - k + 1]
153152
end
154153

155-
# Lists the partitions of the number n, the order is consistent with GAP
156-
function integer_partitions(n::Integer)
157-
if n < 0
158-
throw(DomainError())
159-
elseif n == 0
160-
return Vector{Int}[]
161-
elseif n == 1
162-
return Vector{Int}[[1]]
163-
end
164-
165-
list = Vector{Int}[]
166-
167-
for p in integer_partitions(n-1)
168-
push!(list, [p, 1])
169-
if length(p) == 1 || p[end] < p[end-1]
170-
push!(list, [p[1:end-1], p[end]+1])
171-
end
172-
end
173-
174-
list
175-
end
176-
177154
end # module

src/partitions.jl

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#Generative algorithms
2+
3+
import Base: integer_partitions
4+
5+
export cool_lex, ncpartitions
6+
7+
# Lists the partitions of the number n, the order is consistent with GAP
8+
function integer_partitions(n::Integer)
9+
if n < 0
10+
throw(DomainError())
11+
elseif n == 0
12+
return Vector{Int}[]
13+
elseif n == 1
14+
return Vector{Int}[[1]]
15+
end
16+
17+
list = Vector{Int}[]
18+
19+
for p in integer_partitions(n-1)
20+
push!(list, [p, 1])
21+
if length(p) == 1 || p[end] < p[end-1]
22+
push!(list, [p[1:end-1], p[end]+1])
23+
end
24+
end
25+
26+
list
27+
end
28+
29+
# Produces (n,k)-combinations in cool-lex order
30+
#
31+
#Implements the cool-lex algorithm to generate (n,k)-combinations
32+
#@article{Ruskey:2009fk,
33+
# Author = {Frank Ruskey and Aaron Williams},
34+
# Doi = {10.1016/j.disc.2007.11.048},
35+
# Journal = {Discrete Mathematics},
36+
# Month = {September},
37+
# Number = {17},
38+
# Pages = {5305-5320},
39+
# Title = {The coolest way to generate combinations},
40+
# Url = {http://www.sciencedirect.com/science/article/pii/S0012365X07009570},
41+
# Volume = {309},
42+
# Year = {2009}}
43+
function cool_lex(n::Integer, t::Integer)
44+
s = n-t
45+
if n > 64 error("Not implemented for n > 64") end
46+
if t < 1 error("Need t>1") end
47+
R0::Int64=R1::Int64=0
48+
R2::Int64 = 1 << (s+t)
49+
R3::Int64 = (1 << t) - 1
50+
while R3 & R2 == 0
51+
produce(visit(R3))
52+
R0 = R3 & (R3 + 1)
53+
R1 = R0 $ (R0 - 1)
54+
R0 = R1 + 1
55+
R1 &= R3
56+
R0 = max((R0 & R3) - 1, 0)
57+
R3 += R1 - R0
58+
end
59+
end
60+
61+
#Converts an integer word X into a subset
62+
#If X & 2^k == 1, then k is in the subset
63+
function visit(X::Integer)
64+
subset = Int[]
65+
n::Int=1
66+
while X != 0
67+
if X & 1 == 1 push!(subset, n) end
68+
X >>= 1
69+
n += 1
70+
end
71+
subset
72+
end
73+
74+
#Produces noncrossing partitions of length n
75+
ncpartitions(n::Integer)=ncpart(1,n,n,{})
76+
function ncpart(a::Integer, b::Integer, nn::Integer,
77+
x::Array{Any,1})
78+
n=b-a+1
79+
for k=1:n
80+
for root in @task cool_lex(n, k)
81+
root += a-1
82+
#Abort if construction is out of lex order
83+
if length(x)>0 && x[end] > root return end
84+
#Produce if we've filled all the holes
85+
sofar = {x..., root}
86+
ssofaru = sort(union(sofar...))
87+
if length(ssofaru)==nn && ssofaru==[1:nn]
88+
produce(sofar)
89+
return
90+
end
91+
#otherwise patch all remaining holes
92+
blob = [ssofaru; nn+1]
93+
for l=1:length(blob)-1
94+
ap, bp = blob[l]+1, blob[l+1]-1
95+
if ap <= bp ncpart(ap, bp, nn, sofar) end
96+
end
97+
end
98+
end
99+
end
100+

0 commit comments

Comments
 (0)