How to print a chain of arrows with fprintf - matlab

I am looking for a way to set up the fprintf function so that it returns the string 1->2->...->n for any input n. However, I cannot find a way to do so without having an extra arrow attached at the beginning (->1->2->...->n) or the end of the string (1->2->...->n->). Is there a way around this?

You could use strjoin for this...
n = 4;
str = strjoin( arrayfun(#num2str, 1:n, 'uni', 0), '->' );
% str = '1->2->3->4'
Or if you're set on using fprintf (or sprintf), you could manually add the first element (for ease, assume n >= 1)
str = ['1', sprintf('->%.0f', 2:n )];
If you just want to print these to the Command Window, simply use disp on either option instead of (or after) assigning to str. If you're writing to a file with fprintf then simply use fprintf( fid, [str '\n'] ) to print the line to file.

For this type of task, the solution is to print either the first or the last element separately:
n = 8;
fprintf('%d', 1);
fprintf('->%d', 2:n);
fprintf('\n');

Here's another approach to build the desired string:
n = 10;
str = regexprep(num2str(1:n), '\s+', '->');
This gives
str =
'1->2->3->4->5->6->7->8->9->10'

Related

Creating a function with variable number of inputs?

I am trying to define the following function in MATLAB:
file = #(var1,var2,var3,var4) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4)'];
However, I want the function to expand as I add more parameters; if I wanted to add the variable vark, I want the function to be:
file = #(var1,var2,var3,var4,vark) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4) 'vark=' num2str(vark)'];
Is there a systematic way to do this?
Use fprintf with varargin for this:
f = #(varargin) fprintf('var%i= %i\n', [(1:numel(varargin));[varargin{:}]])
f(5,6,7,88)
var1= 5
var2= 6
var3= 7
var4= 88
The format I've used is: 'var%i= %i\n'. This means it will first write var then %i says it should input an integer. Thereafter it should write = followed by a new number: %i and a newline \n.
It will choose the integer in odd positions for var%i and integers in the even positions for the actual number. Since the linear index in MATLAB goes column for column we place the vector [1 2 3 4 5 ...] on top, and the content of the variable in the second row.
By the way: If you actually want it on the format you specified in the question, skip the \n:
f = #(varargin) fprintf('var%i= %i', [(1:numel(varargin));[varargin{:}]])
f(6,12,3,15,5553)
var1= 6var2= 12var3= 3var4= 15var5= 5553
Also, you can change the second %i to floats (%f), doubles (%d) etc.
If you want to use actual variable names var1, var2, var3, ... in your input then I can only say one thing: Don't! It's a horrible idea. Use cells, structs, or anything else than numbered variable names.
Just to be crytsal clear: Don't use the output from this in MATLAB in combination with eval! eval is evil. The Mathworks actually warns you about this in the official documentation!
How about calling the function as many times as the number of parameters? I wrote this considering the specific form of the character string returned by your function where k is assumed to be the index of the 'kth' variable to be entered. Array var can be the list of your numeric parameters.
file=#(var,i)[strcat('var',num2str(i),'=') num2str(var) ];
var=[2,3,4,5];
str='';
for i=1:length(var);
str=strcat(str,file(var(i),i));
end
If you want a function to accept a flexible number of input arguments, you need varargin.
In case you want the final string to be composed of the names of your variables as in your workspace, I found no way, since you need varargin and then it looks impossible. But if you are fine with having var1, var2 in your string, you can define this function and then use it:
function str = strgen(varargin)
str = '';
for ii = 1:numel(varargin);
str = sprintf('%s var%d = %s', str, ii, num2str(varargin{ii}));
end
str = str(2:end); % to remove the initial blank space
It is also compatible with strings. Testing it:
% A = pi;
% B = 'Hello!';
strgen(A, B)
ans =
var1 = 3.1416 var2 = Hello!

Replacing Several Different Character of a string

I have to write a function to replace the characters of a string with those letters.
A=U
T=A
G=C
C=G
Example:
Input: 'ATAGTACCGGTTA'
Therefore, the output should be:
'UAUCAUGGCCAAU'
I can replace only one character. However, I have no how to do several. I could replace several if '"G=C and C=G" this condition was not there.
I use:
in='ATAGTACCGGTTA'
check=in=='A'
in(check)='U'
ans='UTUGTUCCGGTTU'
if I keep doing this at some point G will be replaced by C then then all the C will be replaced by G. How can I stop this?? Any help will be appreciated.
Just for fun, here's probably the absolute simplest way, via indexing:
key = 'UGCA';
[~, ~, idx] = unique(in);
out = key(idx'); % transpose idx since unique() returns a column vector
I do love indexing :D
Edit: As rightly pointed out, this is very optimised for the question as stated. Since [a, ~, idx] = unique(in); returns a and idx such that a(idx) == in, and by default a is sorted, we can just assume that a == 'ACGT' and pre-construct key to be the appropriate translation of indices into a.
If some characters from the known alphabet never appear in the input string, or if other unknown characters appear, then the indices don't match and the assumption breaks. In that case, we have to calculate the appropriate key explicitly - filling in the step that was optimised out above:
alph = 'ACGT';
trans = 'UGCA';
[key, ~, idx] = unique(in);
[~, alphidx, keyidx] = intersect(alph, key); % find which elements of alph
% appear at which points in key
key(keyidx) = trans(alphidx); % translate the elements of key that we can
out = key(idx');
The simplest way would be to use an intermediary letter. For instance:
in='ATAGTACCGGTTA'
in(in == 'A')='U'
in(in == 'T')='A'
in(in == 'C')='X'
in(in == 'G')='C'
in(in == 'X')='G'
This way you keep the 'C' and 'G' characters separate.
EDIT:
As others have mentioned, there are a few things other things you could do to improve this approach (though personally I think Notlikethat's way is cleanest). For instance, if you use a second variable, you don't have to worry about keeping 'C' and 'G' separate:
in='ATAGTACCGGTTA'
out=in;
out(in == 'A')='U';
out(in == 'T')='A';
out(in == 'C')='G';
out(in == 'G')='C';
Alternatively, you could make your indices first, then index after:
in='ATAGTACCGGTTA'
inA=in=='A';
inT=in=='T';
inC=in=='C';
inG=in=='G';
in(inA)='U';
in(inT)='A';
in(inC)='G';
in(inG)='C';
Finally, my personal favourite for sheer idiocy:
out=char(in+floor((68-in).*(in<70)*7/4)*4-round(ceil((in-67)/4)*3.7));
(Seriously, that last one works)
You can perform multiple character translation with bsxfun.
Inputs:
in = 'ATAGTACCGGTTA';
pat = ['A','T','G','C'];
subst = ['U','A','C','G'];
out0 ='UAUCAUGGCCAAU';
Translate all characters simultaneously:
>> ii = (1:numel(pat))*bsxfun(#eq,in,pat.'); %' instead of repmat and .*
>> out = subst(ii)
out =
UAUCAUGGCCAAU
>> isequal(out,out0)
ans =
1
Say you only want to translate a subset of the characters, leaving part of the sequence intact, it is easily solved with logical indexing and a few extra lines:
% Leave the Gs and Cs in place
pat = ['A','T'];
subst = ['U','A'];
ii = (1:numel(pat))*bsxfun(#eq,in,pat.'); %' same
out = char(zeros(1,numel(in)));
nz = ii>0;
out(nz) = subst(ii(nz));
out(~nz) = in(~nz)
out =
UAUGAUCCGGAAU
The original Gs and Cs are unchanged; A became U, and T became A (T is gone).
I would suggest to use containter.Map:
m=containers.Map({'A','T','G','C'},{'U','A','C','G'})
mapfkt=#(input)(cell2mat(m.values(num2cell(input))))
Usage:
mapfkt('ATAGTACCGGTTA')
Here is another method that should be fairly efficient, general, and in the line of thought of your original attempt:
%Suppose this is your input
myString = 'abcdeabcde';
fromSting = 'ace';
toString = 'xyz';
%Then it just takes this:
[idx fromLocation] = ismember(myString,fromSting)
myString(idx)=toString(fromLocation(idx))
If you know that all letters need to be replaced, the last line can be slightly simplified as you wont need to use idx.

Creating a translator in MatLab

I am trying to create a simple program in Matlab where the user can input a string (such as "A", "B", "AB" or "A B") and the program will output a word corresponding to my letter.
Input | Output
A Hello
B Hola
AB HelloHola
A B Hello Hola
This is my code:
A='Hello'; B='Hola';
userText = input('What is your message: ', 's');
userText = upper(userText);
for ind = 1:length(userText)
current = userText(ind);
X = ['The output is ', current];
disp(X);
end
Currently I don't get my desired results. I instead get this:
Input | Output
A The output is A
B The output is B
I'm not totally sure why X = ['The output is ', current]; evaluates to The output is A instead of The output is Hello.
Edit:
How would this program be able to handle numbers... such as 1 = "Goodbye"
What's going on:
%// intput text
userText = input('What is your message: ', 's');
%// ...and some lines later
X = ['The output is ', userText];
You never map what you type to what is contained by the variables A and B.
The fact that they are called A and B has nothing to do with what you type. You could call them C and blargh and still get the same result.
Now, you could use eval, but that's really not advisable here. In this case, using eval would force the one typing in the strings to know the exact names of your variables...that's a portability, maintainability, security, etc. disaster waiting to happen.
There are better solutions possible, for instance, create a simple map:
map = {
'A' 'Hello'
'B' 'Hola'
'1' 'Goodbye'
};
userText = input('What is your message: ', 's');
str = map{strcmpi(map(:,1), userText), 2};
disp(['The output is ', str]);
I would recommend using a map object to contain what you want. This will circumvent the eval function (which I suggest avoiding like the plague). This is pretty simple to read and understand, and is pretty efficient especially in the case of a long input string.
translation = containers.Map()
translation('A') = 'Hola';
translation('B') = 'Hello';
translation('1') = 'Goodbye';
inputString = 'ABA1BA1B11ABBA';
resultString = '';
for i = 1:length(inputString)
if translation.isKey(inputString(i))
% get mapped string if it exists
resultString = [resultString,translation(inputString(i))];
else
% if mapping does not exist, simply put the input string in (covers space case)
resultString = [resultString,inputString(i)];
end
end
Take a look at the command eval. Currently, you are displaying the name of the variable that contains the string you want. eval will help you in actually accessing and printing it.
What you need to do it :
X = ['The output is ', eval(current)];
Here the documentation : eval

Concatenate strings of digits in matlab

Suppose I have a series of strings such as:
a = '101010101010'
b = '010101'
c = '000101010'
is there a way in Matlab to concatenate them and produce the binary number 101010101010010101000101010?
Use the concatenation operator [ ], with horizontal concatenation , (vertical concatenation ; will fail here unless you reshape() into column vectors):
[a,b,c]
However, I suggest storing your variables in a cell array:
s = {'101010101010','010101', '000101010'};
[s{:}]
or
cat(2,s{:})
To concatenate strings, you could say:
out = [a b c];
Alternatively:
out = strcat(a,b,c);
Yet another way:
out = sprintf('%s', a,b,c);
I think that this should work:
res = [a,b,c]
or alternatively call
res = strcat(a,b,c)
or, yet
res = cat(2,a,b,c)

Using input dialog boxes in Matlab

Suppose I have a function that is something like this:
function [ c ] = input_args(m)
for i = 1 : m+1
c{i} = inputdlg('Enter next m value');
end
end
Now I'd like to change this so that the instruction to the user at the i'th stage of the for loop says something like "Enter the i'th m value", where i is the changing index in the for loop. How can I do this?
Thanks!
A string is a array of characters, so you can concatenate them like any other array. You need to use num2str to convert a number into a printable character.
inputdlg(['Enter the ' num2str(i) 'th m value']);
A more general solution would be to use sprintf to format your string; to do the same thing with sprintf you would use:
inputdlg(sprintf('Enter the %dth m value', i));
which you might find more readable (and allows you to use standard fprintf formatting options).