Using switch statement and while loop in conjunction - matlab

I am trying to complete the following task:
Create
a
script
that
will
repeatedly
create
a
random
integer
K
in
the
range
of
0
to
20
until
every
case
has
been
entered
at
least
once.
You
have
3
possible
cases.
Case
A
is
entered
when
the
range
of
the
random
integer
K
is
between
or
equal
to
0
and
7.
Case
B
is
entered
when
the
range
of
the
random
integer
K
is
between
or
equal
to
8
and
14.
Case
C
is
entered
when
the
range
of
the
random
integer
K
is
between
or
equal
to
15
and
20.
Rules:
When
a
case
is
entered
you
must
print
to
the
user
“Congratulations
you
entered
Case
(A,
B,
or
C)”.
You
can
only
enter
each
case
once.
If
the
program
attempts
to
enter
the
same
case
more
than
once,
you
must
print.
“Invalid,
that
case
has
already
been
entered”.
The
program
will
end
once
all
the
cases
have
been
entered
and
the
program
will
print
“Good
job,
you
have
entered
all
cases”.
If
the
program
attempts
to
enter
any
already
entered
cases
more
than
3
times
(3
total
times
not
just
for
one
specific
case),
the
program
will
end
and
print
to
the
user
“That
random
generator
wasn’t
random
enough”.
Here is the code I have so fa. It has taken me a couple hours to debug. Am I approaching this the wrong way????Please let me know.
K = round(rand*(20))
flag = 0;
counterA =0;
counterB=0;
counterC=0;
switch K
case {0,1,2,3,4,5,6,7}
fprintf('Congratulations you entered Case A\n')
flag = 1;
counterA = 1
case {8,9,10,11,12,13,14}
fprintf('Congratulations you entered Case B\n')
flag =2;
counterB = 1
case {15,16,17,18,19,20}
fprintf ('Congratulations you entered Case C\n')
flag = 3;
counterC = 1
end
while flag == 1 || flag == 2 || flag ==3
K = round(rand*(20))
if K >=0 && K<=7 && flag==1
disp ('Invalid, that case has already been entered')
counterA = counterA+1
elseif K >=8 && K<=14 && flag ==2
disp ('Invalid, that case has already been entered')
counterB=counterB+1
elseif K >=15 && K<=20 && flag==3
disp ('Invalid, that case has already been entered')
counterC =counterC+1
elseif K >=0 && K<=7 && flag ~=1
counterA =counterA+1
flag == 1;
if counterA==1&&counterB~=2 ||counterA==1&&counterC~=2
fprintf('COngrats guacamole A\n')
end
elseif K >=8 && K<=14 && flag ~=2
counterB=counterB+1
flag == 2;
if counterB ==1&&counterA~=2||counterB==1&&counterC~=2
fprintf('COngratsavacado B\n')
end
elseif K >=15 && K<=20 && flag~=3
counterC=counterC+1
flag == 3;
if counterC==1&&counterA~=2||counterC==1&&counterB~=2
fprintf ('Congratscilantro C\n')
end
end
if counterA==1 && counterB==1 && counterC==1
flag=100;
disp('DONE')
elseif counterA == 3|| counterB==3 || counterC==3
disp ('That random generator wasnt random enough')
flag =99;
elseif counterA==2||counterB==2||counterC==2
disp('Inval')
end

Some words about your code:
Don't use variable names like counterA,counterB,counterC, use a array with 3 elements instead. In this case: You need only a total limit, thus one variable is enough.
rand*20 generates random values between 0 and 20, but using round(rand*20) causes a lower probability for 0 and 20. Use randi if you need integers.
Use "Start indent" to format your code clean, it makes it easier to read.
This is not a full solution, the part with the 3 errors is missing. I think you will get this on your own.
caseNames={'A','B','C'};
caseEntered=[false,false,false];
%while there exist a case which is not entered and limit is not reached, continue
while ~all(caseEntered)
K = randi([0,20]);
switch K
case {0,1,2,3,4,5,6,7}
cs=1;
case {8,9,10,11,12,13,14}
cs=2;
case {15,16,17,18,19,20}
cs=3;
end
if caseEntered(cs)
%case has previously been entered, tdb
else
%case is entered frist time
fprintf('Congratulations you entered Case %s\n',caseNames{cs});
caseEntered(cs)=true;
end
end

Related

How to run a formula until it meets a certain criteria?

So, I have a formula ( =INDEX(Sheet1.A1:F15,RANDBETWEEN(1,15),RANDBETWEEN(1,6)) ) that returns a random number in the sheet. But, how to run the formula until the returned number is less than or equal to 25 ?
I thought of using for..next.. but couldn't get it how to run ...
Welcome!
As #thebusybee pointed out in his comment, a macro for this task is much easier than using built-in functions. As rightly pointed out #tohuwawohu, pre-filtering the values makes things a lot easier. The macro code could be, for example, like this
Option Explicit
Function getRandValue(aValues As Variant, nTypeCriteria As Integer, dCriteriaValue As Variant) As Variant
Rem Params: aValues - array of values,
Rem nTypeCriteria - -2 less then, -1 not more, 0 equal, 1 not less, 2 more than
Rem dCriteriaValue - value to compare
Dim aTemp As Variant
Dim i As Long, j As Long, k As Long
Dim bGoodValue As Boolean
k = UBound(aValues,1)*UBound(aValues,2)
ReDim aTemp(1 To k)
k = 0
For i = 1 To UBound(aValues,1)
For j = 1 To UBound(aValues,2)
bGoodValue = False
Select Case nTypeCriteria
Case -2
bGoodValue = (aValues(i,j) < dCriteriaValue)
Case -1
bGoodValue = (aValues(i,j) <= dCriteriaValue)
Case 0
bGoodValue = (aValues(i,j) = dCriteriaValue)
Case 1
bGoodValue = (aValues(i,j) >= dCriteriaValue)
Case 2
bGoodValue = (aValues(i,j) > dCriteriaValue)
End Select
If bGoodValue Then
k = k+1
aTemp(k) = aValues(i,j)
EndIf
Next j
Next i
If k<1 Then
getRandValue = "No matching values"
ElseIf k=1 Then
getRandValue = aTemp(k)
Else
getRandValue = aTemp(Rnd()*(k-1)+1)
EndIf
End Function
Just put a call to this function in a cell in the form
=GETRANDVALUE(A1:F15;-1;25)

How to print ONCE if there are multiple correct answers? (MATLAB)

So I have arr = randi([0,20],20,1). I want to show: If there are numbers less than 5, fprintf('Yes\n') only once. Im using a for loop (for i = 1 : length(arr)) and indexing it.
As your description, maybe you need if statement within for loop like below
for i = 1:length(arr)
if arr(i) < 5
fprintf('Yes\n');
break
end
end
If you want to print Yes once, you can try
if any(arr < 5)
fprintf('Yes\n')
endif
If you don't want to use break, the code below might be an option
for i = 1:min(find(arr <5))
if (arr(i) < 5)
fprintf('Yes\n');
end
end
You can use a break statement upon finding the first value under 5 and printing the Yes statement.
Using a break Statement:
arr = randi([0,20],20,1);
for i = 1: length(arr)
if arr(i) < 5
fprintf("Yes\n");
break;
end
end
Extension:
By Using any() Function:
Alternatively, if you'd like to concise it down without the need for a for-loop the any() function can be used to determine if any values within the array meet a condition in this case arr < 5.
arr = randi([0,20],20,1);
if(any(arr < 5))
fprintf("Yes\n");
end
By Using a While Loop:
Check = 0;
arr = randi([0,20],20,1);
i = 1;
while (Check == 0 && i < length(arr))
if arr(i) < 5
fprintf("Yes\n");
Check = 1;
end
i = i + 1;
end

using special characters in variable name Matlab

i have a function which returns a struct, and i want the return to have a meaningful names hence i wanted it to have names such as
sec.t<0.25
i.e t<0.25 being my variable and for this to return.
any help really appreciated.
function sec = sepfunc(intensdata)
lengthofdata=length(intensdata);
count1=0;
count_2=0;
count_3=0;
count_4=0;
count_5=0;
count_6=0;
count_7=0;
count_8=0;
for i= 1:lengthofdata %loop to seperate count number of data in 5 groups
if (intensdata(i,1)<0.025)
count1=count1+1;
elseif (intensdata(i,1)>=0.025 && intensdata(i,1)<0.05)
count_2=count_2+1;
elseif (0.05<=intensdata(i,1) && intensdata(i,1)<0.1)
count_3=count_3+1;
elseif (0.1<=intensdata(i,1) && intensdata(i,1)<0.125)
count_4=count_4+1;
elseif (0.125<=intensdata(i,1) && intensdata(i,1)<0.15)
count_5=count_5+1;
elseif (0.15<=intensdata(i,1) && intensdata(i,1)<0.175)
count_6=count_6+1;
elseif (0.175<=intensdata(i,1) && intensdata(i,1)<0.2)
count_7=count_7+1;
elseif (intensdata(i,1)>=0.2 )
count_8=count_8+1;
end
end
disp(count1);
disp(count_2);
disp(count_3);
disp(count_4);
disp(count_5);
disp(count_6);
disp(count_7);
disp(count_8);
j=1;
k=1;
l=1;
m=1;
n=1;
o=1;
p=1;
x=1;
low_sec=[count1];
lowmid_sec=[count_2];
middle_sec=[count_3];
upmid_sec=[count_4];
upper_sec=[count_5];
for i= 1:lengthofdata %to seperate original data into 5 different sub-groups.
if (intensdata(i,1)<0.05)
low_sec(j,1)=intensdata(i,1);
j=j+1 ;
elseif(0.05<=intensdata(i,1) && intensdata(i,1)<0.1)
lowmid_sec(k,1)=intensdata(i,1);
k=k+1;
elseif(0.1<=intensdata(i,1) && intensdata(i,1)<0.15)
middle_sec(m,1)=intensdata(i,1);
m=m+1;
elseif(0.15<=intensdata(i,1) && intensdata(i,1)<0.2)
upmid_sec(n,1)=intensdata(i,1);
n=n+1;
elseif( intensdata(i,1)>=0.2)
upper_sec(x,1)=intensdata(i,1);
x=x+1;
end
end
sec.low_sec = low_sec;
sec.lowmid_sec = lowmid_sec;
sec.middle_sec = middle_sec;
sec.upmid_sec = upmid_sec;
sec.upper_sec = upper_sec;
end
so i want to change low_sec to something like t<0.025 and 0.025
You cannot do this. Quoting from The MathWorks guidelines on variable names:
A valid variable name starts with a letter, followed by letters, digits, or underscores.
The < character is an operator. Most other programming languages don't allow this either. A suggestion would be to use the function name for the < operator: lt (help lt).
As you cannot put unusual characters in variable names I can see two ways to do this:
Descriptive: t_lt_0_025
Via a struct: s.name='t<0.025'

VHDL Saving input value into another signal

I have a question for my VHDL code. My entire code has to do the following:
input = Minutes + hours + clk
output = AFTER 1 minute: minuten = minuten + 1 (and if needed hours += 1)
So I built a counter, which counts (well for simulation easyness to 1/10th of a second instead of a minute) clock periods untill one minute is over. Then it raises the minute by 1, and send that to the output. I got one problem however: due to setup violation I can't simulate the synthesis well. I thought this violation was in the line: min_save = minutes. I think that it's impossible to save the input minutes immediately, so I thought: let's build another counter, which counts 1 clock period, and then saves it.
So my 2 questions:
Does this indeed solve the setup violation?
If so: why does the signal setup have no value. It has a value of undefined. What do i do wrong?
If not: why not, and how can I solve this then?
CODE:
architecture behaviour of internclk_u is
begin
process (minuten)
begin -- switching input minutes to binary.
minintern(6) <= minuten(0);
minintern(5) <= minuten(1);
minintern(4) <= minuten(2);
minintern(3) <= minuten(3);
minintern(2) <= minuten(4);
minintern(1) <= minuten(5);
minintern(0) <= minuten(6);
end process;
process (uren)
begin -- switching input hours to binary
uurintern(5) <= uren(0);
uurintern(4) <= uren(1);
uurintern(3) <= uren(2);
uurintern(2) <= uren(3);
uurintern(1) <= uren(4);
uurintern(0) <= uren(5);
end process;
process (clk)
begin
setup <= '0';
if(clk'event and clk = '1') then
if(setup < '1') then
setup <= '1';
else
setup <= setup;
if(min_save = minutes) then
count <= new_count;
else
min_save <= minutes;
count <= (others => '0');
end if;
end if;
end if;
end process;
process (count, minintern)
begin -- count one minute (now its 0.1 second)
if(count < F/10 ) then
new_count <= count + 1;
intern_out <= minintern;
uurintern_out <= uurintern;
else
case minintern is -- Calculate new value for output
when "0001001" => intern_out <= "0010000";
uurintern_out <= uurintern;
when "0011001" => intern_out <= "0100000";
uurintern_out <= uurintern;
when "0101001" => intern_out <= "0110000";
uurintern_out <= uurintern;
when "0111001" => intern_out <= "1000000";
uurintern_out <= uurintern;
when "1001001" => intern_out <= "1010000";
uurintern_out <= uurintern;
when "1011001" => intern_out <= "0000000";
case uurintern is
when "001001" => uurintern_out <= "010000";
when "011001" => uurintern_out <= "100000";
when others => uurintern_out <= uurintern + 1;
end case;
when others => intern_out <= minintern + 1;
uurintern_out <= uurintern;
end case;
new_count <= count;
setup <= '0';
end if;
end process;
process (intern_out) -- Reversing signals for next blocks in system
begin
interne_tijd_m(6) <= intern_out(0);
interne_tijd_m(5) <= intern_out(1);
interne_tijd_m(4) <= intern_out(2);
interne_tijd_m(3) <= intern_out(3);
interne_tijd_m(2) <= intern_out(4);
interne_tijd_m(1) <= intern_out(5);
interne_tijd_m(0) <= intern_out(6);
end process;
process (uurintern_out)
begin -- Reversing signals for next blocks in system
interne_tijd_u(5) <= uurintern_out(0);
interne_tijd_u(4) <= uurintern_out(1);
interne_tijd_u(3) <= uurintern_out(2);
interne_tijd_u(2) <= uurintern_out(3);
interne_tijd_u(1) <= uurintern_out(4);
interne_tijd_u(0) <= uurintern_out(5);
end process;
end behaviour;
Remarks:
ignore the 2 case statements; this is because the inputsignals are not binary coded; they are reversed. Besides that: it doesnt count 1,2,4,8,16 etc; it counts: 1,2,4,8,10,20 etc.
EDIT
I put in the whole architecture now.
The error message I received was something like: "Setup time violations occured(?)". So I believe I cant save the input minutes immediately when I receive minutes. Thats why I tried to program in the setup signal. Hope you guys can help. This error gave me a headache and lots of frustration already:(
EDIT 2
Forget about the whole "setup" signal. A student-assistent pointed out to me that the saving of the input doesnt make any sense. So my updated question is: How can I properly save the input signal/value into another signal?
Your code is really a mess, and it's very difficult to debug... :-(
I think that the problem is due to the fact that you have a multiple definition of the signal setup. Moreover the first time is defined inside a clocked process (even if the setup <= '0' is outside the if statement). The second time is defined inside another process that is not clocked. I think that the synthesis tool doesn't know how to proceed exactly. In the simulation of the RTL code you should normally see some glitches on the setup signal. I also think that the type of setup is set_logic. Try to change it to std_ulogic. The simulation tool will not compile your code since this type is unresolved. Fix the code and then go back to std_logic.
Another thing: you wrote if setup < '1' then: this sounds very strange to me (I didn't know that it was accepted). I prefer to write if setup /= '1' then: it is much more easier to read this kind of code...

how to store looping data in a single array or matrix?

i have a program with nested loop. i want all the values after each loop is completed, to
be stored in a single matrix A or array A.
display should be like
A= value1
value2
value3
etc...
where value1,value2,value3 are answers got at the end of each loop.
here is the program
load('b2.txt');
[M,N]=size(b2);
amp=[1.75,2,2.25,2.5,2.75,3,3.25,3.5,3.75,4];
%defining threshold
m=10501;
for i=10575:75:21000
a=b2(m:i,:);
time=b2(i,2)
t=40;
sum1=0;
sum2=0;
sum3=0;
sum4=0;
sum5=0;
sum6=0;
sum7=0;
sum8=0;
sum9=0;
sum10=0;
for R=1:75
if (a(R,3)>=t) && (a(R,3)<t+5)
sum1=sum1+a(R,1);
elseif (a(R,3)>=t+5) && (a(R,3)<t+10)
sum2=sum2+a(R,1);
elseif (a(R,3)>=t+10) && (a(R,3)<t+15)
sum3=sum3+a(R,1);
elseif (a(R,3)>=t+15) && (a(R,3)<t+20)
sum4=sum4+a(R,1);
elseif (a(R,3)>=t+20) && (a(R,3)<t+25)
sum5=sum5+a(R,1);
elseif (a(R,3)>=t+25) && (a(R,3)<t+30)
sum6=sum6+a(R,1);
elseif (a(R,3)>=t+30) && (a(R,3)<t+35)
sum7=sum7+a(R,1);
elseif (a(R,3)>=t+35) && (a(R,3)<t+40)
sum8=sum8+a(R,1);
elseif (a(R,3)>=t+40) && (a(R,3)<t+45)
sum9=sum9+a(R,1);
elseif (a(R,3)>=t+45) && (a(R,3)<t+50)
sum10=sum10+a(R,1);
end
cumulative_hits=[sum1,sum2,sum3,sum4,sum5,sum6,sum7,sum8,sum9,sum10];
for count=1:10
if cumulative_hits(1,count)<= 0
amplitude(1,count)= 0;
else
amplitude(1,count)=amp(1,count);
end
end
cumulative_hits(cumulative_hits==0)=[];
amplitude(amplitude==0)=[];
y=log10(cumulative_hits);
p=polyfit(amplitude,y,1);
f=polyval(p,amplitude);
end
%disp(p(1,1))
abs(p(1))
m=m+75;
end
need this asap.. thanks :)
You need to provide informations about which variable to store in the resulting array A, but just for your information:
You can always easily append values to it via:
A = [A; new_value];
which works either if new_value is a scalar or if it's a column-vector with identical number of elements like number of columns of A