Combinatorics.jl icon indicating copy to clipboard operation
Combinatorics.jl copied to clipboard

partitions(0) does not return empty set

Open jessebett opened this issue 5 years ago • 3 comments

Currently

julia> partitions(0)|>collect
1-element Array{Any,1}:
 #undef

This is unexpected because the partition of the empty set is the empty set so I would expect

patitions(0)|>collect == [[]]

This results in unexpected behviour here:

julia> [length(b) for b in partitions(1)]
1-element Array{Int64,1}:
 1

julia> [length(b) for b in partitions(0)]
1-element Array{Int64,1}:
 4492284592

# I expect this
julia> [length(b) for b in [[]]]
1-element Array{Int64,1}:
 0

jessebett avatar Jul 11 '19 18:07 jessebett

I don’t know enough about defining Iterators to solve this 😞

I believe that the bug is

function Base.iterate(p::IntegerPartitions, xs = Int[])
    length(xs) == p.n && return
    xs = nextpartition(p.n,xs)
    (xs, xs)
end

since length(xs)==0 this returns nothing. I don't know how to have iterate here return [[]] only once.

jessebett avatar Jul 11 '19 19:07 jessebett

This does the trick, needs some test etc.

function Base.iterate(p::IntegerPartitions, xs = Int[])
    length(xs) >= p.n + (p.n == 0) && return nothing
    xs = nextpartition(p.n,xs)
    (xs, xs)
end

Ah, no, this returns [0] which is not wrong but not "normalized"

mschauer avatar Jul 11 '19 19:07 mschauer

Then maybe add this as a second function:

function Base.iterate(p::IntegerPartitions)
   p.n == 0 && return (Int[], Int[])
  return iterate(p, Int[])
end

and change the signature of the other function from function Base.iterate(p::IntegerPartitions, xs = Int[]) to function Base.iterate(p::IntegerPartitions, xs).

simonschoelly avatar Jul 12 '19 09:07 simonschoelly