Ruby 初学者 - 需要帮助优化此代码
Ruby beginner - need help optimising this code
目前在学习Ruby/programming的过程中,总的来说,遇到了这个问题:
Your task is to construct a building which will be a pile of n cubes. The cube at the bottom will have a volume of n^3
, the cube above will have volume of (n-1)^3
and so on until the top which will have a volume of 1^3
.
You are given the total volume m
of the building. Being given m
can you find the number n
of cubes you will have to build?
The parameter of the function findNb(find_nb, find-nb)
will be an integer m
and you have to return the integer n
such as n^3 + (n-1)^3 + ... + 1^3 = m
if such a n
exists or -1
if there is no such 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
这样的输入时,我将如何理解它作为
find_nb(24723578342962)
任何关于如何改进现有代码的提示都将不胜感激。
提示1:不需要无穷大:在某个n
之后,总和会大于m
,并迅速远离。
提示 2:如果找到 n
,函数将永远不会到达它的最后一行,因为 return
.
提示 3:如果您到达 each
块的末尾,next
是自动的。
提示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
Fixing/Improving 你的代码
要修复您的代码,请在 if-statement
中创建另一个分支,告诉您的迭代何时 return -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
目前在学习Ruby/programming的过程中,总的来说,遇到了这个问题:
Your task is to construct a building which will be a pile of n cubes. The cube at the bottom will have a volume of
n^3
, the cube above will have volume of(n-1)^3
and so on until the top which will have a volume of1^3
. You are given the total volumem
of the building. Being givenm
can you find the numbern
of cubes you will have to build? The parameter of the functionfindNb(find_nb, find-nb)
will be an integerm
and you have to return the integern
such asn^3 + (n-1)^3 + ... + 1^3 = m
if such an
exists or-1
if there is no suchn*
.
这是我解决这个问题的尝试:
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
这样的输入时,我将如何理解它作为find_nb(24723578342962)
任何关于如何改进现有代码的提示都将不胜感激。
提示1:不需要无穷大:在某个n
之后,总和会大于m
,并迅速远离。
提示 2:如果找到 n
,函数将永远不会到达它的最后一行,因为 return
.
提示 3:如果您到达 each
块的末尾,next
是自动的。
提示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
Fixing/Improving 你的代码
要修复您的代码,请在 if-statement
中创建另一个分支,告诉您的迭代何时 return -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