0

私はプロジェクトオイラーの問題を解決することでルビーを学び、実践しています。

これが問題12の私の解決策です。

# Project Euler problem: 12
# What is the value of the first triangle number to have over five hundred divisors?

require 'prime'

triangle_number = ->(num){ (num *(num + 1)) / 2 }

factor_count = ->(num) do
  prime_fac = Prime.prime_division(num)
  exponents = prime_fac.collect { |item| item.last + 1 }
  fac_count = exponents.inject(:*)
end

n = 2
loop do
  tn = triangle_number.(n)
  if factor_count.(tn) >= 500
    puts tn
    break
  end
  n += 1
end

このコードに加えることができる改善はありますか?

4

3 に答える 3

4

他の人が述べているように、Rubyist はメソッドやブロックをラムダよりもはるかに多く使用します。

RubyEnumerableは非常に強力な mixin であるため、Prime. そう:

require 'prime'
class Triangular
  class << self
    include Enumerable
    def each
      sum = 0
      1.upto(Float::INFINITY) do |i|
        yield sum += i
      end
    end
  end
end

これは非常に用途が広いです。それが機能することを確認するだけです:

Triangular.first(4) # => [1, 3, 7, 10]

良い。これを使用して問題を解決できます。

def factor_count(num)
  prime_fac = Prime.prime_division(num)
  exponents = prime_fac.collect { |item| item.last + 1 }
  exponents.inject(1, :*)
end

Triangular.find{|t| factor_count(t) >= 500}  # => 76576500

:

  • Float::INFINITY1.9.2 の新機能です。を使用する1.0/0か、以前のバージョンを使用している場合は をrequire 'backports'実行してください。loop
  • これeachは、最初にブロックが渡されたことを確認することで改善できます。次のようなことがよくあります。

      def each
        return to_enum __method__ unless block_given?
        # ...
    
于 2010-06-11T20:59:56.983 に答える
2

問題を一気に解決するのではなく、問題の個々の部分を見ていくと、Ruby の理解が少し深まるかもしれません。

最初の部分は、三角形の数が何であるかを調べることです。これは自然数の並びを使っているので、ルビでは範囲で表現できます。次に例を示します。

(1..10).to_a => [1,2,3,4,5,6,7,8,9,10]

Ruby の配列は列挙可能と見なされ、Ruby はデータを列挙する多くの方法を提供します。この概念を使用すると、 each メソッドを使用してこの配列を反復処理し、数値を合計するブロックを渡すことができます。

sum = 0
(1..10).each do |x|
  sum += x
end

sum => 55

これは、前の要素から返されたものを現在の要素に渡す inject と呼ばれる別の列挙可能なメソッドを使用して行うこともできます。これを使用すると、合計を 1 行で取得できます。この例では、機能的には (1..10) と同じように動作する 1.upto(10) を使用します。

1.upto(10).inject(0) {|sum, x| sum + x} => 55

これをステップ実行すると、これが最初に呼び出されたとき、sum = 0、x = 1、つまり (sum + x) = 1 になります。次に、これを次の要素に渡し、sum = 1、x = 2、(sum + x ) = 3. 次の sum = 3, x = 3, (sum + x) = 6. sum = 6, x = 4, (sum + x) = 10. など

これは、この問題の最初のステップにすぎません。このように言語を学びたい場合は、問題全体に取り組むのではなく、問題の各部分にアプローチし、その部分について何を学ぶのが適切かを学ぶ必要があります。

REFACTORED SOLUTION (まったく効率的ではありませんが)

def factors(n)
  (1..n).select{|x| n % x == 0}
end

def triangle(n)
  (n * (n + 1)) / 2
end

n = 2

until factors(triangle(n)).size >= 500
  puts n
  n += 1
end

puts triangle(n) 
于 2010-06-11T16:47:01.990 に答える
0

あなたは Ocaml や他の関数型言語を書いているようです。defRuby では、メソッドを定義するためにもっと使いたいと思うでしょう。ルビーはクリーンでいることです。しかし、それは個人的な好みでもあるかもしれません。

そして、loop doあなたができるのではなくwhile (faction_count(traingle_number(n)) < 500) do、1行には多すぎるかもしれない人もいます.

于 2010-06-11T16:32:36.367 に答える