2

私はこれまでにこのコードを持っています:

def longest_awtz(n)
  upto = n
  series = []

  for x in 2..upto
    series << x
  end

  series.each do |num|
    print num.to_s + " - " 
    while num != 1
      if num % 2 == 0
        num = num / 2
        print num.to_s + " - "
      else
        num = (3 * num) + 1
        print num.to_s + " - "
      end
    end
    puts " "
  end
end

longest_awtz(6)

そのコードの出力は次のとおりです。

----------------------------------------------
こんにちは世界                                   
2 - 1 -                                      
3 - 10 - 5 - 16 - 8 - 4 - 2 - 1 -  
4 - 2 - 1 -  
5 - 16 - 8 - 4 - 2 - 1 -  
6 - 3 - 10 - 5 - 16 - 8 - 4 - 2 - 1 -  
----------------------------------------------

ここで、どの開始番号が最も長いチェーンを生成するかを特定したいので、各チェーンを配列に入れてカウントし、どれが最も長いかを特定する必要があります。最終的な出力は次のようになります。

----------------------------------------------
こんにちは世界                                   
2 - 1 -                                      
3 - 10 - 5 - 16 - 8 - 4 - 2 - 1 -  
4 - 2 - 1 -  
5 - 16 - 8 - 4 - 2 - 1 -  
6 - 3 - 10 - 5 - 16 - 8 - 4 - 2 - 1 -  

[2,1] # は 2
[3,10,5,16,8,4,2,1] # は 8
[4,2,1] # は 3
[5,16,8,4,2,1] # は 6
[6,3,10,5,16,8,4,2,1] # は 9
# 最長のチェーンを作成する開始番号を特定して出力します。
6 は、最長のチェーンを作成する開始番号です。
----------------------------------------------

これまでのところ、上記の最初の出力があり、それぞれを配列に入れる方法にこだわっています。私の問題を解決するのを手伝ってもらえますか?

4

3 に答える 3

2

適切な抽象化を伴う関数型アプローチを使用すると、プロジェクト オイラーの問題 (およびその問題に関するすべての数学的問題) はより簡潔で宣言的になります。

collatz = proc { |n| n.even? ? n/2 : (3*n + 1) }
collatz_length = proc { |n| n > 1 ? 1 + collatz_length.(collatz.(n)) : 0 }
(1...1000).max_by(&collatz_length)
#=> 871
于 2013-05-27T09:54:25.933 に答える
1

まず、シーケンスの生成を独自のメソッドに抽出します。

def generate_sequence(num)
  result = [num]
  while num != 1
    if num%2 == 0
      num = num/2
    else
      num = (3*num)+1
    end
    result << num
  end
  result
end

これは、シーケンスを含む配列を返します。次に、 の入力から生じるすべての系列を生成するメソッドを作成できます1..n

def generate_sequences_upto(n)
  1.upto(n).map do |num|
    generate_sequence(num)
  end
end

最長のシーケンスを選択する別のもの:

def longest_sequence(n)
  generate_sequences_upto(n).max_by(&:length)
end

たとえば、次のように使用できます。

longest = longest_sequence(6)
puts "The longest sequence with length #{longest.length} is\n#{longest.inspect}"

出力します

The longest sequence with length 9 is
[6, 3, 10, 5, 16, 8, 4, 2, 1]

で数字を区切りたい場合は、次" - "の使用をお勧めしますArray#join

longest.join(' - ')
#=> "6 - 3 - 10 - 5 - 16 - 8 - 4 - 2 - 1"
于 2013-05-27T09:03:28.293 に答える
0

mapのように、おそらく が必要です。

array = series.map do |num|

ただし、これを適切に使用するには、単に出力するのではなく、必要な配列の値を返すようにブロックを調整する必要があります ( return 、ここでは不要ですputs) nil

の代わりに、メインの配列内のサブ配列に個々の数値を収集するにはputs、必要に応じてsubarray.push( num )、または同様の構文を使用します。これには、いくつかの同等の構文があります。次に、代わりに(または後)puts " "subarray変数(またはそれを呼び出したもの)を最後に配置します。これにより、ブロックからの戻り値になり、メイン配列に追加されます。配列の配列になってしまいます。

Ruby オブジェクトで何ができるかを知りたい場合は、コマンドを起動しirbて使用し、Ruby オブジェクトでmethodsできるすべてのことを確認することを強くお勧めします。

irb
1.9.3-p327 :001 > a = [1,2,3,4]
 => [1, 2, 3, 4]
1.9.3-p327 :002 > a.methods.sort
 => [:!, :!=, :!~, :&, :*, :+, :-, :<<, :<=>, :==, :===, :=~, :[], :[]=, :__id__, :__send__, :all?, :any?, :assoc, :at, :chunk, :class, :clear, :clone, :collect, :collect!, :collect_concat, :combination, :compact, :compact!, :concat, :count, :cycle, :define_singleton_method, :delete, :delete_at, :delete_if, :detect, :display, :drop, :drop_while, :dup, :each, :each_cons, :each_entry, :each_index, :each_slice, :each_with_index, :each_with_object, :empty?, :entries, :enum_for, :eql?, :equal?, :extend, :fetch, :fill, :find, :find_all, :find_index, :first, :flat_map, :flatten, :flatten!, :freeze, :frozen?, :grep, :group_by, :hash, :include?, :index, :initialize_clone, :initialize_dup, :inject, :insert, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_variable_defined?, :instance_variable_get, :instance_variable_set, :instance_variables, :is_a?, :join, :keep_if, :kind_of?, :last, :length, :map, :map!, :max, :max_by, :member?, :method, :methods, :min, :min_by, :minmax, :minmax_by, :nil?, :none?, :object_id, :one?, :pack, :partition, :permutation, :pop, :private_methods, :product, :protected_methods, :public_method, :public_methods, :public_send, :push, :rassoc, :reduce, :reject, :reject!, :repeated_combination, :repeated_permutation, :replace, :respond_to?, :respond_to_missing?, :reverse, :reverse!, :reverse_each, :rindex, :rotate, :rotate!, :sample, :select, :select!, :send, :shift, :shuffle, :shuffle!, :singleton_class, :singleton_methods, :size, :slice, :slice!, :slice_before, :sort, :sort!, :sort_by, :sort_by!, :taint, :tainted?, :take, :take_while, :tap, :to_a, :to_ary, :to_enum, :to_s, :transpose, :trust, :uniq, :uniq!, :unshift, :untaint, :untrust, :untrusted?, :values_at, :zip, :|]

それは学ぶべき方法の負荷と負荷です!しかし、たとえばRuby Array mapGoogle に入力すると、ほとんどの場合、最初の回答で役立つ参照が得られます。

Ruby のイディオムの多くは、配列メソッドとブロックを組み合わせて実行できることに基づいています。時間をかけて調べてみる価値はあります。

于 2013-05-27T08:07:40.997 に答える