challenge 重複無し乱数

整数nを渡すと1 ~ n までの整数を重複しないようランダムに出力する関数「bingo」を作ってください。

このお題はraynstardさんの投稿を元にしています。ご投稿ありがとうございました。 投稿の内容には表示のしかたも含まれていたのですが、 このお題では「重複しない1~nまでの乱数をどうやって作るか」という点に集中することにして、 結果の整形は続編としてこの後のお題で出すことにします。 サンプル入出力は下のようになります。

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

Posted feedbacks - Ruby

久々の1行問題
1
2
3
4
5
6
7
8
def bingo(n)
  (1..n).to_a.sort_by{rand}
end
bingo 10                        # => [4, 2, 1, 10, 8, 5, 3, 7, 6, 9]
bingo 3                         # => [3, 1, 2]
bingo 3                         # => [1, 3, 2]
bingo 3                         # => [2, 3, 1]
bingo 10                        # => [3, 2, 6, 5, 7, 4, 1, 8, 10, 9]

普通にやってみた
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
def bingo(num)
        raise ArgumentError.new("fixnum only") unless num.kind_of? Fixnum
        raise ArgumentError.new("1 ijyou de onegai simasu") unless num >= 1

        results = []

        ary=(1..num).to_a
        ary.size.times{
                index = (rand * ary.size).to_i
                results << ary.delete_at(index)
        }

        results
end

Ruby 1.9にはArray#shuffleが存在します
1
2
3
def bingo(n)
  [*1..n].shuffle
end

どこかで見たことがある問題だなぁ…
コードはあまり確かめずに書いた.
配列の参照範囲とか間違ってなければいいけど.
1
2
3
4
5
6
7
8
def bingo( n )
  ary = (1..n).to_a
  n.downto(1) {| i |
    e = ary.delete_at( rand( i ) )
    ary.push( e )
  }
  ary
end

こうすると配列作成コスト1回で済む・・・?

繰り返し部分をxsを返す式にしようとinjectやら何やら色々試したけど
いまひとつきれいにできないのであきらめました.
1
2
3
4
5
def bingo(n)
  xs = *1..n
  n.times {|i| xs << xs.slice!(rand(n - i)) }
  xs
end

うーん,なかなか短くならない.

1
2
3
4
5
def bingo(n)
  pool, ret = (1..n).to_a, []
  ret << (pool.delete_at(rand(pool.size))) until pool.empty?
  ret
end

randメソッドを利用して自作してみた.

1
2
3
4
def bingo(n)
  ary = Array.new(n){|i| i+1}
  Array.new(n){|i| ary.delete_at(rand(n-i).modulo(n-i))}
end

Index

Feed

Other

Link

Pathtraq

loading...