Skip to content

Commit bbd5b1b

Browse files
authored
doc: add more examples and test for partitions (#181)
* doc: add doc and examples for `ncpartitions(n::Int)` * test: add more tests for `ncpartitions(n::Int)` * doc: update doc and examples for `integer_partitions(n)` * test: add more tests for `integer_partitions(n)` * doc: update doc and examples for `partitions(n::Integer)` * test: add more tests for `partitions(n::Integer)` * doc: update doc and examples for `partitions(n::Integer, m::Integer)` * test: add more tests for `partitions(n::Integer, m::Integer)` * doc: update doc and examples for `partitions(s::AbstractVector)` * test: add more tests for `partitions(s::AbstractVector)` * doc: update doc and examples for `partitions(s::AbstractVector, m::Int)` * test: add more tests for `partitions(s::AbstractVector, m::Int)` * doc: add link to `bellnum` * doc: add doc for `stirlings2` * doc: update doc and examples for `prevprod` * test: add more tests for `prevprod` * Update src/partitions.jl
1 parent ab33a23 commit bbd5b1b

File tree

3 files changed

+422
-88
lines changed

3 files changed

+422
-88
lines changed

src/numbers.jl

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ function stirlings1(n::Int, k::Int, signed::Bool=false)
151151
return (n - 1) * stirlings1(n - 1, k) + stirlings1(n - 1, k - 1)
152152
end
153153

154+
"""
155+
stirlings2(n::Int, k::Int)
156+
157+
Compute the Stirling number of the second kind, `S(n,k)`.
158+
"""
154159
function stirlings2(n::Int, k::Int)
155160
if n < 0
156161
throw(DomainError(n, "n must be nonnegative"))

src/partitions.jl

+258-34
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export
88
#nextprod,
99

1010

11-
#integer partitions
11+
# integer partitions
1212

1313
struct IntegerPartitions
1414
n::Int
@@ -24,17 +24,56 @@ function Base.iterate(p::IntegerPartitions, xs = Int[])
2424
end
2525

2626
"""
27-
partitions(n)
28-
29-
Generate all integer arrays that sum to `n`. Because the number of partitions can be very
30-
large, this function returns an iterator object. Use `collect(partitions(n))` to get an
31-
array of all partitions. The number of partitions to generate can be efficiently computed
32-
using `length(partitions(n))`.
27+
partitions(n::Integer)
28+
29+
Generate all integer arrays that sum to `n`.
30+
31+
Because the number of partitions can be very large,
32+
this function returns an iterator object.
33+
Use `collect(partitions(n))` to get an array of all partitions.
34+
35+
The number of partitions to generate can be efficiently computed using
36+
`length(partitions(n))`.
37+
38+
See also:
39+
- [`integer_partitions(n::Integer)`](@ref)
40+
for a non-iterator version that returns all partitions as a array
41+
- [`partitions(n::Integer, m::Integer)`](@ref)
42+
for partitions with exactly `m` parts.
43+
44+
## Examples
45+
```jldoctest
46+
julia> collect(partitions(2))
47+
2-element Vector{Vector{Int64}}:
48+
[2]
49+
[1, 1]
50+
51+
julia> collect(partitions(3))
52+
3-element Vector{Vector{Int64}}:
53+
[3]
54+
[2, 1]
55+
[1, 1, 1]
56+
57+
julia> integer_partitions(3)
58+
3-element Vector{Vector{Int64}}:
59+
[1, 1, 1]
60+
[2, 1]
61+
[3]
62+
63+
julia> first(partitions(10))
64+
1-element Vector{Int64}:
65+
10
66+
67+
julia> length(partitions(10))
68+
42
69+
```
70+
71+
# References
72+
- [Integer partition - Wikipedia](https://en.wikipedia.org/wiki/Integer_partition)
3373
"""
3474
partitions(n::Integer) = IntegerPartitions(n)
3575

3676

37-
3877
function nextpartition(n, as)
3978
isempty(as) && return Int[n]
4079

@@ -97,12 +136,47 @@ Base.length(f::FixedPartitions) = npartitions(f.n,f.m)
97136
Base.eltype(f::FixedPartitions) = Vector{Int}
98137

99138
"""
100-
partitions(n, m)
101-
102-
Generate all arrays of `m` integers that sum to `n`. Because the number of partitions can
103-
be very large, this function returns an iterator object. Use `collect(partitions(n, m))` to
104-
get an array of all partitions. The number of partitions to generate can be efficiently
105-
computed using `length(partitions(n, m))`.
139+
partitions(n::Integer, m::Integer)
140+
141+
Generate all integer partitions of `n` into exactly `m` parts, that sum to `n`.
142+
143+
Because the number of partitions can be very large,
144+
this function returns an iterator object.
145+
Use `collect(partitions(n, m))` to get an array of all partitions.
146+
147+
The number of partitions to generate can be efficiently computed using
148+
`length(partitions(n, m))`.
149+
150+
See also: [`partitions(n::Integer)`](@ref)
151+
152+
## Examples
153+
```jldoctest
154+
julia> collect(partitions(4))
155+
5-element Vector{Vector{Int64}}:
156+
[4]
157+
[3, 1]
158+
[2, 2]
159+
[2, 1, 1]
160+
[1, 1, 1, 1]
161+
162+
julia> collect(partitions(4, 2))
163+
2-element Vector{Vector{Int64}}:
164+
[3, 1]
165+
[2, 2]
166+
167+
julia> collect(partitions(4, 4))
168+
1-element Vector{Vector{Int64}}:
169+
[1, 1, 1, 1]
170+
171+
julia> collect(partitions(4, 5))
172+
Vector{Int64}[]
173+
174+
julia> partitions(4, 0)
175+
ERROR: DomainError with (4, 0):
176+
n and m must be positive
177+
Stacktrace:
178+
[...]
179+
```
106180
"""
107181
partitions(n::Integer, m::Integer) =
108182
n >= 1 && m >= 1 ?
@@ -176,11 +250,45 @@ Base.eltype(p::SetPartitions) = Vector{Vector{eltype(p.s)}}
176250
"""
177251
partitions(s::AbstractVector)
178252
179-
Generate all set partitions of the elements of an array `s`, represented as arrays of
180-
arrays. Because the number of partitions can be very large, this function returns an
181-
iterator object. Use `collect(partitions(s))` to get an array of all partitions. The
182-
number of partitions to generate can be efficiently computed using
183-
`length(partitions(s))`.
253+
Generate all set partitions of the elements of an array `s`,
254+
represented as arrays of arrays.
255+
256+
Because the number of partitions can be very large,
257+
this function returns an iterator object.
258+
Use `collect(partitions(s))` to get an array of all partitions.
259+
260+
The number of partitions of an `n`-element set
261+
is given by the n-th Bell number `Bn`:
262+
`length(partitions(s)) == bellnum(length(s))`.
263+
264+
See also: [`bellnum`](@ref)
265+
266+
# Examples
267+
```jldoctest
268+
julia> collect(partitions([1, 1]))
269+
2-element Vector{Vector{Vector{Int64}}}:
270+
[[1, 1]]
271+
[[1], [1]]
272+
273+
julia> collect(partitions(-1:-1:-2))
274+
2-element Vector{Vector{Vector{Int64}}}:
275+
[[-1, -2]]
276+
[[-1], [-2]]
277+
278+
julia> collect(partitions('a':'c'))
279+
5-element Vector{Vector{Vector{Char}}}:
280+
[['a', 'b', 'c']]
281+
[['a', 'b'], ['c']]
282+
[['a', 'c'], ['b']]
283+
[['a'], ['b', 'c']]
284+
[['a'], ['b'], ['c']]
285+
286+
julia> length(partitions(1:10)) == bellnum(10)
287+
true
288+
```
289+
290+
# References
291+
- [Partition of a set - Wikipedia](https://en.wikipedia.org/wiki/Partition_of_a_set)
184292
"""
185293
partitions(s::AbstractVector) = SetPartitions(s)
186294

@@ -257,11 +365,45 @@ Base.eltype(p::FixedSetPartitions) = Vector{Vector{eltype(p.s)}}
257365
partitions(s::AbstractVector, m::Int)
258366
259367
Generate all set partitions of the elements of an array `s` into exactly `m` subsets,
260-
represented as arrays of arrays. Because the number of partitions can be very large,
261-
this function returns an iterator object. Use `collect(partitions(s, m))` to get
262-
an array of all partitions. The number of partitions into `m` subsets is equal to the
263-
Stirling number of the second kind, and can be efficiently computed using
264-
`length(partitions(s, m))`.
368+
represented as arrays of arrays.
369+
370+
Because the number of partitions can be very large,
371+
this function returns an iterator object.
372+
Use `collect(partitions(s, m))` to get an array of all partitions.
373+
374+
The number of partitions into `m` subsets is equal to
375+
the Stirling number of the second kind,
376+
and can be efficiently computed using `length(partitions(s, m))`.
377+
378+
See also: [`stirlings2(n::Int, k::Int)`](@ref)
379+
380+
# Examples
381+
```jldoctest
382+
julia> collect(partitions('a':'c', 3))
383+
1-element Vector{Vector{Vector{Char}}}:
384+
[['a'], ['b'], ['c']]
385+
386+
julia> collect(partitions([1, 1, 1], 2))
387+
3-element Vector{Vector{Vector{Int64}}}:
388+
[[1, 1], [1]]
389+
[[1, 1], [1]]
390+
[[1], [1, 1]]
391+
392+
julia> collect(partitions(1:3, 2))
393+
3-element Vector{Vector{Vector{Int64}}}:
394+
[[1, 2], [3]]
395+
[[1, 3], [2]]
396+
[[1], [2, 3]]
397+
398+
julia> stirlings2(3, 2)
399+
3
400+
401+
julia> length(partitions(1:10, 3)) == stirlings2(10, 3)
402+
true
403+
```
404+
405+
# References
406+
- [Partition of a set - Wikipedia](https://en.wikipedia.org/wiki/Partition_of_a_set)
265407
"""
266408
partitions(s::AbstractVector, m::Int) =
267409
length(s) >= 1 && m >= 1 ?
@@ -394,15 +536,31 @@ end
394536
"""
395537
prevprod(a::Vector{Int}, x)
396538
397-
Previous integer not greater than `x` that can be written as ``\\prod k_i^{p_i}`` for
398-
integers ``p_1``, ``p_2``, etc.
539+
Find the largest integer not greater than `x`
540+
that can be expressed as a product of powers of the elements in `a`.
541+
542+
This function computes the largest value `y ≤ x` that can be written as:
543+
```math
544+
y = \\prod a_i^{n_i}
545+
= a_1^{n_1} a_2^{n_2} \\cdots a_k^{n_k}
546+
\\leq x
547+
```
548+
where ``n_i`` is a non-negative integer, `k` is the length of Vector `a`.
549+
550+
# Examples
551+
```jldoctest
552+
julia> prevprod([10], 1000) # 1000 = 10^3
553+
1000
399554
400-
For integers ``i_1``, ``i_2``, ``i_3``, this is equivalent to finding the largest ``x``
401-
such that
555+
julia> prevprod([2, 5], 30) # 25 = 2^0 * 5^2
556+
25
402557
403-
``i_1^{n_1} i_2^{n_2} i_3^{n_3} \\leq x``
558+
julia> prevprod([2, 3], 100) # 96 = 2^5 * 3^1
559+
96
404560
405-
for integers ``n_1``, ``n_2``, ``n_3``.
561+
julia> prevprod([2, 3, 5], 1) # 1 = 2^0 * 3^0 * 5^0
562+
1
563+
```
406564
"""
407565
function prevprod(a::Vector{Int}, x)
408566
if x > typemax(Int)
@@ -446,11 +604,43 @@ end
446604
"""
447605
integer_partitions(n)
448606
449-
List the partitions of the integer `n`.
607+
Generates all partitions of the integer `n` as a list of integer arrays,
608+
where each partition represents a way to write `n` as a sum of positive integers.
609+
610+
See also: [`partitions(n::Integer)`](@ref)
450611
451612
!!! note
452613
The order of the resulting array is consistent with that produced by the computational
453614
discrete algebra software GAP.
615+
616+
# Examples
617+
```jldoctest
618+
julia> integer_partitions(2)
619+
2-element Vector{Vector{Int64}}:
620+
[1, 1]
621+
[2]
622+
623+
julia> integer_partitions(3)
624+
3-element Vector{Vector{Int64}}:
625+
[1, 1, 1]
626+
[2, 1]
627+
[3]
628+
629+
julia> collect(partitions(3))
630+
3-element Vector{Vector{Int64}}:
631+
[3]
632+
[2, 1]
633+
[1, 1, 1]
634+
635+
julia> integer_partitions(-1)
636+
ERROR: DomainError with -1:
637+
n must be nonnegative
638+
Stacktrace:
639+
[...]
640+
```
641+
642+
# References
643+
- [Integer partition - Wikipedia](https://en.wikipedia.org/wiki/Integer_partition)
454644
"""
455645
function integer_partitions(n::Integer)
456646
if n < 0
@@ -474,12 +664,46 @@ function integer_partitions(n::Integer)
474664
end
475665

476666

477-
478-
#Noncrossing partitions
667+
# Noncrossing partitions
479668

480669
const _cmp = cmp
481670

482-
#Produces noncrossing partitions of length n
671+
"""
672+
ncpartitions(n::Int)
673+
674+
Generates all noncrossing partitions of a set of `n` elements,
675+
returning them as a `Vector` of partition representations.
676+
677+
The number of noncrossing partitions of an `n`-element set
678+
is given by the n-th Catalan number `Cn`:
679+
`length(ncpartitions(n)) == catalannum(n)`.
680+
681+
See also: [`catalannum`](@ref)
682+
683+
# Examples
684+
```jldoctest
685+
julia> ncpartitions(1)
686+
1-element Vector{Vector{Vector{Int64}}}:
687+
[[1]]
688+
689+
julia> ncpartitions(3)
690+
5-element Vector{Vector{Vector{Int64}}}:
691+
[[1], [2], [3]]
692+
[[1], [2, 3]]
693+
[[1, 2], [3]]
694+
[[1, 3], [2]]
695+
[[1, 2, 3]]
696+
697+
julia> catalannum(3)
698+
5
699+
700+
julia> length(ncpartitions(6)) == catalannum(6)
701+
true
702+
```
703+
704+
# References
705+
- [Noncrossing partition - Wikipedia](https://en.wikipedia.org/wiki/Noncrossing_partition)
706+
"""
483707
function ncpartitions(n::Int)
484708
partitions = Vector{Vector{Int}}[]
485709
_ncpart!(1,n,n,Vector{Int}[], partitions)

0 commit comments

Comments
 (0)