『ランダムな並び替え方法』

1,2,3,4,5などの整数の組をランダムに(たとえば 3,1,4,2,5 など)並び替えるための方法です。

以下のように、1から10までの数のリスト(配列)があったとします;

>    restart;

>    integerData := [seq(i, i=1..10)];

integerData := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

この整数のリスト要素をランダムに並び替えます。

まず、各要素を 0 〜 1 の乱数と共にペアにします。

>    randomize():
randomNums := evalf([seq(rand()/10^12, i=1..nops(integerData))]);

randomNums := [.7592457720, .6290695468e-1, .5148286164, .2147205772e-1, .8440650641, .1573888319, .6605283183, .2871021210, .6633764121, .3726585777]

>    pairData := ListTools[Transpose]([integerData, randomNums]);

pairData := [[1, .7592457720], [2, .6290695468e-1], [3, .5148286164], [4, .2147205772e-1], [5, .8440650641], [6, .1573888319], [7, .6605283183], [8, .2871021210], [9, .6633764121], [10, .3726585777]]
pairData := [[1, .7592457720], [2, .6290695468e-1], [3, .5148286164], [4, .2147205772e-1], [5, .8440650641], [6, .1573888319], [7, .6605283183], [8, .2871021210], [9, .6633764121], [10, .3726585777]]

このリストの各要素を2番目(すなわち乱数値)でソートします。ソートの順序は昇順でも降順でもどちらでも構いません。

>    sortedData := sort(pairData, (s, t)->evalb(s[2]>t[2]));

sortedData := [[5, .8440650641], [1, .7592457720], [9, .6633764121], [7, .6605283183], [3, .5148286164], [10, .3726585777], [8, .2871021210], [6, .1573888319], [2, .6290695468e-1], [4, .2147205772e-1]]...
sortedData := [[5, .8440650641], [1, .7592457720], [9, .6633764121], [7, .6605283183], [3, .5148286164], [10, .3726585777], [8, .2871021210], [6, .1573888319], [2, .6290695468e-1], [4, .2147205772e-1]]...

並び替えられた sortedData の1番目の要素を抜き出します。1番目の要素だけを抜き出すには、リストを転置させてもいいですし、順次1番目の要素を抜き出しても構いません。

転置させる方法:

>    ListTools[Transpose](sortedData)[1];

[5, 1, 9, 7, 3, 10, 8, 6, 2, 4]

順次抜き出す方法:

>    map(x->x[1], sortedData);

[5, 1, 9, 7, 3, 10, 8, 6, 2, 4]

ここで用意した手順をひとつの手続きにまとめておくと、以下のようになります。

>    whattype([a,b,c]);

list

>    RandomPermutation := proc(d::list)
  local len, s, t, ind, pd;

  len := nops(d);
  randomize();
  ind := [seq(rand()/10^12, i=1..len)]; # random number for sorting
  pd := ListTools[Transpose]([d, ind]); # change to pairs list
  # sorting each element by random element
  map( m->m[1],
       sort(pd, (s,t)->evalb(s[2]>t[2]))
  );
end proc:

実験してみましょう。

>    RandomPermutation([a,b,c,d,e,f,g]);

[d, a, c, b, g, f, e]

>    data := [seq(i, i=1..100)];

data := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 5...
data := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 5...

>    RandomPermutation(data);

[47, 79, 76, 62, 96, 95, 93, 56, 86, 72, 59, 83, 89, 14, 19, 31, 25, 29, 24, 54, 17, 8, 53, 16, 6, 58, 10, 81, 65, 67, 64, 4, 22, 98, 82, 21, 34, 49, 41, 35, 36, 27, 30, 69, 99, 78, 1, 68, 57, 39, 46, ...
[47, 79, 76, 62, 96, 95, 93, 56, 86, 72, 59, 83, 89, 14, 19, 31, 25, 29, 24, 54, 17, 8, 53, 16, 6, 58, 10, 81, 65, 67, 64, 4, 22, 98, 82, 21, 34, 49, 41, 35, 36, 27, 30, 69, 99, 78, 1, 68, 57, 39, 46, ...

>   

閉じる