How do I expand a range of numbers in MATLAB - matlab

Lets say I have this range of numbers, I want to expand these intervals. What is going wrong with my code here? The answer I am getting isn't correct :(
intervals are only represented with -
each 'thing' is separated by ;
I would like the output to be:
-6 -3 -2 -1 3 4 5 7 8 9 10 11 14 15 17 18 19 20
range_expansion('-6;-3--1;3-5;7-11;14;15;17-20 ')
function L=range_expansion(S)
% Range expansion
if nargin < 1;
S='[]';
end
if all(isnumeric(S) | (S=='-') | (S==',') | isspace(S))
error 'invalid input';
end
ixr = find(isnumeric(S(1:end-1)) & S(2:end) == '-')+1;
S(ixr)=':';
S=['[',S,']'];
L=eval(S) ;
end
ans =
-6 -2 -2 -4 14 15 -3

You can use regexprep to replace ;by , and the - that define ranges by :. Those - are identified by them being preceded by a digit. The result is a string that can be transformed into the desired output using str2num. However, since this function evaluates the string, for safety it is first checked that the string only contains the allowed characters:
in = '-6;-3--1;3-5;7-11;14;15;17-20 '; % example
assert(all(ismember(in, '0123456789 ,;-')), 'Characters not allowed') % safety check
out = str2num(regexprep(in, {'(?<=\d)-' ';'}, {':' ','})); % replace and evaluate

Related

Find the number at the n position in the infinite sequence

Having an infinite sequence s = 1234567891011...
Let's find the number at the n position (n <= 10^18)
EX: n = 12 => 1; n = 15 => 2
import Foundation
func findNumber(n: Int) -> Character {
var i = 1
var z = ""
while i < n + 1 {
z.append(String(i))
i += 1
}
print(z)
return z[z.index(z.startIndex, offsetBy: n-1)]
}
print(findNumber(n: 12))
That's my code but when I find the number at 100.000th position, it returns an error, I thought I appended too many i to z string.
Can anyone help me, in swift language?
The problem we have here looks fairly straight forward. Take a list of all the number 1-infinity and concatenate them into a string. Then find the nth digit. Straight forward problem to understand. The issue that you are seeing though is that we do not have an infinite amount of memory nor time to be able to do this reasonably in a computer program. So we must find an alternative way around this that does not just add the numbers onto a string and then find the nth digit.
The first thing we can say is that we know what the entire list is. It will always be the same. So can we use any properties of this list to help us?
Let's call the input number n. This is the position of the digit that we want to find. Let's call the output digit d.
Well, first off, let's look at some examples.
We know all the single digit numbers are just in the same position as the number itself.
So, for n<10 ... d = n
What about for two digit numbers?
Well, we know that 10 starts at position 10. (Because there are 9 single digit numbers before it). 9 + 1 = 10
11 starts at position 12. Again, 9 single digits + one 2 digit number before it. 9 + 2 + 1 = 12
So how about, say... 25? Well that has 9 single digit numbers and 15 two digit numbers before it. So 25 starts at 9*1 + 15*2 + 1 = 40 (+ 1 as the sum gets us to the end of 24 not the start of 25).
So... 99 starts at? 9*1 + 89*2 + 1 = 188.
The we do the same for the three digit numbers...
100... 9*1 + 90*2 + 1 = 190
300... 9*1 + 90*2 + 199*3 + 1 = 787
1000...? 9*1 + 90*2 + 900*3 + 1 = 2890
OK... so now I'm seeing a pattern here that seems to need to know the number of digits in each number. Well... I can get the number of digits in a number by rounding up the log(base 10) of that number.
rounding up log base 10 of 5 = 1
rounding up log base 10 of 23 = 2
rounding up log base 10 of 99 = 2
rounding up log base 10 of 627 = 3
OK... so I think I need something like...
// in pseudo code
let lengthOfNumber = getLengthOfNumber(n)
var result = 0
for each i from 0 to lengthOfNumber - 1 {
result += 9 * 10^i * (i + 1) // this give 9*1 + 90*2 + 900*3 + ...
}
let remainder = n - 10^(lengthOfNumber - 1) // these have not been added in the loop above
result += remainder * lengthOfNumber
So, in the above pseudo code you can give it any number and it will return the position in the list that that number starts on.
This isn't the exact same as the problem you are trying to solve. And I don't want to solve it for you.
This is just a leg up on how I would go about solving it. Hopefully, this will give you some guidance on how you can take this further and solve the problem that you are trying to solve.

get values from a text file with a mix of floats and strings

I am struggling with a text file that I have to read in. In this file, there are two types of line:
133 0102764447 44 11 54 0.4 0 0.89 0 0 8 0 0 7 Attribute_Name='xyz' Type='string' 02452387764447 884
134 0102256447 44 1 57 0.4 0 0.81 0 0 8 0 0 1 864
What I want to do here is to textscan all the lines and then try to determine the number of 'xyz' (and the total number of lines).
I tried to use:
fileID = fopen('test.txt','r') ;
data=textscan(fileID, %d %d %d %d %d %d %d %d %d %d %d %d %d %s %s %d %d','\n) ;
And then I will try to access data{i,16} to count how many are equal to Attribute_Name='xyz', it doesnt seem to be an efficient though.
what will be a proper way to read the data(what interests me is to count how many Attribute_Name='xyz' do I have)? Thanks
You could simply use count which is referenced here.
In your case you could use it in this way:
filetext = fileread("test.txt");
A = count(filetext , "xyz")
fileread will read the whole text file into a single string. Afterwards you can process that string using count which will return the occurrences from the given pattern.
An alternative when using older versions of MATLAB is this one. It will work with R2006a and above.
filetext = fileread("test.txt");
A = length(strfind(filetext, "xyz");
strfind will return an array which length represents the amount of occurrences of the specified string. The length of that array can be accessed by length.
There is the option of strsplit. You may do something like the following:
count = 0;
fid = fopen('test.txt','r');
while ~feof(fid)
line = fgetl(fid);
words = strsplit( line )
ind = find( strcmpi(words{:},'Attribute_Name=''xyz'''), 1); % Assume only one instance per line, remove 1 for more and correct the rest of the code
if ( ind > 0 ) then
count = count + 1;
end if
end
So at the end count will give you the number.

MATLAB fprintf Increase Number of Digits of Exponent

If we have
A=[100 -0.1 0];
B=[30 0.2 -2]; t1='text 1'; t2=text 2'
how to use fprintf so that the output saved in a file will look like that
100 -1.000E-0001 0.000E-0000 'text 1'
30 2.000E-0001 -2.000E-0000 'text 2'
I put together a "one-liner" (spread across several lines for better readability) that takes an array, a single number format, and a delimiter and returns the desired string. And while you found the leading blank-space flag, I prefer the + flag, though the function will work with both:
A=[-0.1 0];
B=[0.2 -2];
minLenExp = 4;
extsprintf = #(num,fmt,delim) ...
strjoin(cellfun(...
#(toks)[toks{1},repmat('0',1,max([0,minLenExp-length(toks{2})])),toks{2}],...
regexp(sprintf(fmt,num),'([+-\s][\.\d]+[eE][+-])(\d+)','tokens'),...
'UniformOutput',false),delim);
Astr = extsprintf(A,'%+.4E',' ');
Bstr = extsprintf(B,'%+.4E',' ');
disp([Astr;Bstr]);
Running this yields:
>> foo
-1.0000E-0001 +0.0000E+0000
+2.0000E-0001 -2.0000E+0000
(foo is just what the script file is called.)
Here's a more general approach that searches for the exponential format instead of assuming it:
A=[100 -0.1 0].';
B=[30 0.2 -2];
extsprintf = #(fmt,arr) ...
regexprep(...
sprintf(fmt,arr),...
regexprep(regexp(sprintf(fmt,arr),'([+-\s][\.\d]+[eE][+-]\d+)','match'),'([\+\.])','\\$1'),...
cellfun(#(match)...
cellfun(...
#(toks)[toks{1},repmat('0',1,max([0,minLenExp-length(toks{2})])),toks{2}],...
regexp(match,'([+-\s][\.\d]+[eE][+-])(\d+)','tokens'),...
'UniformOutput',false),...
regexp(sprintf(fmt,arr),'([+-\s][\.\d]+[eE][+-]\d+)','match')));
fmt = '%3d %+.4E %+.4e';
disp(extsprintf(fmt,A));
disp(extsprintf(fmt,B));
Outputs
>> foo
100 -1.0000E-0001 +0.0000e+0000
30 +2.0000E-0001 -2.0000e+0000

finding values of x and y using Octal Base system

In finding the values of x and y, if (x567) + (2yx5) = (71yx) ( all in base 8) I proceeded as under.
I assumed x=abc and y=def and followed.
(abc+010 def+101 110+abc 111+101)=(111 001 def abc) //adding ()+()=() and equating LHS=RHS.
abc=111-010=101 which is 5 in base 8 and then def=001-101 which is -4
so x=5 and y=-4
Now the Question is that the answer mentioned in my book is x=4 and y=3.
Is the above method correct.If so,then what's issue here ??
you can't compare the digits beginning with the most significant digit, because you don't know the carry from the digit below. Also a digit cannot have a negative value.
You can start with the least significant digit, because there is no carry:
7 + 5 = 14
so x = 4 with a carry of 1 at the next digit.
now you can rewrite your equation to:
(4567) + (2y45) = (71y4)
now you can look at the second least significant digit (the carry in mind):
6 + 4 + 1 (carry) = 13
so y = 3, also with a carry of 1.
the whole equation is:
(4567) + (2345) = (7134)
which is true for the octal system.

Matlab - preprocess CSV file

I have a CSV file in a format similar to the following one:
title1
index columnA1 columnA2 columnA3
1 2 3 6
2 23 23 1
3 2 3 45
4 2 2 101
title2
index columnB1 columnB2 columnB3
1 23 53 6
2 22 13 1
3 5 4 43
4 8 6 102
I want to build a function readCustomCSV which receives a CSV file in the bellow illustrated format and a row index i and returns an output file with (for let's say i = 3) the following content:
title1
index columnA1 columnA2 columnA3
3 2 3 45
title2
index columnB1 columnB2 columnB3
3 5 4 43
Do you know how to use the csvread function in order to obtain this type of functionality?
It confuses me that there are 2 types sections. I was thinking at using the whole thing as a string and then split it into 2 .csv files and then read the corresponding line line.
try using this function :
I assumed that all tables have equal number of columns/rows. The code can definitely be shortened / improved / extended ;)
function multi_table_csvread (row_index)
filename_INPUT = 'multi_table.csv' ;
filename_OUTPUT = 'selected_row.csv' ;
fIN = fopen(filename_INPUT,'r');
nextLine = fgetl(fIN);
tableIndex = 0;
tableLine = 0;
csvTable = [];
% start reading the csv file, line by line
while nextLine ~= -1
lineStr = strtrim(strsplit(nextLine,',')) ;
% remove empty cells
lineStr(cellfun('isempty',lineStr)) = [] ;
tableLine = tableLine + 1 ;
% if 1 element start new table
if numel(lineStr) == 1
tableIndex = tableIndex + 1;
tableLine = 1;
csvTable{tableIndex,tableLine} = lineStr ;
else
lineStr = add_comas(lineStr) ;
csvTable{tableIndex,tableLine} = lineStr ;
end
nextLine = fgetl(fIN);
end
fclose(fIN);
fOUT = fopen(filename_OUTPUT,'w');
if row_index > size(csvTable,2) -2
error('The row index exceeds the maximum number of rows!')
end
for k = 1 : size(csvTable,1)
title = csvTable{k,1};
columnHeaders = csvTable{k,2};
selected_row = csvTable{k,row_index+2};
fprintf(fOUT,'%s\n',title{:});
fprintf(fOUT,'%s',columnHeaders{:});
fprintf(fOUT,'\n');
fprintf(fOUT,'%s',selected_row{:});
fprintf(fOUT,'\n');
end
fclose(fOUT);
function line_with_comas = add_comas(this_line)
for ii = 1 : length(this_line)-1
this_line{ii} = strcat(this_line{ii},',') ;
end
line_with_comas = this_line ;