Swift extra trailing newline when reading file - swift

I am making an app where my levels are stored as grids of numbers in a text file, and when reading them in, I keep getting a trailing newline when there isn't one. The content of the text file being read in is the following (note there is no trailing newline, the last line just ends). Ignore the tick marks, they are there for clarity to mark the beginning and end of the file content.
'1 1 0 0
1 0 0 0
0 0 0 0
0 0 0 0'
My code:
let mypath = Bundle.main.path(forResource:"level1", ofType:nil)!
let content = try! String(contentsOfFile:mypath)
let lines:[String] = content.components(separatedBy:"\n")
print("lines=\(lines)")
print("content = '\(content)'")
Output:
lines=["1 1 0 0", "1 0 0 0", "0 0 0 0", "0 0 0 0", ""]
content = '1 1 0 0
1 0 0 0
0 0 0 0
0 0 0 0
'
As you can see, there is a fifth array element, implying that there were four "\n" strings found in the file, when there were only three. Plus the value of content has an extra newline at the end.
Now if I add a trailing newline to the file such that the file content is (everything between the tick marks):
'1 1 0 0
1 0 0 0
0 0 0 0
0 0 0 0
'
The output becomes:
lines=["1 1 0 0", "1 0 0 0", "0 0 0 0", "0 0 0 0", ""]
content = '1 1 0 0
1 0 0 0
0 0 0 0
0 0 0 0
'
It's the exact same as before!
If I add two trailing newlines, then the output accounts for it, becoming
lines=["1 1 0 0", "1 0 0 0", "0 0 0 0", "0 0 0 0", "", ""]
content = '1 1 0 0
1 0 0 0
0 0 0 0
0 0 0 0
'
Why is this? Is it a bug? Is there any way I can turn this "feature" off? I need to count the number of lines, and this is throwing off everything. I know I can trim off all the extra newlines, but that just seems like a patch to avoid the problem rather than a fix to the problem itself.

Related

matlab - too many loops finding paths array from Adjacency

Like the title says I would like to make the code faster and easier to read.
I have an Adjacency matrix:
Ad=[ 0 1 0 0 1 0 0 0 0 0;
1 0 0 0 0 0 0 0 0 0;
1 0 0 1 1 0 0 0 0 0;
0 0 1 0 0 1 0 0 0 0;
1 0 1 0 0 1 0 0 0 0;
0 0 0 1 1 0 0 0 0 0;
0 0 0 0 0 0 0 1 1 0;
0 0 0 0 0 0 1 0 0 1;
0 0 0 0 0 0 1 0 0 1;
0 0 0 0 0 0 0 1 1 0];
and a Name={'a';'b';'c';'d';'E';'F';'a';'E';'d';'F'}; that I will use for describing a type of "planet".
After finding out some new words from past comments from deleted questions, I could come up with a start:
dig=digraph(Ad, Name);
[Num.Nodes,Num.Null]=size(dig.Nodes);
for j2=1:Num.Nodes
dfs{j2}=dfsearch(dig,(j2),'allevents');
Num.node2path=dfs{j2}.Node;
Num.tokeep = ~isnan(Num.node2path);
Num.node2path = Num.node2path(Num.tokeep);
Num.node2path(1)=[];
[Num.node2path2,Num.Null]=size(Num.node2path);
for i2=1:Num.node2path2-1
if Num.node2path(i2)==Num.node2path(i2+1)
path{j2,i2}=Num.node2path(1:i2);Num.node2path(i2)=1000;Num.node2path(i2+1)=1001;
if Num.node2path(i2-1)==Num.node2path(i2+2)
Num.node2path(i2-1)=1002;Num.node2path(i2+2)=1003;
end
end
end
end
path = path(~cellfun('isempty',path));
[Num.clear1000,Num.degeaba] = size(path);
for i3=1:Num.clear1000
Num.is1000 = find(path{i3}(:) == 1000);
path{i3}(Num.is1000)=[];
Num.is1000 = find(path{i3}(:) == 1001);
path{i3}(Num.is1000)=[];
Num.is1000 = find(path{i3}(:) == 1002);
path{i3}(Num.is1000)=[];
Num.is1000 = find(path{i3}(:) == 1003);
path{i3}(Num.is1000)=[];
end
The thing is I feel it is getting too complicated with too many loops and I haven't even got to having the result I wanted. For example the path between '2' and '6' would be [2;1;5;3;4;6] and could be found with some more loops looking for path{i4}(1); equal to 2 and path{i4}(end); equal to 6, i4 being 10.
So after finding all paths I would like to rename the paths using Name, since I assign the same name to the same kind of "planet". Next I will choose the shortest path to the "best planet".
The paths being now in the form of [a;E;d] are compared to paths of Ad2 and Name2. Paths with the same Name are going to be saved and compared if they have similar distances from the first "planet" to the last one, just like the one that started the search. I quote "planets" because they may be stars, asteroids, and even these are categorized so this is where Name is coming from.

MATLAB - Get rid of leading zeros in each row of matrix, 1 at a time?

I want to get rid of leading zeros in each row of a matrix, but limit it to eliminating one zero at a time.
This is my current solution, but is there a simpler way of doing it?
a = [ 0 0 0 0 0 0 0 0 0 0
0 0 5 2 3 4 0 0 0 0
0 0 0 1 2 3 4 0 0 0
0 0 1 2 3 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 ]
b=zeros(size(a));
for j=1:size(a,2)
for i=1:size(a,1)
temp=find(a(i,:),1,'first');
candelete=min(2,temp);
b(i,1:end-candelete+1)=a(i,candelete:end);
end
a=b
end
EDIT:
I'm want to print every iteration, so that the first output will only have the first leading zero removed:
0 0 0 0 0 0 0 0 0 0
0 5 2 3 4 0 0 0 0 0
0 0 1 2 3 4 0 0 0 0
0 1 2 3 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
the second will have 2 zeros removed, and so on...
EDIT: Now that the question was clarified, here's a better answer using circshift:
index = (a(:, 1) == 0) & any(a, 2);
while any(index)
a(index, :) = circshift(a(index, :), -1, 2);
disp(a);
index = (a(:, 1) == 0) & index;
end

Search a position of pattern in a cell array

I have a cell array as below which contains 17000 such combinations.
'0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1'
'0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0'
'0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0'
'0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0'
'0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0'
'0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1'
'0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0'
'0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0'
I want to search the patterns in an array in a loop. I am interested in the position of that pattern in the cell array using Matlab. I had tried strcmp() function for comparison but it takes lots of time as each pattern is compared with 17000 elements of the cell array.
Is there any fastest method to search a pattern in cell array?
Use bin2dec to convert all entries in the cell array to integers, then convert the search pattern to int as well and search for ints

Print between patterns -awk

I have the following input file
-------------------------------------
--- A-TKE spectrum (post-neutron)---
-------------------------------------
2-dim. array: (A = 73 To 162 Step 1) (E = 122 To 198 Step 1)
(The data are written according to the loop structure specified above.
The last loop is the inner-most one. Line breaks are not related to the data structure!
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 2 0 0 1 0 0 0 0
</A_TKE>
</Results>
This file is part of a bigger file, which contains more number block similar to the above one.
What I want to do is print in a seperate file the numbers that are within the file. As a first try, I thought "Let's print what is between two patters". The START pattern will be --- A-TKE spectrum (post-neutron)--- and the END pattern will </A_TKE>
I used
awk '/--- A-TKE spectrum (post-neutron)---/{flag=1;next}/</A_TKE>/{flag=0}flag{print}' input
To my surprise nothing is printed on the screen. Any idea on why is this happening?
I would also like to now if I can substitue next with a number that will correspond to the line that I want to print after the given pattern.
In perl (because whilst you start with awk, this is tagged as perl too):
perl -ne 'print if m/post-neutron/...m/A_TKE/' input
Which will do what your thingy was trying to.
It works by using the range operator - which is a perl construct which tests if the current file is between two markers.
And the fact that perl can run inline in the same way as awk or sed. -ne says "wrap this code in a while loop" that iterates a line at a time. (e.g. as sed/awk/grep do by default).
Otherwise ... it depends a little on what else is in your file. Because from the sample you gave - the only lines starting with a number are the ones you want. So:
perl -ne 'print if m/^\s*\d+\s*\d+/'
(Or combine the two tests:
perl -ne 'print if m/post-neutron/...m/A_TKE/ and m/^\s*\d+\s*\d+/'
Which will output anything between the two text markers that has number-space-number at the start of line.
Your awk script is almost there. I'd build it like this:
awk '
/<\/A_TKE>/ {exit}
flag && NF==50 {print}
/--- A-TKE spectrum .post-neutron.---/ {flag=1}
' input
You could optimize it of course, but just looking at the logic of it, the idea is that you need do no further processing once you hit your end marker .. and you only want to start printing AFTER your start marker.
Note that I've replaced the brackets in your start marker with dots, since brackets are interpreted as PART OF THE REGULAR EXPRESSION. I believe you may be considering these simple strings to search for, but they are regex.
Some working ideas
Awk can print between two matching lines with this simple command:
awk '/PATTERN1/,/PATTERN2/' file.txt
If you want more control over what happens when the lines are found, you can use the flag approach.
awk '/A-TKE/{f=1;for (i=0;i<7;i++){getline}}/A_TKE/{f=0}f' file.txt
Adjust i<7 to specify how many lines you would like to skip.
Also, in this particular case, you can exploit the fact that you have 50 fields of numbers, which is unlikely to occur anywhere else in the file. Thus, you could also get the numbers of interest out with:
awk 'NF>40' file.txt
NF is a special awk variable that stores the number of fields (columns) in the current record (line).
Why your approach does not work
Your approach does not work, because everything that is between // in awk is treated as a regular expression. In your case you have several - and () in the string, which are not escaped, and thus assume their special meaning and therefore the expression you typed never matches, thus the flag is never set to 1 and awk does not print a line.
Try this simple sed command
sed -n '/A-TKE/,/<\/A_TKE>/p' FileName
If you want to extract rows with just numbers
awk 'NF && !/[a-zA-Z\-]+/' input.file
will generate
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 2 0 0 1 0 0 0 0
with patterns and smart counters you can write it as
awk '/\/A_TKE/{exit}
f&&s&&s--{next}
f&&NF{print}
/A-TKE spectrum/{f=1;s=7}' input.file
fine tune patterns as you like.

Check whether unit cell forms a "whole piece" in MATLAB?

I wish to check whether a square unit cell, when repeated side by side, forms a valid "whole piece" or not. I am sorry that I may not have described it in an accurate way, but I really do not know how to say this using scientific terms. Let me give you two examples, one for "whole piece" and the other for "not whole piece".
1 represents rubber, and 0 represents air.
"whole piece"
0 0 1 0 0 0
0 0 1 0 0 0
1 1 1 0 1 1
0 0 1 1 1 0
0 0 1 0 0 0
0 0 1 0 0 0
"not whole piece"
0 0 1 0 0 0
0 0 1 0 0 0
1 1 1 0 1 1
0 0 0 1 1 0
0 0 1 0 0 0
0 0 1 0 0 0
As you can see, in the "whole piece" case, one can find a path (diagonal counted) from top to bottom and left to right, whereas in the "not whole piece", the path is broken. So if you lift the periodic structure up, part of it will fall apart.
How can I do it efficiently in MATLAB? Is there an efficient way? Built-in?
Update
Actually, even if bwconncomp() returns 1, the periodic structure may not be connected. Let's consider this example.
A =
0 0 0 1 0 0
0 0 1 1 0 0
1 1 1 0 1 0
0 0 1 1 1 1
0 0 1 0 0 0
0 0 1 0 0 0
>> bwconncomp(A, 4)
>> 1
If I show 4 A blocks, then it is like
A | A
-----
A | A
0 0 0 1 0 0 | 0 0 0 1 0 0
0 0 1 1 0 0 | 0 0 1 1 0 0
1 1 1 0 1 0|1 1 1 0 1 0
0 0 1 1 1 1 | 0 0 1 1 1 1
0 0 1 0 0 0 | 0 0 1 0 0 0
0 0 1 0 0 0 | 0 0 1 0 0 0
-------------------------
0 0 0 1 0 0 | 0 0 0 1 0 0
0 0 1 1 0 0 | 0 0 1 1 0 0
1 1 1 0 1 0 | 1 1 1 0 1 0
0 0 1 1 1 1 | 0 0 1 1 1 1
0 0 1 0 0 0 | 0 0 1 0 0 0
0 0 1 0 0 0 | 0 0 1 0 0 0
So as you can see, the 1 on the left side collides with the 0 on the right side of another A, causing the thing not a "whole piece". (Placed with no space deliberately to make it patent).
The term is "connected". Equivalently, each piece is called a connected component.
Use bwconncomp (Image Processing Toolbox) to determine the number of connectrd components. Let A denote your matrix. Then
c = bwconncomp(A,4);
returns a structure c whose NumObjects field indicates how many connected components there are in A. The input argument "4" is the number of neighbours you want to consider to defin connectedness: either 4 (don't take diagonals into account; that semes to be what you want) or 8 (include diagonals). So, just check if
c.NumObjects
is 1 ("whole piece") or more than 1 ("not whole piece"). In your examples, the first matrix has 1 connected component and the second has 3.
If you want it in one line:
getfield(bwconncomp(A,4),'NumObjects')==1
(or use Divakar's suggestion).