The program that I would like to write has the same aim of the File row confrontation. This time the file I have is put in a different way:
1 2
1 3
1 4
2 1
2 3
2 4
2 5
3 1
...
8 6
8 7
8 9
9 8
I want to find:
when the first element of a row appears in the second position of the other rows and if the first element of the subsequent rows appear alongside the row taken in exam;
if it found then I want to print "I have found the link x y";
if the "link" exists, then I want to count how many "neighbours" they share, where by eighbours I mean how many elements in the second column they have in common and print "I found z triangles".
The file is sorted.
In this case the program will start founding the first "couple" 1 2 in the file but reversed and it will find it at the 4th row (2 1). Then it looks if the 3 ( second row and neighbour of 1) is also present in 2 ( and it is the case because it exists 2 3) and so on. At the end it will found that the "there is the link 1 2" and it "found 2 triangles" (1 - 2 - 3 and 1 - 2 - 4). I think the answer sould not be so different from the answer in the upper link, but I don't know how to arrange the files from a file made like this.
The first part of the problem is to find only the index of the inverted matching pairs? While reading this problem yesterday I had the feeling that grep may be of use;
#!usr/bin/perl
use warnings;
use strict;
my #parry;
while (<DATA>){
push #parry, [split(' ',$_)];
}
##remind is reverse matched indices;
my #remind = grep {
my $ind = $_;
grep { #reverse #{$parry[$_]} == #{parry[$ind]} did not appear to work.
#{$parry[$_]}[0] == #{$parry[$ind]}[1] &&
#{$parry[$_]}[1] == #{$parry[$ind]}[0];
} 0..$#parry
} 0..$#parry;
grep { print $_,': ',#{$parry[$_]},$/ } #remind;
__END__
1 2
1 3
1 4
2 1
2 3
2 4
2 5
3 1
8 6
8 7
8 9
9 8
output is
0: 12
1: 13
3: 21
7: 31
10: 89
11: 98
from here you then want to find say for
7[0] 7[1] (3 1) with neighbour row 6 and 8 with col 2?
6[1]
7[1] (1 5) and/or
7[1] (1 6) exist in the original set (in #parry)?
8[1]
Which they do not so no triangle.
Related
I am trying to add the elements of one list to another with the desired output as seen below.
I've attempted joining the lists with the , operator but this does not create the desired results:
q)l1: (1 2 3; 5 6 7)
q)l2: (4 8)
q)l1,l2
(1 2 3; 5 6 7;4;8)
Desired result: (1 2 3 4; 5 6 7 8)
I'm wondering if there's any built-in ability to do this in q as my understanding is that having to iterate through these vectors would be inefficient in q.
You can achieve it by doing the following which will join each element of the left with each element of the right
q)l1: (1 2 3; 5 6 7)
q)l2:(4 8)
q)l1,'l2
1 2 3 4
5 6 7 8
I have a number of text files with data, and want to read a specific part of each file (time information), which is always located at the end of the first row of each file. Here's an example:
%termo2, 30-Jan-2016 12:27:20
I.e. I would like to get "12:27:20".
I've tried using textscan, which I have used before for similar problems. I figured there are 3 columns of this row, with single white space as delimiter.
I first tried to specify these as strings (%s):
fid = fopen(fname);
time = textscan(fid,'%s %s %s');
I also tried to specify the date and time using datetime format:
time = textscan(fid,'%s %{dd-MMM-yyyy}D %{HH:mm:ss}D')
Both of these just produce a blank cell. (I've also tried a number of variations, such as defining the delimiter as ' ', with the same result)
Thanks for any help!
Here's the entire file (not sure pasting here is the right way to do this - i'm new to both matlab and stackoverflow..):
%termo2, 30-Jan-2016 12:27:20
%
%102
%
%stimkod stimtyp
% 1 Next:Pain
% 2 Next:Brush
% vaskod text
% 1 Obeh -> Beh
% 2 Inte alls intensiv -> Mycket intensiv
% stimnr starttid stimkod vaskod VASstart VASmark VAS
1 78.470 2 1 96.470 100.708 6.912
1 78.470 2 2 96.470 104.739 2.763
2 138.822 1 2 156.821 162.619 7.615
2 138.822 1 1 156.821 166.659 2.496
3 199.117 2 2 217.116 222.978 2.897
3 199.117 2 1 217.116 224.795 5.773
4 258.612 2 1 276.612 280.419 5.395
4 258.612 2 2 276.612 284.145 4.622
5 320.068 1 1 338.068 340.689 4.396
5 320.068 1 2 338.068 346.090 2.722
6 377.348 1 2 395.347 398.809 6.336
6 377.348 1 1 395.347 404.465 3.391
7 443.707 2 1 461.707 464.840 6.604
7 443.707 2 2 461.707 473.703 3.652
8 503.122 1 2 521.122 526.009 4.285
8 503.122 1 1 521.122 529.808 3.646
9 568.546 2 2 586.546 586.546 5.000
9 568.546 2 1 586.546 595.496 6.412
10 629.953 2 1 647.953 650.304 7.034
10 629.953 2 2 647.953 655.600 6.615
11 694.305 1 1 712.305 714.416 4.669
11 694.305 1 2 712.305 721.079 2.478
12 751.537 2 2 769.537 773.511 7.307
12 751.537 2 1 769.537 777.423 8.225
13 813.944 1 2 831.944 834.958 7.731
13 813.944 1 1 831.944 839.255 1.363
14 872.448 2 1 890.448 893.829 6.813
14 872.448 2 2 890.448 899.439 2.600
15 939.880 1 2 957.880 963.811 4.332
15 939.880 1 1 957.880 966.603 2.786
16 998.328 2 1 1016.327 1020.707 5.837
16 998.328 2 2 1016.327 1025.275 2.664
17 1062.911 1 2 1080.910 1082.967 2.792
17 1062.911 1 1 1080.910 1088.674 4.094
18 1125.182 1 1 1143.182 1144.379 0.619
18 1125.182 1 2 1143.182 1151.786 8.992
If you're not reading in the entire file, you could just read the first line using fgetl, split on the strings (using regexp) and then grab the last element.
parts = regexp(fgetl(fid), '\s+', 'split');
last = parts{end};
That being said, there doesn't seem to be anything wrong with the way you're using textscan if your file is actually how you say. You could alternately do something like:
parts = textscan(fid, '%s', 3);
last = parts{end}
Update
Also, be sure to rewind the file pointer using frewind before trying to parse the file to ensure that it starts at the top of the file.
frewind(fid)
If I am to split a list into 2 rows, I can use:
q)2 0N#til 10
However, the following syntax does not work:
q)n:2
q)n 0N#til 10
how I can achieve such reshaping?
Need brackets and semi colon
q)2 0N#til 10
0 1 2 3 4
5 6 7 8 9
q)n:2
q)(n;0N)#til 10
0 1 2 3 4
5 6 7 8 9
Here is the general syntax to split a list in matrix form:
(list1)#(list2)
As you can see, left part and right part of '#' is list. So here is one example:
q)list1: (4;3) / or simply (4 3)
q)list2: til 12
q)list1#list2
We can make an integer list in 2 way:
Using semicolon as list1:(2;3;4)
Using spaces as list1:(2 3 4)
But when you have variable, option 2 doesn't work;
q)list1: (n 3) / where n:2
q) `type error
So for your question, solution is to use semicolon to create list:
q) list1:(n;0N)
q) list1#til 10
How do I change the list of value to all 1? I need the top right to bottom left also end up with 1.
rc = input('Please enter a value for rc: ');
mat = ones(rc,rc);
for i = 1:rc
for j = 1:rc
mat(i,j) = (i-1)+(j-1);
end
end
final = mat
final(diag(final)) = 1 % this won't work?
Code for the original problem -
final(1:size(final,1)+1:end)=1
Explanation: As an example consider a 5x5 final matrix, the diagonal elements would have indices as (1,1), (2,2) .. (5,5). Convert these to linear indices - 1, 7 and so on till the very last element, which is exactly what 1:size(final,1)+1:end gets us.
Edit : If you would like to set the diagonal(from top right to bottom left elements) as 1, one approach would be -
final(fliplr(eye(size(final)))==1)=1
Explanation: In this case as well we can use linear indexing, but just for more readability and maybe a little fun, we can use logical indexing with a proper mask, which is being created with fliplr(eye(size(final)))==1.
But, if you care about performance, you can use linear indexing here as well, like this -
final(sub2ind(size(final),1:size(final,1),size(final,2):-1:1))=1
Explanation: Here we are creating the linear indices with the rows and columns indices of the elements to be set. The rows here would be - 1:size(final,1) and columns are size(final,2):-1:1. We feed these two to sub2ind to get us the linear indices that we can use to index into final and set them to 1.
If you would to squeeze out the max performance here, go with this raw version of sub2ind -
final([size(final,2)-1:-1:0]*size(final,1) + [1:size(final,1)])=1
All of the approaches specified so far are great methods for doing what you're asking.
However, I'd like to provide another viewpoint and something that I've noticed in your code, as well as an interesting property of this matrix that may or may not have been noticed. All of the anti-diagonal values in your matrix have values equal to rc - 1.
As such, if you want to set all of the anti-diagonal values to 1, you can cheat and simply find those values equal to rc-1 and set these to 1. In other words:
final(final == rc-1) = 1;
Minor note on efficiency
As a means of efficiency, you can do the same thing your two for loops are doing when constructing mat by using the hankel command:
mat = hankel(0:rc-1,rc-1:2*(rc-1))
How hankel works in this case is that the first row of the matrix is specified by the vector of 0:rc-1. After, each row that follows incrementally shifts values to the left and adds an increasing value of 1 to the right. This keeps going until you encounter the vector seen in the second argument, and at this point we stop. In other words, if we did:
mat = hankel(0:3,3:6)
This is what we get:
mat =
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
Therefore, by specifying rc = 5, this is the matrix I get with hankel, which is identical to what your code produces (before setting the anti-diagonal to 1):
mat =
0 1 2 3 4
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
Tying it all together
With hankel and the cheat that I mentioned, we can compute what you are asking in three lines of code - with the first line of code asking for the dimensions of the matrix:
rc = input('Please enter a value for rc: ');
mat = hankel(0:rc-1, rc-1:2*(rc-1));
mat(mat == rc-1) = 1;
mat contains your final matrix. Therefore, with rc = 5, this is the matrix I get:
mat =
0 1 2 3 1
1 2 3 1 5
2 3 1 5 6
3 1 5 6 7
1 5 6 7 8
Here's a simple method where I just add/subtract the appropriate matrices to end up with the right thing:
final=mat-diag(diag(mat-1))+fliplr(diag([2-rc zeros(1,rc-2) 2-rc]))
Here is one way to do it:
Say we have a the square matrix:
a = ones(5, 5)*5
a =
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
5 5 5 5 5
You can remove the diagonal, then create a diagonal list of ones to replace it:
a = a - fliplr(diag(diag(fliplr(a)))) + fliplr(diag(ones(length(a), 1)))
a =
5 5 5 5 1
5 5 5 1 5
5 5 1 5 5
5 1 5 5 5
1 5 5 5 5
The diag(ones(length(a), 1)) can be any vector, ie. 1->5:
a = a - fliplr(diag(diag(fliplr(a)))) + fliplr(diag(1:length(a)))
a =
5 5 5 5 1
5 5 5 2 5
5 5 3 5 5
5 4 5 5 5
5 5 5 5 5
I have a two column matrix of the following form:
1. 1 1
2. 1 1
3. 1 2
4. 1 2
5. 2 2
6. 2 2
7. 3 2
8. 3 2
9. 3 3
10. 4 3
11. 4 4
I would like to sample a single number from the first column using say randsample().
Let's say the results is 2.
What I would like to know is which ROW was the sample taken from? (in this case it could have been sampled both from row 5 or row 6)
Is this possible?
It's easy with find and ==:
>> A = [
1 1
1 1
1 2
1 2
2 2
2 2
3 2
3 2
3 3
4 3
4 4];
>> R = randsample(4,1)
>> find(A(:,1) == R)
R =
4
ans =
10
11
Or, as indicated by igor milla,
>> I = randi(11)
>> A(I, :)
I =
9
ans =
3 3
If you just need to sample one value, the solution as given by #igor milla is fine. But if you want to use the options given by randsample then I would recommend you to sample the column numbers rather than the sample directly.
A = rand(11,2); %suppose this is your matrix
k = 1; %This is the size of your desired sample
mysampleid = randsample(size(A,1),k)
mysample = A(mysampleid,:)
Now mysampleid contains the numbers of the columns, and mysample contains the rows that you sampled.
If you just want to sample the first column you can use A(mysampleid,1) instead.