我有一个随机数,我想把它分成几个部分(加数),条件是一个部分不能超过20个,部分必须尽可能彼此接近。
例如,如果我的随机数为41,则加数应为14,14,13。 如果随机数为60,则加数应为20,20,20。 如果随机数为21,则加数应为11和10 等等。
我的代码是在Ruby(Rails)中,所以我非常感谢一个能够在Ruby中实现这一功能的答案,尽管也欢迎使用伪代码或其他编程语言。
这是我在数组中找到的,但我真的需要用数字做这件事:“Splitting an array into equal parts in ruby”
答案 0 :(得分:12)
你可以使用这款酷炫的单线眼镜。它应该可以除以你想要的任何数量:
def split_into n, p
[n/p + 1] * (n%p) + [n/p] * (p - n%p)
end
print (split_into 32, 3) # => [11, 11, 10]
它基本上将数字分成相等的部分,并将余数除以前面的数字(每个为1)。那个以及你可以将数组相乘并添加在一起的事实,如下所示:
[1] * 3 # => [1, 1, 1]
[1] + [2] # => [1, 2]
编辑:考虑到每件作品应小于20的规则,您可以按照@Cary Swoveland的建议计算理想的件数:
p = (n / 20.0).ceil
答案 1 :(得分:4)
<强>代码强>
让n
为要分割的给定数字,并m
每个组件的最大值。
def doit(n,m)
nbr_components = (n/(m.to_f)).ceil
smaller, nbr_larger = n.divmod(nbr_components)
{ smaller=>nbr_components-nbr_larger, smaller+1=>nbr_larger }.
delete_if { |_,v| v.zero? }
end
Fixnum#divmod是一种经常被忽视的方法,有很多用途。
<强>实施例强>
(1..300).to_a.sample(15).sort.each { |n| puts "doit(#{n},20) = #{doit(n,20)}" }
doit(2,20) = {2=>1}
doit(7,20) = {7=>1}
doit(13,20) = {13=>1}
doit(19,20) = {19=>1}
doit(32,20) = {16=>2}
doit(36,20) = {18=>2}
doit(47,20) = {15=>1, 16=>2}
doit(61,20) = {15=>3, 16=>1}
doit(77,20) = {19=>3, 20=>1}
doit(146,20) = {18=>6, 19=>2}
doit(149,20) = {18=>3, 19=>5}
doit(160,20) = {20=>8}
doit(199,20) = {19=>1, 20=>9}
doit(253,20) = {19=>7, 20=>6}
doit(275,20) = {19=>5, 20=>9}
doit(11_347_155, 20)
#=> {19=>5, 20=>567353}
5*19 + 567353*20
#=> 11347155
<强>解释强>
假设:
n = 77
m = 20
步骤如下:
nbr_components = (n/(m.to_f)).ceil
#=> (77/20.0).ceil
#=> 3.85.ceil
#=> 4
smaller, nbr_larger = n.divmod(nbr_components)
#=> 77.divmod(4)
#=> [19, 1]
smaller
#=> 19
nbr_larger
#=> 1
h = { smaller=>nbr_components-nbr_larger, smaller+1=>nbr_larger }
#=> {19=>3, 20=>1}
h.delete_if { |_,v| v.zero? }
#=> {19=>3, 20=>1}
答案 2 :(得分:3)
没有内置功能来执行此操作。
我可以为您写出解决方案,但一般来说,您应该在StackOverflow问题中包含您自己的尝试。这种类型的问题似乎是练习学习ruby语言的基础知识。如果你不确定从哪里开始,我建议你阅读一本Ruby教科书。
def split_number_into_three(number) # i.e. number=32
base = Array.new(3, (number / 3)) # i.e. base=[10,10,10]
remainder = number % 3 # i.e. remainer=2
return base if remainder.zero?
while remainder > 0
base.each_with_index do |num, idx|
if remainder > 0
base[idx] += 1
remainder -= 1
end
end
end
base
end
运行此代码:
irb(main):035:0> split_number_into_three(32)
=> [11, 11, 10]