2015-05-31 2 views
0

Я не уверен, что я использовал для исправления формулировок в заголовке, чтобы описать проблему. Пожалуйста, не стесняйтесь редактировать его, чтобы отразить описание ниже.Назначение значений подматрице индексированной подматрицы в Matlab

Пусть у меня есть программа Sudoku Solver и позволяет сказать, что входной матрицы заключается в следующем,

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

индекс I 3х3 суб-матрицы coulumnwise от 1 до 9. Предположим, что переменная nSubMat представляя это индекс может принимать любые значения от 1 до 9.

I индекс подматрицы следующим образом,

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

Теперь я хочу получить доступ и изменить значение в позиции (2x3) SubMat, не создавая в первую очередь SubMat (скажем, чтобы избежать ненужных копий).

Разрабатывать, если бы я иметь функцию подматрицы(), которая будет осуществлять выше, мое заявление будет выглядеть примерно следующим,

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]; 

I знают, что интерпретатор Matlab автоматически оптимизирует LHS = назначения типа RHS для скорости, но работа над матрицей важна по многим причинам (с точки зрения алгоритма), чем просто сокращение копий и ускорение кода, который я не буду здесь останавливаться. Я видел требуемый синтаксис в библиотеке C++ под названием Armadillo, но я не уверен, что то же самое можно сделать с MATLAB.

+0

Вы нашли ответ полезный? Если да, то, пожалуйста, примите его, чтобы он вышел из списка без ответа. –

ответ

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 генерирует все возможные комбинации входных аргументов. Вы также можете использовать this, который быстрее, чем allcomb (в соответствии с ответом).

+0

Доступ к формату armadillo [submat views] (http://arma.sourceforge.net/docs.html#submat) - это то, что я искал, но нужно делать линейное индексирование. Кроме того, насколько эффективна allcomb() для больших квадратных матриц, более широкой области доступа или большого количества итераций в судоку? – Naveen

+0

Я думаю, что это будет довольно эффективно. Как я уже упоминал, вы также можете проверить альтернативу, которая, по-видимому, быстрее. –

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 
Смежные вопросы