最后一个从JS到Ruby的Odin项目的翻译

时间:2015-07-20 18:55:29

标签: javascript ruby

原始问题:

13195的主要因素是5,7,13和29。

600851475143号码的最大主要因素是什么?

这是我在JS的回答:

function largestPrimeFactor(n){
var i=2;
while (i<=n){
if (n%i == 0){
    n/=i;    
}else{
    i++;
    }
  }
console.log(i);
}
var a = 600851475143; 
largestPrimeFactor(a)

我花了几个小时试图弄清楚如何在Ruby中做到这一点,这就是我想出来的,但我无法让它工作:

def largestPrimeFactor (n)
i  = 2
while i <= n
    if n % i == 0
        n /= i 
     i++
        puts i
    end
  end
end

a = 600851475143
puts largestPrimeFactor(a)

2 个答案:

答案 0 :(得分:1)

要回答您的初始问题,您遗失的所有内容都是else,而不是使用i++,您应该使用i += 1

def largestPrimeFactor (n)
  i  = 2
  while i <= n
    if n % i == 0
      n /= i 
    else
      i += 1
    end
  end
end

然而,这段代码并不是非常“ruby-ish”,所以我将提供一些我可能会使用的实现。

没有必要计算这个,因为ruby已经有了确定素因子的方法。只需要prime,这是ruby标准库的一部分。

require 'prime'

def largestPrimeFactor(n)
  primes, _ = n.prime_division.transpose
  primes.max
end 

largestPrimeFactor(13195) # => 29
largestPrimeFactor(600851475143) # => 6857

此方法(以及原始JS代码)的唯一缺点是不使用称为memoization的东西,因此多次调用largestPrimeFactor相当大的数字可能会导致计算浪费。我们可以通过使用稍微复杂的解决方案来解决这个问题:

require 'prime'

def largestPrimeFactor(number)
  @largest_prime_factor ||= {}.tap do |hash|
    hash.default_proc = proc do |_, key|
      hash[key] = begin
        primes, _ = n.prime_division.transpose
        primes.max
      end
    end
  end[number]
end

largestPrimeFactor(13195) # => 29
largestPrimeFactor(600851475143) # => 6857

当运行这些不同的实现w / benchmark(也是ruby标准库的一部分)时,您可以看到巨大的改进

                           user     system      total        real
JS port                0.030000   0.000000   0.030000 (  0.036535)
without memozation     0.020000   0.000000   0.020000 (  0.017466)
with memozation        0.000000   0.000000   0.000000 (  0.000199)

答案 1 :(得分:1)

如果我需要使用此代码,下面并不是真正解决这个问题的方法,但这就是我将如何编写最相似的解决方案。

我使用两种方法使其更易于使用。要输出答案(我认为你在另一个问题上遇到了困难),你需要运行:

puts largest_prime_factor(600851475143)

以下是代码:

def largest_prime_factor(input)
  i = 1
  while i < input
    input /= i if (is_prime?(i) && input%i == 0) 
    i += 1
  end
  input
end

def is_prime?(num)
  (2...num).each {|i| num%i == 0 ? false : true}
end