Dividing a Square Matrix into Four Distinct Matrices Based on indexing element as well as the last digit

5 views (last 30 days)
Assuming I have a square matrix of N x N, example for 2x2 we can have A = [10902425 3040701; 36904080 304], where each cell contains a number with at least eight digits. I aim to generate four distinct square matrices from A, namely A1=[10 30;36 30], A2=[90 40;90 04], A3=[24 70;40 00], and A4=[25 01;80 00]. The division of pixels is based on pairs, and a new matrix is formed. If the last number of pixel is not in pair,the put 0 as the leading number to make pair and the rest of pixel position will be 00. in a simple way each number in each position is divided into pair for example 10902425 -> 10| 90| 24| 25 , but for 304 it should be 30| 04 instead of 40 this will make easy during the reversing process (in my view). I need a help on both forwarding process as well as reversing to the original matrix
close all;
clear;
clc;
% Given matrix A
A = [10902425 3040701; 36904080 304];
% Extract the digits from A
A_digits = mod(A, 10);
% Generate A1
A1 = floor(A/100);
% Generate A2
A2 = zeros(size(A));
A2(A_digits == 0 | A_digits == 1) = mod(A(A_digits == 0 | A_digits == 1), 100);
% Generate A3
A3 = zeros(size(A));
A3(A_digits == 2 | A_digits == 4) = mod(A(A_digits == 2 | A_digits == 4), 100);
% Generate A4
A4 = zeros(size(A));
A4(A_digits == 5 | A_digits == 6) = mod(A(A_digits == 5 | A_digits == 6), 100);
% Display the resulting matrices
this code produce error
  3 Comments
dani elias
dani elias on 16 Jun 2023
Edited: dani elias on 16 Jun 2023
Apologies for any lack of clarity in my previous responses plus question. I understand that there might have been some confusion in the beginning.
The objective is to ensure that each value in the matrix consists of 8 digits. If the digits in a value are not in pairs, a leading 0 is added to the last digit. If the digits are in pairs but the value has less than 8 digits, trailing 0s are added to the right side of the last digit until it reaches a total of 8 digits. Always the numbers are greater than 3 digits..
So far, I have successfully transformed the matrix A = [10902425 3040701; 36904080 304] into AA = [10902425 30407001; 36904080 30040000]. As a result, I obtained four separate matrices: A1 = [10 30; 36 30], A2 = [90 40; 90 4], A3 = [24 70; 40 00], and A4 = [25 01; 80 00]. This transformation was accomplished with the help of a specific method from @chicken vector. Now, I would like to reverse the process and convert A1, A2, A3, and A4 back to the original matrix, A. This is the codes:
A = [10902425 3040701; 36954080 285];
% Initialize the output matrix v with zeros
v = zeros(size(A));
for i = 1:size(A, 1)
for j = 1:size(A, 2)
num_str = num2str(A(i, j));
num_len = length(num_str);
% Check if any digit is not in pair
if mod(num_len, 2) ~= 0
% Add leading zero before the last number
num_str = strcat(num_str(1:end-1), '0', num_str(end));
end
% Check if the number of digits is less than eight
if num_len < 8
% Add trailing zeros to the right side
num_str = strcat(num_str, repmat('0', 1, 7 - num_len));
elseif num_len > 8
% Trim the string to eight digits
num_str = num_str(1:8);
end
% Convert the modified string back to a number and assign it to v
v(i, j) = str2num(num_str);
end
end
% Check if the last position has 8 digits
last_num_str = num2str(v(end));
last_num_len = length(last_num_str);
if last_num_len < 8
% Add trailing zeros to the last position
last_num_str = strcat(last_num_str, repmat('0', 1, 8 - last_num_len));
v(end) = str2num(last_num_str);
end
out = cellfun(@(x) reshape(x, 2, 4)', cellstr(string(v'.*10.^(8 - strlength(string(v'))))), 'UniformOutput', false);
out = cellfun(@(x) reshape(str2num(reshape(x, 2, 4)'),2,2)', cellstr([out{:}]), 'UniformOutput', false);
A1 = out{1};
A2 = out{2};
A3 = out{3};
A4 = out{4};

Sign in to comment.

Accepted Answer

chicken vector
chicken vector on 15 Jun 2023
Edited: chicken vector on 15 Jun 2023
This will give you what you are looking for, except for the inverted number in case of odd number of digits:
A = [10902425 3040701; 36904080 304];
out = cellfun(@(x) reshape(x, 2, 4)', cellstr(string(A'.*10.^(8 - strlength(string(A'))))), 'UniformOutput', false);
out = cellfun(@(x) reshape(str2num(reshape(x, 2, 4)'),2,2)', cellstr([out{:}]), 'UniformOutput', false);
EDIT:
This is what you asked for.
Be careful that we are using numbers so in the final output 04 or 00 become 4 and 0.
B = cellstr(string(A'.*10.^(8 - strlength(string(A'))) - rem(strlength(string(A')),2).*((A'./10 - floor(A'./10)).*10).*10.^(7 - strlength(string(A'))).*9));
out = cellfun(@(x) reshape(x, 2, 4)', B, 'UniformOutput', false);
out = cellfun(@(x) reshape(str2num(reshape(x, 2, 4)'),2,2)', cellstr([out{:}]), 'UniformOutput', false);
Output:
out{1}
ans = 2×2
10 30 36 30
out{2}
ans = 2×2
90 40 90 4
out{3}
ans = 2×2
24 70 40 0
out{4}
ans = 2×2
25 1 80 0
  5 Comments
chicken vector
chicken vector on 16 Jun 2023
Edited: chicken vector on 16 Jun 2023
As I said at the beginning:
"This will give you what you are looking for, except for the inverted number in case of odd number of digits:"
You can disregard the first method.
Actually the second method is the same with some additional manipulation of odd digits numbers.
A = [10902425 3040701; 36904080 304];
This add the trailing zeros to the number:
A'.*10.^(8 - strlength(string(A')))
ans = 2×2
10902425 36904080 30407010 30400000
This check what numbers have odd digits:
rem(strlength(string(A')),2)
ans = 2×2
0 0 1 1
This takes the last digit of every number:
((A'./10 - floor(A'./10)).*10)
ans = 2×2
5.0000 0 1.0000 4.0000
So together retain only the last digit of the odd digit numbers:
rem(strlength(string(A')),2).*((A'./10 - floor(A'./10)).*10)
ans = 2×2
0 0 1.0000 4.0000
This inverts the digit by substracting by 9:
10.^(7 - strlength(string(A'))).*9
ans = 2×2
1.0e+04 * 0.0001 0.0001 0.0009 9.0000
Example: to make 4000 become 400 you substract 10^3*(9*4))
where 4 is the last digit given by:
rem(strlength(string(A')),2).*((A'./10 - floor(A'./10)).*10);
And 10^3*9 is given by:
10.^(7 - strlength(string(A'))).*9;
The rest of the code is a series of 3 reshaping manipulations, 2 acting on char arrays and the last one on a matrix.
dani elias
dani elias on 16 Jun 2023
thank you once again for your help, I have tried to modified the code like this.
A = [10902425 3040701; 36954080 301];
% Initialize the output matrix v with zeros
v = zeros(size(A));
for i = 1:size(A, 1)
for j = 1:size(A, 2)
num_str = num2str(A(i, j));
num_len = length(num_str);
% Check if any digit is not in pair
if mod(num_len, 2) ~= 0
% Add leading zero before the last number
num_str = strcat(num_str(1:end-1), '0', num_str(end));
end
% Check if the number of digits is less than eight
if num_len < 8
% Add trailing zeros to the right side
num_str = strcat(num_str, repmat('0', 1, 7 - num_len));
elseif num_len > 8
% Trim the string to eight digits
num_str = num_str(1:8);
end
% Convert the modified string back to a number and assign it to v
v(i, j) = str2num(num_str);
end
end
% Check if the last position has 8 digits
last_num_str = num2str(v(end));
last_num_len = length(last_num_str);
if last_num_len < 8
% Add trailing zeros to the last position
last_num_str = strcat(last_num_str, repmat('0', 1, 8 - last_num_len));
v(end) = str2num(last_num_str);
end
% compare A and v
disp("A =");
disp(A);
disp("v =");
disp(v);
%from chicken vector-mathworks
out = cellfun(@(x) reshape(x, 2, 4)', cellstr(string(v'.*10.^(8 - strlength(string(v'))))), 'UniformOutput', false);
out = cellfun(@(x) reshape(str2num(reshape(x, 2, 4)'),2,2)', cellstr([out{:}]), 'UniformOutput', false);
A1 = out{1};
A2 = out{2};
A3 = out{3};
A4 = out{4};
disp(A1);
disp(A2);
disp(A3);
disp(A4);
outputs
A =
10902425 3040701
36954080 301
v =
10902425 30407001
36954080 30010000
A1 =
10 30
36 30
A2 =
90 40
95 1
A3 =
24 70
40 0
A4 =
25 1
80 0
now I need to convert it back to the original matrix either in form of "v" or "A"

Sign in to comment.

More Answers (1)

Stephen23
Stephen23 on 16 Jun 2023
Edited: Stephen23 on 16 Jun 2023
Simpler and more efficient.
My answer takes into account my comments here. Assumes no zero, negative, fractional, inf, etc. values.
format compact
A = [10902425,3040701;36904080,304]
A = 2×2
10902425 3040701 36904080 304
B = A.*10.^(8-fix(log10(A)))
B = 2×2
109024250 304070100 369040800 304000000
C = 10.^cat(3,7,5,3,1);
% A1=[10 30;36 30], A2=[90 40;90 04], A3=[24 70;40 00], A4=[25 01;80 00]
D = mod(fix(B./C),100)
D =
D(:,:,1) = 10 30 36 30 D(:,:,2) = 90 40 90 40 D(:,:,3) = 24 70 40 0 D(:,:,4) = 25 10 80 0
And back again:
E = sum(D.*C,3)
E = 2×2
109024250 304070100 369040800 304000000
  6 Comments
Stephen23
Stephen23 on 16 Jun 2023
"Your assistance in solving the question was invaluable. I truly appreciate your expertise and guidance."
@dani elias: you can show your appreciation by voting for answers that helped you.

Sign in to comment.

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!