2017-03-20 16 views
1

設定された変数数(たとえば1〜10)でRに行列を作成したいとします。それらの変数は、行と列にランダムに割り当てられるべきですが、どちらでも繰り返されるべきではありません(番号1は行1に1回、列1に1回)。例えばので固定値が列と行で繰り返されない

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

2,3,4,5,6,7,8,9 、10,1

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

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

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

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

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

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

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

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

しかし、もちろんのではその例では数字が昇順であり、それらをランダム化したいと考えています。私は単純な行列の要求を試みたが、私はこれを行う方法を理解することはできません。誰も助けることができますか?前もって感謝します!

+0

数独種類の行列のように見えますが、バックトラックアルゴリズムが必要です。 – Fernando

答えて

1

を、私は問題を誤解していない限り、このシャッフル行列を作成するための非常に簡単な方法がありますループや複雑な条件文も必要ありません。

# number of rows and columns 
n <- 10 

# create ordered rows and columns 
ordered.by.row <- matrix(1:n, n, n) 
ordered.by.col <- matrix(1:n, n, n, byrow = T) 

# offset the rows and columns relative to each other. 
# no row or column has a repeated value, but the values are still ordered 
offset <- (ordered.by.row + ordered.by.col) %% n + 1 

# shuffle the columns, then shuffle the rows, this produces a randomized matrix 
# 'shuffle.row' is the final, randomized matrix 
set.seed(1222) # change this to change randomization 
shuffle.col <- offset[,sample(1:n, n, replace = F)] 
shuffle.row <- shuffle.col[sample(1:n, n, replace = F), ] 

# verify solution 
any(apply(shuffle.row, 1, function(r)any(duplicated(r)))) # FALSE 
any(apply(shuffle.row, 2, function(r)any(duplicated(r)))) # FALSE 

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

シャッフリングはランダム化を維持しますか?これは確かにバックトラックよりはるかに高速です。 – Fernando

+0

はい。 2つの別々のステップでランダム化を実行することが重要です。最初に、各桁が各行と列に1回表示されているが、すべての桁が順番に並んでいる「順序付けられたソリューション」を作成します。列をランダム化すると、行の一意性の基準を満たします。次に、行をランダム化し、列の一意性を満たします。シャッフルされた行と列のインデックスは無作為に選択されますので、ランダム性は保持されます。 – jdobres

+0

これは完璧です!どうもありがとうございました! – shampoo

0

これはほぼSudokuグリッドを生成するようです。以下のコードはかなり速く動作しますが、いくつかのマイナーなRの最適化を行うことができます。

backtrack = function(n = 10){ 
    x = matrix(NA, ncol = n, nrow = n) 
    cells = list() 
    k = 1 
    for (i in 1:n){ 
    for (j in 1:n){ 
     cells[[k]] = sample(1:n) 
     k = k + 1 
    } 
    } 

    i = 0 
    while (i < n*n){ 
    candidates = cells[[i + 1]] 
    idx = sample(1:length(candidates), 1) 
    val = candidates[idx] 

    if (length(candidates) == 0){ 
     cells[[i + 1]] = sample(1:n) 
     i = i - 1 
     x[as.integer(i/n) + 1, i %% n + 1] = NA 
    } 
    else { 
     rr = as.integer(i/n) + 1 
     cc = i %% n + 1 
     if ((val %in% x[rr, ]) || (val %in% x[, cc])){ 
     candidates = candidates[-idx] 
     cells[[i + 1]] = candidates 
     } 
     else{ 
     x[as.integer(i/n) + 1, i %% n + 1] = val 
     candidates = candidates[-idx] 
     cells[[i + 1]] = candidates 
     i = i + 1 
     } 
    } 
    } 
    x 
} 

テスト:

set.seed(1) # Please change this 
x = backtrack(10) 
print(x) 

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


any(apply(x, 1, function(r)any(duplicated(r)))) # FALSE 
any(apply(x, 2, function(r)any(duplicated(r)))) # FALSE 
+0

うわー!そんなにありがとう、@フェルナンド!これはまさに私が必要なものです(あなたがしたことを本当に理解するにはしばらく時間がかかるでしょうが))!! – shampoo

+0

ようこそ。これはバックトラッキングのアルゴリズムです:https://en.wikipedia.org/wiki/Backtracking – Fernando

+0

あなたは答えを受け入れるか、より多くの人々の入力を待つことができます。通常は少し待つべきですが、この場合はバックトラック以外の解決方法はありません。 – Fernando

関連する問題