LoginSignup
7
9

More than 5 years have passed since last update.

全要素が移動する(同じ位置に残らない)shuffle

Last updated at Posted at 2017-08-15

8/25追記

最終版??
http://qiita.com/ttatsf/items/d4543ccc80e0fbe3891d#comment-3eccf9c112d73c505bc2

8/23追記

下記のプログラムだと全てのshuffleパターンが網羅されていない,という指摘がありました.
[0,1,2,3] → [1,0,3,2] のような奇遇交換の例.

利用にあたってはご注意ください.

8/21追記

最終的に2行になった模様(白目)

def shuffle_all_move(items):
    rand_ord = random.sample(range(len(items)), k=len(items))
    return [items[r] for i, r in sorted(zip(rand_ord, rand_ord[1:]+rand_ord[:1]))]

実行速度も僅かに上のコードの方がわずかに速いようです(コメント欄に計測結果を載せています)


8/19追記

コメント欄にある,ttatsfさんが作ってくださったものが一番気に入っています.
(ベースにある「サットロのアルゴリズム」は7of9さんに紹介頂きました)
他にもコメントでコードを書いてくださった皆様,ありがとうございました.

import random

def shuffle_all_move( items ):
  length = len( items )
  res = [ 0 ] * length
  rand_ord = random.sample( range( length ), k=length )
  for i in range(  length  ) :
    res[ rand_ord[ i ] ] = items[ rand_ord[ ( i + 1 ) % length ] ]
  return res

実にエレガント!
…というわけで,下の適当なDIY shuffleより上記を利用することをおススメしたいw


元の投稿

絶対に要素が移動するようなshuffleのpython+numpy実装です(配列の要素が3以上であることを仮定しているので注意).
手順
1. ランダムに要素を3グループに分割
2. グループ毎にshuffle
3. グループを1つスライドさせる.

1のランダムなグループ分割は,実際にはshuffleしてから配列を3つに分割することで実現.shuffleされた配列のグループをスライドさせても,元の配列の位置とは無関係になってしまうので,後でこのshuffleを元に戻す.これにより,元の配列と必ず違う位置に移動することが保障される.

このコードでは,下記の2つのページにあるコードを借用しています.
※ resettable_shuffle/reset_shuffle
http://qiita.com/EafT/items/9527cb30409b70106fd4
※ divide_list
http://fits.hatenablog.com/entry/2015/11/09/211012

def shuffle_all_move(_array):
    array = _array.copy()
    seed = random.randint(0,np.iinfo(np.int32).max)
    resettable_shuffle(array,seed)
    array = divide_list(array,3)
    if type(array[0]) == list:
        array = array[-1] + array[0] + array[1]
    else:
        array = np.vstack((array[-1], array[0],array[1]))
    return reset_shuffle(array,seed)

実行例

test_array = ['a','b','c','d','e','f']
print(test_array)
test_array = shuffle_all_move(test_array)
print(test_array)

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

7
9
17

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
7
9