如何“扭转和”#39;在Ruby?

时间:2015-05-15 15:53:47

标签: ruby math

我不知道如何用正确的数学术语来调用它。考虑一个采用两位数的方法:

 def num_of_sum(total, group_count)

 end

其中total是整数,group_count是整数。

我怎样才能得到一个很好的'分组group_count的整数数组 - 长度总计为total

我的规格如下:

describe "number to sum of" do
  it "grabs all numbers" do
    expect(num_of_sum(10, 2)).to eq([5,5])
    expect(num_of_sum(10, 3)).to eq([3,3,4])
    expect(num_of_sum(20, 3)).to eq([6,7,7])
    expect(num_of_sum(100, 3)).to eq([33,33,34])
    expect(num_of_sum(100, 2)).to eq([50,50])
  end
end

我试过这个,有效:

def num_of_sum(total, in_groups_of)
  result = []
  section_count ||= (total.to_f / in_groups_of.to_f).round

  while(total > 0)
    total -= section_count

    if (total - section_count) < 0 && (total + section_count).even?
      section_count += total
      total -= total
    end

    result << section_count
  end

  result
end

但是,例如,这个规范不起作用:

 expect(num_of_sum(67,5)).to eq([13,13,13,14,14]) 

我需要数组包含尽可能彼此接近的数字。但是数组仅限于group_count的长度。

有人知道这个数学名称是什么,所以我可以更准确地搜索一下吗?

5 个答案:

答案 0 :(得分:6)

这个数学术语是整数partition

更直接的方法是观察如果你对总数进行整数除法(向下舍入)除以组的数量,那么你的总和就会缩短总数为number_of_groups,所以你只需要分配这个数量整个阵列:

def even_partition(total, number_of_groups)
  quotient, remainder = total.divmod(number_of_groups)
  (number_of_groups-remainder).times.collect {quotient} +
  remainder.times.collect { quotient + 1}    
end

答案 1 :(得分:5)

天真的实现是这样的:

我们以(20, 3)为例。你想要三个数字。

20 / 3 # => 6

这是您的“基础”价值。创建一个包含三个六的数组[6, 6, 6]。这将让你18.现在你必须尽可能平均分配剩余的2。例如,枚举数组元素并将每个元素递增1,直到您没有要分发的值。结果是[7, 7, 6]。我认为这很好。

可能(正常)实施:

def breakdown(total, group_count)
  avg_value, extra = total.divmod(group_count)

  result = Array.new(group_count, avg_value)
  extra.times do |i|
    result[i] += 1
  end

  result
end

breakdown(10, 2) == [5, 5] # => true
breakdown(10, 3) == [4, 3, 3] # => true
breakdown(20, 3) # => [7, 7, 6]

答案 2 :(得分:5)

def n_parts(num, groupcount)
  div, mod = num.divmod(groupcount)
  Array.new(groupcount-mod, div) + Array.new(mod, div+1)
end

n_parts(100,3) => [33, 33, 34]

文档到Array.newFixnum.divmod

答案 3 :(得分:0)

我不知道它是如何调用的,但这是一个解决方案:

def num_of_sum sum, count
  result = [i = sum / count] * count # prepare an array e.g. [3,3,3] for 10,3
  result[sum - i * count..-1] + # these should be left intact
    result[0...sum - i * count].map { |i| i + 1 } # these are ++’ed
end

希望它有所帮助。

答案 4 :(得分:0)

另一种方式:

Conversion

或者,def floors_then_ceils(n, groups) floor, ceils = n.divmod(groups) groups.times.map { |i| (i < groups-ceils) ? floor : floor + 1 } end floors_then_ceils(10, 3) #=> [3, 3, 4] floors_then_ceils(9, 3) #=> [3, 3, 3] 可以替换为:

groups.times.map...