ruby - 如何求阶乘之和

标签 ruby minitest

使用 minitest,我试图让这个测试通过,它要求 5! 的总和:

def test_sum_of_factorials

  sum_of_factorials = 0
  numbers = [1, 2, 3, 4, 5]


  assert_equal 153, sum_of_factorials
end

我写了一个简单的解决方案,但它又长又重复​​:

fractorial_5 = numbers.inject(1) {|aggregate, num| aggregate * num}
fractorial_4 = numbers[0..3].inject(1) {|aggregate, num| aggregate * num}
fractorial_3 = numbers[0..2].inject(1) {|aggregate, num| aggregate * num}
fractorial_2 = numbers[0..1].inject(1) {|aggregate, num| aggregate * num}
fractorial_1 = 1

fractorials_array = [fractorial_1, fractorial_2, fractorial_3, fractorial_4, fractorial_5]

fractorials_array.each {|fractorial| sum_of_factorials += fractorial}

有人愿意解释一个更干净、更简单的解决方案吗?

最佳答案

看起来你得到了:

def test_sum_of_factorials
  sum_of_factorials = 0
  numbers = [1, 2, 3, 4, 5]
  <...missing bits...>
  assert_equal 153, sum_of_factorials
end

并被要求填写缺失的位。我认为需要类似以下内容。

def test_sum_of_factorials
  sum_of_factorials = 0
  numbers = [1, 2, 3, 4, 5]
  fac = 1
  numbers.each do |n|
    fac *= n
    sum_of_factorials += fac
  end
  assert_equal 153, sum_of_factorials
end

我们可以将其写为:

def test_sum_of_factorials
  numbers = [1, 2, 3, 4, 5]      
  assert_equal 153, sum_of_factorials(numbers)
end

def sum_of_factorials(numbers)
  fac_sum = 0
  fac = 1
  numbers.each do |n|
    fac *= n
    fac_sum += fac
  end
  fac_sum
end

哪里

sum_of_factorials([1,2,3,4,5])
  #=> 153

但是,使用 Array#sum 会更像 Ruby。编写 sum_of_factorials 如下:

def sum_of_factorials(numbers)
  fac = 1
  numbers.sum { |n| fac *= n }
end

结合您的问题标题,这就是为什么其他答案的作者假设您正在询问如何改进 sum_of_factorials 方法。首先,它可以传递参数numbers.max,而不是数组numbers

编写 sum_of_factorials 的另一种方法是使用方法 Enumerator::produce ,在 v2.7 中首次亮相。

def sum_of_factorials(n)
  enum = Enumerator.produce([1,1]) { |n0, n1| [n0+1, (n0+1)*n1] }
  n.times.sum { enum.next.last }
end

(1..8).each { |n| puts "%d: %6d" % [n, sum_of_factorials(n)] }
1:      1
2:      3
3:      9
4:     33
5:    153
6:    873
7:   5913
8:  46233

请注意,如果:

enum = Enumerator.produce([1,1]) { |n0, n1| [n0+1, (n0+1)*n1] }
  #=> #<Enumerator: #<Enumerator::Producer:0x000059d490c742a0>:each> 

然后

enum.next #=> [1, 1] 
enum.next #=> [2, 2] 
enum.next #=> [3, 6] 
enum.next #=> [4, 24] 

因此,14 的阶乘由下式给出(重新定义或倒回 enum 后):

enum.next.last #=>  1 
enum.next.last #=>  2 
enum.next.last #=>  6 
enum.next.last #=> 24 

如果n 可以等于零,请在方法的开头添加行return 1 if n.zero?

关于ruby - 如何求阶乘之和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59757243/

相关文章:

ruby-on-rails-3 - 使用 Minitest+Guard+Spork,每次运行都会重新加载所有测试套件和支持文件

ruby-on-rails - Rails 测试(MiniTest)中assigns 方法的目的是什么?

ruby-on-rails-4 - 在 Rails 4 minitest 中禁用 Zeus 的运行两次?

ruby-on-rails - 如何从Rails卸载Minitest

ruby-on-rails - 使用 Tire 和 ElasticSearch 搜索多个模型

ruby-on-rails - 如何配置 Rails 5.2.1 服务器监听所有接口(interface)?

ruby-on-rails - 通过 Rails 访问存储在 Amazon S3 中的数据

Ruby 到 Scala 的代码转换

ruby-on-rails - 当前正在执行的代码

ruby - minitest - 在测试运行时输出更好的错误报告