1

これは特に ruby​​ の問題ではなく、アルゴリズムに関する一般的な質問です。しかし、役に立ついくつかの ruby​​ 固有の配列メソッドがあるかもしれません。

私は30個のアイテムを持つ配列を持っています。15 から 30 の間のアイテム数を要求し、配列全体からできるだけ均等に分散された特定の数のアイテムを選択したいと考えています。選択はランダムでなく、毎回同じ結果を返す必要があります。

誰かが 16 個のアイテムを要求したとします。最初の 16 個を返すと、大失敗になります。代わりに、奇数番号のものすべてと最後のものを返すことができました。配列に 1 から 30 までの数字を格納しておけば、返せます。

myArr.spread(16)
=> [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,30]

誰かが 20 個のアイテムを要求した場合、それは少しトリッキーです。これを行うための適切なプログラムによる方法をすぐには思いつきません。すでに誰かによって解決されているに違いないような気がします。助言がありますか?

4

5 に答える 5

3

Alex Dに触発されて、これを行うことになりました。n-1回ステップスルーしてから、常に最後の要素を最後に追加します。

class Array
  def spread(n)
    step = self.length.to_f / (n -1) 
    (0..(n-2)).to_a.collect{|i| self[i * step]} + [self.last]
  end
end

 > (1..30).to_a.spread(3)
 => [1, 16, 30] 
 > (1..30).to_a.spread(4)
 => [1, 11, 21, 30] 
 > (1..30).to_a.spread(5)
 => [1, 8, 16, 23, 30] 
 > (1..30).to_a.spread(15)
 => [1, 3, 5, 7, 9, 11, 13, 16, 18, 20, 22, 24, 26, 28, 30] 
于 2012-08-13T13:02:16.920 に答える
1

配列のサイズを選択する項目の数で割ります (切り捨て除算は使用しないでください)。これは、項目を選択しながら配列を移動するときの「ストライド」になります。配列のサイズと同じかそれを超えるまで、実行中の合計に「ストライド」を追加し続けます。「ストライド」を追加するたびに、整数部分を取り、それを配列へのインデックスとして使用して項目を選択します。

100 個のアイテムがあり、30 個を選択したいとします。この場合、「ストライド」は 3.3333 になります...そのため、「累計」の 3.3333 から始めて、アイテム 3 を選択します。次に、6.66666 であるため、アイテム 6 を選択します。次は 10.0 です。つまり、アイテム 10 を選択します。

「off by one」エラーが発生しないこと、および配列サイズまたは選択するアイテムの数がゼロの場合にゼロで除算しないことをテストしてください。また、ガード句を使用して、選択するアイテムの数が配列内の数を超えないようにします。

于 2012-08-10T15:08:34.733 に答える
1

これについては同様の質問がありました、解決策は python にあります。

Ruby では、次のようになります。

class Array
    def spread( count)
        length = self.length
        result = Array.new
        0.upto(count-1) do |i|
            result << self[(i * length.to_f / count).ceil]
        end
        return result
    end
end

arr = Array(1..30)
puts arr.spread(20)
#=> [1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30]
于 2012-08-10T15:23:37.687 に答える
-1

固定シードでRandom (doc)を使用してみることができます。

  • オブジェクトを使用するRandomと、配列の要素をランダムに選択できます
  • 固定シードは、関数へのすべての呼び出しが乱数のリストを生成することを保証します。

たとえば、 Array#sample

def spread(arr, count) do
    arr.sample(count, Random.new(0))
end
于 2012-08-10T14:52:11.730 に答える