为什么
julia> collect(partitions(1,2))
0-element Array{Any,1}
返回而不是
2-element Array{Any,1}:
[0,1]
[1,0]
我真的必须
x = collect(partitions(n,m));
y = Array(Int64,length(x),length(x[1]));
for i in 1:length(x)
for j in 1:length(x[1])
y[i,j] = x[i][j];
end
end
将结果转换为二维数组?
答案 0 :(得分:2)
来自wikipedia:
在数论和组合学中,正整数n的分区,也称为整数分区,是一种将n写为正整数之和的方法。
对于阵列转换,请尝试:
julia> x = collect(partitions(5,3))
2-element Array{Any,1}:
[3,1,1]
[2,2,1]
或
julia> x = partitions(5,3)
Base.FixedPartitions(5,3)
然后
julia> hcat(x...)
3x2 Array{Int64,2}:
3 2
1 2
1 1
答案 1 :(得分:2)
使用Combinatorics.jl库,这是我认为更简单的问题的另一种方法:
multisets(n, k) = map(A -> [sum(A .== i) for i in 1:n],
with_replacement_combinations(1:n, k))
这会分配一堆内存,但我认为您当前的方法也是如此。也许制作一流的版本并将其添加到Combinatorics.jl会很有用。
示例:
julia> multisets(2, 1)
2-element Array{Array{Int64,1},1}:
[1,0]
[0,1]
julia> multisets(3, 5)
21-element Array{Array{Int64,1},1}:
[5,0,0]
[4,1,0]
[4,0,1]
[3,2,0]
[3,1,1]
[3,0,2]
[2,3,0]
[2,2,1]
[2,1,2]
[2,0,3]
⋮
[1,2,2]
[1,1,3]
[1,0,4]
[0,5,0]
[0,4,1]
[0,3,2]
[0,2,3]
[0,1,4]
[0,0,5]
参数顺序是从你的后退以匹配数学约定。如果您更喜欢其他方式,那么很容易改变。
答案 2 :(得分:2)
使用词典预表生成算法可以实现一个强大的解决方案,原来 By Donald Knuth 加上经典partitions(n)
。
这是词典预测生成器:
function lpremutations{T}(a::T)
b=Vector{T}()
sort!(a)
n=length(a)
while(true)
push!(b,copy(a))
j=n-1
while(a[j]>=a[j+1])
j-=1
j==0 && return(b)
end
l=n
while(a[j]>=a[l])
l-=1
end
tmp=a[l]
a[l]=a[j]
a[j]=tmp
k=j+1
l=n
while(k<l)
tmp=a[k]
a[k]=a[l]
a[l]=tmp
k+=1
l-=1
end
end
end
上述算法将生成所有可能的唯一 具有重复的数组元素的组合:
julia> lpremutations([2,2,0])
3-element Array{Array{Int64,1},1}:
[0,2,2]
[2,0,2]
[2,2,0]
然后我们将生成所有使用partitions(n)
求和为n的整数数组(忘记所需数组的长度 m ),并将它们调整为长度 m 使用resize_!
function resize_!(x,m)
[x;zeros(Int,m-length(x))]
end
主要功能如下:
function lpartitions(n,m)
result=[]
for i in partitions(n)
append!(result,lpremutations(resize_!(i, m)))
end
result
end
检查
julia> lpartitions(3,4)
20-element Array{Any,1}:
[0,0,0,3]
[0,0,3,0]
[0,3,0,0]
[3,0,0,0]
[0,0,1,2]
[0,0,2,1]
[0,1,0,2]
[0,1,2,0]
[0,2,0,1]
[0,2,1,0]
[1,0,0,2]
[1,0,2,0]
[1,2,0,0]
[2,0,0,1]
[2,0,1,0]
[2,1,0,0]
[0,1,1,1]
[1,0,1,1]
[1,1,0,1]
[1,1,1,0]
答案 3 :(得分:1)
来自http://www.mathworks.com/matlabcentral/fileexchange/28340-nsumk的MATLAB脚本实际上就像我需要的那样,并且我可以通过给出的描述来执行partition()。朱莉娅版本是
# k - sum, n - number of non-negative integers
function nsumk(k,n)
m = binomial(k+n-1,n-1);
d1 = zeros(Int16,m,1);
d2 = collect(combinations(collect((1:(k+n-1))),n-1));
d2 = convert(Array{Int16,2},hcat(d2...)');
d3 = ones(Int16,m,1)*(k+n);
dividers = [d1 d2 d3];
return diff(dividers,2)-1;
end
julia> nsumk(3,2)
4x2 Array{Int16,2}:
0 3
1 2
2 1
3 0
使用daycaster的可爱hcat(x ...)tidbit :) 我仍然希望有一种更紧凑的方式来做到这一点。
第一次提到这种方法似乎是https://au.mathworks.com/matlabcentral/newsreader/view_thread/52610,据我所知,它基于“星星和酒吧”方法https://en.wikipedia.org/wiki/Stars_and_bars_(combinatorics)