在 Matlab 中为索引 sub-matrix 的 sub-matrix 赋值
Assigning values to a sub-matrix of a indexed sub-matrix in Matlab
我不确定我是否习惯于更正标题中的措辞来描述问题。请随时对其进行编辑以反映下面的描述。
假设我有一个数独求解器程序,假设输入矩阵如下,
A = randi(10,[9,9])-1;
我将 3x3 sub-matrices 按列从 1 到 9 进行索引。假设表示该索引的变量 nSubMat 可以取 1 到 9 之间的任何值。
我按以下方式索引子矩阵,
SubMat(nSubMat) = A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3)));
现在,我想访问和修改 SubMat 的 (2x3) 位置的值,而不必首先创建 SubMat(比如避免不必要的副本)。
具体来说,如果我有一个函数 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 完成同样的操作。
您可以使用简单的线性索引来做到这一点。以下代码不言自明。
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
generates all possible combinations of the input arguments. You can also use this 比 allcomb
快(根据答案)。
这是适用于任何大小的数独游戏的通用函数。
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
我不确定我是否习惯于更正标题中的措辞来描述问题。请随时对其进行编辑以反映下面的描述。
假设我有一个数独求解器程序,假设输入矩阵如下,
A = randi(10,[9,9])-1;
我将 3x3 sub-matrices 按列从 1 到 9 进行索引。假设表示该索引的变量 nSubMat 可以取 1 到 9 之间的任何值。
我按以下方式索引子矩阵,
SubMat(nSubMat) = A((1:3)+(3*floor((nSubMat-1)/3)),(1:3)+(3*mod(nSubMat-1,3)));
现在,我想访问和修改 SubMat 的 (2x3) 位置的值,而不必首先创建 SubMat(比如避免不必要的副本)。
具体来说,如果我有一个函数 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 完成同样的操作。
您可以使用简单的线性索引来做到这一点。以下代码不言自明。
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
generates all possible combinations of the input arguments. You can also use this 比 allcomb
快(根据答案)。
这是适用于任何大小的数独游戏的通用函数。
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