print original line numbers of extracted range with cat and sed - sed

I'm extracting lines 8 through 11 from a file (example.c),
and I want the lines to be numbered 8,9,10,11.
Here's what I tried, but (unsurprisingly) it gives me the line numbers
1,2,3,4. There's got to be a simple way around this, right?
$ sed -n '8,11p;12q' example.c | cat -n
1 x = 5;
2 y = 6;
3 z = 7;
4 w = 8;
And here's my example.c file for completeness:
$ cat -n example.c
1 int x;
2 int y;
3 int z;
4 int w;
5
6 int main()
7 {
8 x = 5;
9 y = 6;
10 z = 7;
11 w = 8;
12
13 return x+y+z+w;
14 }

Related

How to save multiple output in recursive function

Given a matrix A, I have to make all possible combinations of entries of A such that only one number is selected for each row. I have made a recursive program which is running successfully. But I am not able to save the output vector. So, for example in the following matrix A, there will be 27 such combinations, I want to save them in matrix of order 3x27.
A = [3 4 0; 2 3 7; 45 7 0]
n = 1;
X = zeros(3,1);
comb(n, X, A);
%function to calculate all combinations.
function X = comb(n, X, A)
if (n > 3)
X
return
end
for i = 1:3
X(n) = A(n, i);
comb(n + 1, X, A);
end
end
Here's one of the possible approaches:
To make your variable visible in all contexts, you need to declare a global variable:
global OUT;
%rest of the code
Then, you just define OUT in you main file as empty variable:
OUT = [];
And in function script, you instruct to append X to OUT whenever the if-statement is satisfied:
if (n > 3)
OUT = [OUT,X];
return
end
The resulting code is as follows:
global OUT;
OUT = [];
A = [3 4 0; 2 3 7; 45 7 0];
n = 1;
X = zeros(3,1);
comb_SO(n, X, A);
OUT
function X = comb_SO(n, X, A)
global OUT;
if (n > 3)
OUT = [OUT,X];
return
end
for i = 1:3
X(n) = A(n, i);
comb_SO(n + 1, X, A);
end
end
The sought result is in OUT variable:
3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 0
2 2 2 3 3 3 7 7 7 2 2 2 3 3 3 7 7 7 2 2 2 3 3 3 7 7 7
45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0 45 7 0
But, MATLAB functionality allows your goal to be achieved without any recursion:
A = [3 4 0; 2 3 7; 45 7 0];
OUT = combvec(A(1,:),A(2,:),A(3,:))
Or, even without combvec, for arbitrary size of A:
A = reshape(1:20,4,5);
[n,m] = size(A);
Q = repmat({1:m},n,1);
B = cell(n,1);
[B{:}] = ndgrid(Q{:})
tmp = [];
OUT = [];
for k = 1:n
tmp = [tmp,B{k}(:)];
OUT = [OUT;A(k,tmp(:,k))];
end
Hope, that helps

How to resize MATLAB matrix

If I have matrix size(mat)= X*Y*6
let call mat(:,:,1)=A
and mat(:,:,2)=B and so on
how do i rezise mat to X*Y*12
where
mat(:,:,1)=mat(:,:,2)= A
mat(:,:,3)=mat(:,:,4)=B
and so on
You can use the following syntax:
%defines input matrix (in your case it is already defined)
m = 500;
n = 400;
z = 6;
mat = rand(m,n,z);
%initialize output matrix
newMat = zeros(m,n,z*2);
%assign old matrix values into the new matrix
newMat(:,:,1:2:end) = mat;
newMat(:,:,2:2:end) = mat;
If you have Matlab 2015a or newer you can use repelem:
N = 2; %// number of times to repeat
result = repelem(mat, 1, 1, N); %// repeat N times along 3rd dim
For older Matlab versions you can do it manually as follows:
N = 2; %// number of times to repeat
ind = ceil(1/N:1/N:size(mat,3)); %// build index with repetitions
result = mat(:,:,ind); %// apply index along desired dim
Example:
>> %// Data
>> mat = randi(9,2,4,2)
mat(:,:,1) =
5 8 9 2
7 3 1 5
mat(:,:,2) =
5 7 1 1
1 8 8 2
>> %// First approach
>> N = 2;
>> result = repelem(mat, 1, 1, N)
result(:,:,1) =
5 8 9 2
7 3 1 5
result(:,:,2) =
5 8 9 2
7 3 1 5
result(:,:,3) =
5 7 1 1
1 8 8 2
result(:,:,4) =
5 7 1 1
1 8 8 2
>> %// Second approach
>> N = 2;
>> ind = ceil(1/N:1/N:size(mat,3));
>> result = mat(:,:,ind)
result(:,:,1) =
5 8 9 2
7 3 1 5
result(:,:,2) =
5 8 9 2
7 3 1 5
result(:,:,3) =
5 7 1 1
1 8 8 2
result(:,:,4) =
5 7 1 1
1 8 8 2

MATLAB compute length of an integer

I'm trying to compute the length of an integer.
For example:
a = 1.1234; b = 33; c = 100; d = -222;
e = lengthint([a,b,c,d])
Expected output:
e = 1 2 3 3
I tried using this:
e = max(ceil(log10(abs([a,b,c,d]))),1)
but this is the output:
e = 1 2 2 3
So there is a problem with numbers that are multiples of 10.
You can do something like this -
A = [a,b,c,d]
lens = floor(log10(abs(A)))+1
lens(lens<0) = 0 %// Assuming that 0.xx numbers to have zero lengths
Sample runs:
Case #1:
>> A = [0.00001234, 1.1234, 33, 10, -222];
>> lens = floor(log10(abs(A)))+1;
>> lens(lens<0) = 0
lens =
0 1 2 2 3
Case #2:
>> A = [-0.00001234, 1.1234 33, 10, -222, 0];
>> lens = floor(log10(abs(A)))+1;
>> lens(lens<0) = 0
lens =
0 1 2 2 3 0
Another option would be to convert them to strings and check the length:
cellfun(#(x)length(num2str(abs(fix(x)))),{a,b,c,d});
the only complication is that you need cells to keep your strings separate.
Output from #Divakar's example input:
>> a1 = 0.00001234; a2 = 1.1234; b = 33; c = 100; d = -222;
>> cellfun(#(x)length(num2str(abs(fix(x)))),{a1,a2,b,c,d})
ans =
1 1 2 3 3
so it will obviously not give 0 for the 1e-5 case.

Find and replace the rows of an array having repeated number by a fixed given row

I have a matrix having rows with repeated numbers. I want to find those rows and replace them with a dummy row so as to keep the number of rows of the matrix constant.
Dummy_row = [1 2 3]
(5x3) Matrix A
A = [2 3 6;
4 7 4;
8 7 2;
1 3 1;
7 8 2]
(5x3) Matrix new_A
new_A = [2 3 6;
1 2 3;
8 7 2;
1 2 3;
7 8 2]
I tried the following which deleted the rows having repeated numbers.
y = [1 2 3]
w = sort(A,2)
v = all(diff(t,1,2)~=0|w(:,1:2)==0,2) % When v is zero, the row has repeated numbers
z = A(w,:)
Can you please help?
bsxfun based solution -
%// Create a row mask of the elements that are to be edited
mask = any(sum(bsxfun(#eq,A,permute(A,[1 3 2])),2)>1,3);
%// Setup output variable and set to-be-edited rows as copies of [1 2 3]
new_A = A;
new_A(mask,:) = repmat(Dummy_row,sum(mask),1)
Code run -
A =
2 3 6
4 7 4
8 7 2
1 3 1
7 8 2
new_A =
2 3 6
1 2 3
8 7 2
1 2 3
7 8 2
You could use the following:
hasRepeatingNums = any(diff(sort(A, 2), 1, 2)==0, 2);
A(hasRepeatingNums,:) = repmat(Dummy_row, nnz(hasRepeatingNums), 1);
See if this works for you,
A= [ 2 3 6;
4 7 4;
8 7 2;
5 5 5;
1 8 8;
1 3 1;
7 8 2 ];
Dummy_row = [1 2 3];
b = diff(sort(A,2),1,2);
b = sum(b == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;
gives,
newA =
2 3 6
1 2 3
8 7 2
1 2 3
1 2 3
1 2 3
7 8 2
Edit
Not much change is needed, try this,
Dummy_row = [1 2 3];
b = sum(A == 0,2);
b = b > 0;
c = repmat(Dummy_row,sum(b),1);
b = b' .* (1:length(b));
b = b(b > 0);
newA = A;
newA(b,:) = c;

Expand matrix based on first row value (MATLAB)

My input is the following:
X = [1 1; 1 2; 1 3; 1 4; 2 5; 1 6; 2 7; 1 8];
X =
1 1
1 2
1 3
1 4
2 5
1 6
2 7
1 8
I am looking to output a new matrix based on the value of the first column. If the value is equal to 1 -- the output will remain the same, when the value is equal to 2 then I would like to output two of the values contained in the second row. Like this:
Y =
1
2
3
4
5
5
6
7
7
8
Where 5 is output two times because the value in the first column is 2 and the same for 7
Here it is (vectorized):
C = cumsum(X(:,1))
A(C) = X(:,2)
D = hankel(A)
D(D==0) = inf
Y = min(D)
Edit:
Had a small bug, now it works.
% untested code:
Y = []; % would be better to pre-allocate
for ii = 1:size(X,1)
Y = [Y; X(ii,2)*ones(X(ii,1),1)];
end