0

問題を説明するためにタイトルの文言を修正したかどうかはわかりません。以下の説明を反映するように自由に編集してください。

数独ソルバー プログラムがあり、入力行列が次のようになっているとします。

A = randi(10,[9,9])-1;

3x3 サブマトリックスに列ごとに 1 から 9 までのインデックスを付けます。このインデックスを表す変数nSubMatは、1 から 9 までの任意の値を取ることができるとします。

次の方法で部分行列にインデックスを付けます。

SubMat(nSubMat) = A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3)));

ここで、最初に SubMat を作成する必要なく (不要なコピーを避けるために)、SubMat の (2x3) 位置の値にアクセスして変更したいと考えています。

詳しく説明すると、上記を実装する関数 submatrix() がある場合、ステートメントは次のようになります。

submatrix(A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3))),[2,3]) = 5;

あるいは、

submatrix(A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3))),[2:3,2:3]) = [1 2;3 4];

Matlab インタープリターが速度のために LHS=RHS 型の割り当てを自動的に最適化することは知っていますが、上記の行列演算は、コピーを減らしてコードを高速化するだけでなく、ここでは詳しく説明しませんが、(アルゴリズム的に) より多くの理由で重要です。Armadillo という C++ ライブラリで必要な構文を見たことがありますが、MATLAB で同じことができるかどうかはわかりません。

4

2 に答える 2

1

これは、単純な線形インデックスを使用して行うことができます。次のコードは一目瞭然です。

matrixRows=9;
matrixCols=9;
blockRows=3;
blockCols=3;
accessRow=2;
accessCol=3;

A = randi(10,[matrixRows,matrixCols])-1;
allPos=allcomb(accessRow:blockRows:matrixRows,accessCol:blockCols:matrixCols);
linPos=sub2ind(size(A),allPos(:,1),allPos(:,2));

% access them as usual and put any value
A(linPos)=-100;

結果:

A =

 8     9     7     3     6     4     1     6     8
 9     1     9     6     3     4     4     8     2
 1     9     6     1     9     6     9     9     9
 9     9     0     7     0     7     3     5     3
 6     4     8     0     4     7     5     1     1
 0     8     9     2     3     2     2     1     2
 2     1     6     0     7     6     7     2     6
 5     4     7     0     7     6     2     8     4
 9     9     7     8     1     1     5     2     3

上記のコードを実行した後:

A =

 8     9     7     3     6     4     1     6     8
 9     1  -100     6     3  -100     4     8  -100
 1     9     6     1     9     6     9     9     9
 9     9     0     7     0     7     3     5     3
 6     4  -100     0     4  -100     5     1  -100
 0     8     9     2     3     2     2     1     2
 2     1     6     0     7     6     7     2     6
 5     4  -100     0     7  -100     2     8  -100
 9     9     7     8     1     1     5     2     3

注:allcomb入力引数のすべての可能な組み合わせを生成します。(回答によると)よりも高速なこれを使用することもできます。allcomb

于 2015-05-31T03:57:35.497 に答える
1

これは、任意のサイズの数独パズルの一般的な機能です。

function index = SudukoIndex(varargin)
%%%SudukoIndex provides the index or indicies of a sub-block of any n*n
%%%Suduko puzzle

%Possible inputs
%   One (1) number (i) between 1 and n will provide a sqrt(n) * sqrt(n) set of
%      indicies from the i-th block. Note this is counted using Matlab
%      syntax going from top to bottom then left to right, a simple check
%      for this can be found by typing the command 'reshape(1:n, sqrt(n),
%      sqrt(n))' into the command window.
%   Two (2) numbers between 1 and n will provide the single number index of
%       the row, column combination
%   Three (3) numbers the first (i) between 1 and n and the second (j) and 
%       third (k) between 1 and sqrt(n) will provide the index of the (j,k)
%       point in the i-th cell
n = 9;

if nargin == 1
    sM = varargin{1};
    majorColumn = floor((sM-1)/sqrt(n)) + 1;
    majorRow = mod(sM-1, sqrt(n)) + 1;

    x = (1:sqrt(n))';
    y = (1:n:n^1.5);
    [x, y] = meshgrid(x, y);
    m = (x + y - 1)';

    index = (n^1.5)*(majorColumn - 1) + sqrt(n)*(majorRow - 1) + m;
elseif nargin == 2
    index = n*(varargin{2} - 1) + varargin{1};
elseif nargin == 3
    m = nsm(varargin{1});
    index = m(varargin{2}, varargin{3});
end
end
于 2015-05-31T04:57:33.353 に答える