所有可能和的最小值、最大值、平均值和中值 (Ruby)

Posted

技术标签:

【中文标题】所有可能和的最小值、最大值、平均值和中值 (Ruby)【英文标题】:Min, Max, Average, and Median of All Possible Sums (Ruby) 【发布时间】:2018-08-09 18:32:12 【问题描述】:

我一直在使用我找到的一段 Ruby 代码 here。

代码如下:

a = [1, 4, 7, 13]

def add(ary, idx, sum)
    (idx...ary.length).each do |i|
        add(ary, i+1, sum + ary[i])
    end
    puts sum
end
add(a, 0, 0)

问题是,我不需要它来吐出所有总和相加的结果。我需要总和的最小值、最大值、中值和平均值。

如何修改此代码以获取它们?我是 Ruby 的初学者。我一直在使用这段代码,然后将结果传输到 Excel 以获得我想要的值。但感觉我的方法可能更有效。

感谢您的帮助。

编辑:预期结果 - 目前代码在我的屏幕上吐出:

25
12
18
5
21
8
14
1
24
11
17
4
20
7
13
0

我希望它输出最小值、平均值、中值和最大值:

0
12.5
12.5
25

【问题讨论】:

您需要指定 - “所有可能的总和”是什么意思。附言请注意,此代码使用递归 - 在这个简单循环的简单任务中绝对没有必要。 我添加了预期的结果。我不知道 idx=sum=0 是什么意思。我只是使用它,因为它到目前为止有效(在手动验证之后)。这里所有可能的和意味着如果我有一组数字(例如,1、2、3),结果应该是另一组数字,结果为 1、1+2、1+2+3、2+3 , 1+3...等。直到没有更多未使用的组合。但我不需要一堆数字。我只需要最小值、最大值、中值、平均值。 我修改了预期的结果。 然后只收集总和而不是打印它们并对其进行排序。排序数组的最小值/最大值/平均值/中位数是微不足道的。 在Ruby中你通常会看到0.upto(a.size).flat_map |i| a.combination(i).map(&:sum) 【参考方案1】:
a = [1, 4, 7, 13]

def all_sums(array)
    combination_lengths = (0..array.length)
    all_combinations = combination_lengths.flat_map do |c|
      array.combination(c).to_a
    end
    all_combinations.map(&:sum)
end

def print_min_max_avg_med(array)
  puts array.min
  puts array.max
  puts array.sum.to_f / array.length
  sorted_arr = array.sort
  puts sorted_arr[(array.length - 1) / 2] + sorted_arr[array.length / 2] / 2.0
end

print_min_max_avg_med(all_sums(a))

【讨论】:

不幸的是,我正在寻找一般工作的东西,而不仅仅是这个任务。正如我在其他地方的评论中提到的,这是用于计算可选新车套餐的定价统计数据。无法保证包裹的数量是偶数还是奇数。 @johnny 嗯?此解决方案确实适用于所有数量的包。如果您指的是我的评论,那是专门针对 print_min_max_avg_med 函数的。 @StefanPochmann 除了将中位数转换为浮点数之外,我认为它应该适用于奇数长度的数组。但是对于这个用例,空支票可能会被删除 @StefanPochmann 啊,是的,你是对的。我正在查看错误的值。现在修复它。 需要最小和最大 sums,而不是最小和最大元素。例如,如果数组为[1,-2,3,-4],则最小和最大和将分别为-64。平均值和中位数类似。【参考方案2】:

好的,我们可以将它们存储在一个数组中,然后将该数组用于您需要的值,而不是输出这些值。 (由 Stefan Pochmann 咀嚼后编辑)

 a = [1, 4, 7, 13]

def add(ary, idx, sum, results = nil)
  unless results
    results = []
    first_run = true
  end
  (idx...ary.length).each do |i|
      add(ary, i+1, sum + ary[i], results)
  end
  results << sum

  if first_run
    puts results.min
    puts results.inject(&:+).to_f / results.size
    puts (results.sort[((results.size - 1) / 2)] + results.sort[(results.size / 2)]) / 2.0
    puts results.max
  end
end
add(a, 0, 0)

【讨论】:

经过测试,似乎还可以。 :)【参考方案3】:

好的,在看到 Pochmann 和 Bronca 的例子后,我在谷歌上搜索了一个更好的方法来获得中位数。

a = [1, 4, 7, 13]

def all_sums(array)
    combination_lengths = (0..array.length)
    all_combinations = combination_lengths.flat_map do |c|
      array.combination(c).to_a
    end
    all_combinations.map(&:sum)
end

def median(array)
  sorted = array.sort
  len = sorted.length
  (sorted[(len - 1) / 2] + sorted[len / 2]) / 2.0
end

def print_min_max_avg_med(array)
  puts array.min
  puts array.empty? ? 0 : array.sum.to_f / array.length
  puts median(array)
  puts array.max
end

print_min_max_avg_med(all_sums(a))

我已经进行了一些测试,它似乎对奇数和偶数数组都有效。希望这对未来其他卡在我现在职位上的人有用。

感谢所有帮助过的人。

【讨论】:

呸...说“在谷歌上搜索了一个更好的方法来获得中位数”让我兴奋了一会儿。因为这是我唯一不能在线性时间内轻松完成的事情。但后来我看到你实际上并没有以不同的方式做这件事,但仍然是相同的指数方式。 我的做法有缺点吗?在厌倦了我为 Excel 制作的估计公式的不准确性之后,我真的开始研究 Ruby,就像 2 天前一样。 嗯,与迄今为止提出的所有方法相同的“缺点”。它需要指数级的时间和空间。如果你有 30 个或更多的包裹,那你就有麻烦了。 啊,我明白了。好吧,谢天谢地,我不太可能遇到一家在单一车型上提供 30 个包装的汽车制造商。甚至奥迪也有最多 10 个。 是的,十个人这样就可以了。您仍然可以使用min = 0, max = a.sum and average = a.sum / 2.0,但如果您要计算所有总和,您也可以使用它们。【参考方案4】:

最小值和最大值

最小值和最大值很简单。

def min_and_max_of_sums a
  return [nil, nil] if a.empty?      
  negs, nonnegs = a.partition  |n| n < 0 
  [negs.any? ? negs.sum : nonnegs.min, nonnegs.any? ? nonnegs.sum : negs.max]
end

min_and_max_of_sums [1, 4, -5, 7, -8, 13]
  #=> [-13, 25]
min_and_max_of_sums [1, 2, 3]
  #=> [1, 6]
min_and_max_of_sums [-1, -2, -3]
  #=> [-6, -1]
min_and_max_of_sums []
  #=> [nil, nil]

平均值

现在考虑计算平均值。

如果n是数组a的大小,则的元素有2n种组合em>a 包含 0n 元素。1 此外,每个元素之间存在 1-1 映射组合和一个由 0 和 1 组成的 n-vector,其中 n-vector 的 ith 元素等于 1当且仅当元素 ai 包含在组合中。注意有2n个这样的n-向量,一半在中包含一个1第 i 个 位置。这意味着一半的组合包含元素ai。由于 i 是任意的,因此 a 的每个元素都出现在一半的组合中。

所有组合的所有元素之和的平均值等于T/2n,其中T是每个组合的元素。每个元素ai出现在2n/2种组合中,所以它对T的贡献em> 等于(用 Ruby 术语)

a[i] * 2**(n)/2

因为这对 a 的每个元素都成立,所以均值等于

a.sum * (2**(n)/2)/2**(n)
  => a.sum/2

这是一个例子。对于数组

a = [1, 4, 8]

总和的平均值是

a.sum/2
  #=> 13/2 => 6.5

如果我们要根据其定义计算平均值,我们将执行以下计算(当然会得到相同的返回值)。

(0 + (1) + (4) + (8) + (1+4) + (1+8) + (4+8) + (1=4+8))/2**3
  #=> (4*1 + 4*4 + 4*8)/8
  #=> (1 + 4 + 8)/2
  #=> 6.5

我会把中位数的计算留给别人。

1 搜索“二项式系数之和”here。

【讨论】:

以上是关于所有可能和的最小值、最大值、平均值和中值 (Ruby)的主要内容,如果未能解决你的问题,请参考以下文章

均值滤波,中值滤波,最大值滤波,最小值滤波

均值滤波,中值滤波,最大最小值滤波

Leetcode——数组中最大数对和的最小值

813. 最大平均值和的分组(Python)

计算输入数字的最小值、最大值和平均值

Matplotlib 箱线图使用预先计算(汇总)统计