Ruby初学者 - 需要帮助优化此代码

时间:2016-11-29 03:17:06

标签: ruby algorithm optimization enumerable

目前正在学习Ruby /编程的过程中,我遇到了这个问题:

  

你的任务是建造一座建筑物,它将是一堆n个立方体。底部的立方体的体积为n^3,上面的立方体的体积为(n-1)^3,依此类推,直到顶部的体积为1^3。   您将获得建筑物的总体积m。获得m后,您是否可以找到要构建的多维数据集n的数量?   函数findNb(find_nb, find-nb)的参数将是整数m,如果n存在,则必须返回整数n^3 + (n-1)^3 + ... + 1^3 = m,例如n或{{} 1}}如果没有这样的-1

这是我尝试解决这个问题:

n*

这似乎适用于我知道可以使用的输入,例如:

def find_nb(m)
  (1..Float::INFINITY).each do |n|
    if (1..n).inject(0) {|sum, value| sum + value**3} == m
      return p n 
    else
      next
    end
  end
end

我需要帮助的地区:

  • 我不知道如果没有find_nb(4183059834009) find_nb(135440716410000) find_nb(40539911473216) 的值满足等式,我会如何理解它,因此输出n作为输入,例如

    -1
  • 非常感谢任何有关如何改善现有代码的提示。

2 个答案:

答案 0 :(得分:7)

提示1:你不需要去无穷大:在某个n之后,总和将大于m,并且会越来越远。

提示2:如果找到n,由于return,该函数将永远不会到达最后一行。

提示3:next如果到达each阻止的结尾,则会自动生成。

提示4:每次都不需要从头开始重新计算立方体的总和。你没有建造一座全新的建筑,只是在下方放置一个更大的立方体。

因此...

def find_nb(m)
  n = 1
  sum = 1
  while sum < m
    n += 1
    sum += n**3
  end
  return sum == m ? n : -1
end

编辑:这是一个功能版本,但我认为上面的简单while仍然更清晰(也可能更快):

def find_nb(m)
  sum = 0
  sizes = 1.upto(Float::INFINITY)
    .lazy
    .map { |n| sum += n ** 3 }
    .take_while { |x| x <= m }
    .to_a
  sizes.last == m ? sizes.length : -1
end

答案 1 :(得分:1)

修复/改进您的代码

要修复代码,请在if-statement中创建另一个分支,告诉您的迭代何时返回-1。在next迭代中不需要each(归功于@Amadan指出这一点)。

注意,最好不要从方法定义中打印任何内容。调用方法时打印。压痕和间距得到改善。另请注意,我在变量total中定义了多维数据集的总和:

def find_nb m
  (1..Float::INFINITY).each do |n|
    total = (1..n).inject(0) { |sum, value| sum + value**3 }
    if total == m
      return n 
    elsif total > m
      return -1
    end
  end
end

find_nb 4183059834009   #=> 2022
find_nb 135440716410000 #=> 4824
find_nb 40539911473216  #=> 3568
find_nb 37              #=> -1

进一步改进

如果你想使用无限循环,Ruby有loop。与with_index一起使用,如下所示:

def find_nb m
  loop.with_index(1) do |_,n|
    t = (1..n).inject { |sum,i| sum + i**3 }
    if t == m
      return n            
    elsif t > m
      return -1        
    end
  end
end

find_nb 4183059834009   #=> 2022
find_nb 135440716410000 #=> 4824
find_nb 40539911473216  #=> 3568
find_nb 37              #=> -1