10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

数値をランダムに分配する

Last updated at Posted at 2015-07-02

値をランダムに分配するにはどうすればいいのか という記事をみて、そういえば前にこんなことを考えていたなーということを思い出したので書いた。

背景

ゲームのユニットのパラメタをランダムに生成したいことはよくある。しかしこのやり方には注意が必要だ。
例えば10000ptを割り振りたいときに、「ランダムにパラメタを選んで1増やす。これを10000回繰り返す」とすると各パラメタの値は期待値に落ち着く。
パラメタ数が5種類なら、各パラメタは全体的に2000前後になってしまう。

やりたいこと

各パラメタの値がそれなりに分散して欲しい。

やり方

中学か高校の数学の「場合の数」で習ったような方法を使う。

10,000個のみかんを5人で分けたい場合、みかんを一列に並べランダムに4枚の仕切りをさして各人が区切られた区間のみかんをもらう。

この方法だと少なくともみかんの数が増えても、もらえるみかんの数が期待値に収束することは無い。

コード

distribute_1が期待値に収束するやり方。distribute_2がしないやり方。

random_parameter.rb
# 検証用のヘルパ関数
def sum_value(hash)
  ret = 0
  hash.each do |k, v|
    ret += v
  end
  ret
end

def distribute_1(max, params)
  ary = Array.new(params.size, 0)
  max.times do
    index = rand(ary.size)
    ary[index] += 1
  end
  params.zip(ary).to_h
end

def distribute_2(max, params)
  randoms = Array.new(params.size - 1){ rand(max) }.sort
  table = [0, *randoms, max]
  params.map.with_index { |key, index| [key, table[index + 1] - table[index]] }.to_h
end


max = 10_000
params = [:atk, :def, :dex, :mag, :lak]

puts "---- type 1"
table = distribute_1(max, params)
p table
puts "total = #{sum_value table}"

puts "---- type 2"
table = distribute_2(max, params)
p table
puts "total = #{sum_value table}"
出力
$ ruby random_parameter.rb
---- type 1
{:atk=>1994, :def=>2009, :dex=>1969, :mag=>2017, :lak=>2011}
total = 10000
---- type 2
{:atk=>1322, :def=>2089, :dex=>465, :mag=>4966, :lak=>1158}
total = 10000

それなりにバラけます。

10
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?