I have a homework exercise that asks for a script that finds smallest 3-digit Armstrong Number.
I wrote my script. It works fine for finding these numbers, but I don’t know how to stop at first Armstrong number.
Here is my code
a=0;
b=0;
c=0;
for x1=1:1:9
a=x1^3;
for x2=0:1:9
b=x2^3;
for x3=0:1:9
c=x3^3;
d=(x1*100 + x2*10 + x3);
if (a+b+c) == (d)
disp(d)
end
end
end
end
It normally prints 153 370 371 407.
If I use break after disp it just gets out of first for and not all, and prints 153 370 407.
You can stop loops with the keyword break. However, this just stops one loop. You have now to options
set some kind of flag and check it in every loop to terminate (break) it (aka: the proper way)
use return (aka: the nasty way)
Option 1
a = 0;
b = 0;
c = 0;
FLAG_STOP = false;
for x1 = 1:9
a = x1^3;
for x2 = 0:9
b = x2^3;
for x3 = 0:9
c = x3^3;
d = (x1*100 + x2*10 + x3);
if (a+b+c) == (d)
disp(d)
% set flag
FLAG_STOP = true;
break
end
end
if FLAG_STOP
break
end
end
if FLAG_STOP
break
end
end
Option 2
a word of warning:
(...) it does not just exit the loop; it exits the script or function and
returns control to the invoking program or command prompt.
i.e. all statements after return will be ignored -- with no matter whether they are part of a loop or not
a = 0;
b = 0;
c = 0;
for x1 = 1:9
a = x1^3;
for x2 = 0:9
b = x2^3;
for x3 = 0:9
c = x3^3;
d = (x1*100 + x2*10 + x3);
if (a+b+c) == (d)
disp(d)
return % <<<<<<<<<<<<
end
end
end
end
If you don't want to use return as recommended in #max's answer you may use try/catch and error to handle such cases:
try
a = 0;
b = 0;
c = 0;
for x1 = 1:9
a = x1^3;
for x2 = 0:9
b = x2^3;
for x3 = 0:9
c = x3^3;
d = (x1*100 + x2*10 + x3);
if (a+b+c) == (d)
disp(d)
error("") ;
end
end
end
end
catch
end
Related
I am programming a simple perceptron in matlab but it is not converging and I can't figure out why.
The goal is to binary classify 2D points.
%P1 Generate a dataset of two-dimensional points, and choose a random line in
%the plane as your target function f, where one side of the line maps to +1 and
%the other side to -1. Let the inputs xn 2 R2 be random points in the plane,
%and evaluate the target function f on each xn to get the corresponding output
%yn = f(xn).
clear all;
clc
clear
n = 20;
inputSize = 2; %number of inputs
dataset = generateRandom2DPointsDataset(n)';
[f , m , b] = targetFunction();
signs = classify(dataset,m,b);
weights=ones(1,2)*0.1;
threshold = 0;
fprintf('weights before:%d,%d\n',weights);
mistakes = 1;
numIterations = 0;
figure;
plotpv(dataset',(signs+1)/2);%mapping signs from -1:1 to 0:1 in order to use plotpv
hold on;
line(f(1,:),f(2,:));
pause(1)
while true
mistakes = 0;
for i = 1:n
if dataset(i,:)*weights' > threshold
result = 1;
else
result = -1;
end
error = signs(i) - result;
if error ~= 0
mistakes = mistakes + 1;
for j = 1:inputSize
weights(j) = weights(j) + error*dataset(i,j);
end
end
numIterations = numIterations + 1
end
if mistakes == 0
break
end
end
fprintf('weights after:%d,%d\n',weights);
random points and signs are fine since plotpv is working well
The code is based on that http://es.mathworks.com/matlabcentral/fileexchange/32949-a-perceptron-learns-to-perform-a-binary-nand-function?focused=5200056&tab=function.
When I pause the infinite loop, this is the status of my vairables:
I am not able to see why it is not converging.
Additional code( it is fine, just to avoid answers asking for that )
function [f,m,b] = targetFunction()
f = rand(2,2);
f(1,1) = 0;
f(1,2) = 1;
m = (f(2,2) - f(2,1));
b = f(2,1);
end
function dataset = generateRandom2DPointsDataset(n)
dataset = rand(2,n);
end
function values = classify(dataset,m,b)
for i=1:size(dataset,1)
y = m*dataset(i,1) + b;
if dataset(i,2) >= y, values(i) = 1;
else values(i) = -1;
end
end
end
i write a code using GUI and Mfile in MATHLAB. in my program i have a board.each time, computer put a marble and rotate the board then get a marble place and rotate direction of the board from user and After each of these things, i want it shows the result in axes1 in GUI. but it doesen't work in line 9 in the code below:
% some codes...
1. while(currentDepth < 7)
2. if(mod(currentDepth,2) ~= (plrC-1))
3. plat(currentDepth);
4. drawTable(); % show the result in axes1 --> it works
5. else
6. getMarble();
7. drawTable(); % show the result in axes1 --> it works
8. rotate();
9. drawTable(); % show the result in axes1 --> it dosen't work
10. end
11. end
% some codes...
.
function drawTable()
global board;
% some codes...
imshow(board,[0 4]);
end
do you have any idea?
it's rotate function. th board is divided into 4 parts just 1 part rotates.
function rotate()
global board;
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
ok now here we have a simplified code. make a new GUI with an axes then run the code below from 'OpeningFnc'. you will see my problem.
function test()
currentDepth = 1;
plrC = 1;
plrO = 2;
board = zeros(6);
while(currentDepth < 40)
if(mod(currentDepth,2) == 1)
plat();
drawTable(); % show the result in axes1 --> it works
else
getMarble();
drawTable(); % show the result in axes1 --> it works
rotate();
drawTable(); % show the result in axes1 --> it dosen't work
end
currentDepth = currentDepth +1;
end
function plat()
for a=1:5000
for b=1:5000
for c=1:50
m = a + b;
end
end
end
row = 1;
column = 1;
while(board(row,column) ~= 0)
row = randi(6);
column = randi(6);
end
board(row,column) = plrC;
row = randi([1 4]);
column = randi([1 4]);
board(row:row+2,column:column+2)=rot90(board(row:row+2,column:column+2));
end
function drawTable()
board(board==0) = board(board==0)+4;
B = zeros(305);
B(:,152:154) = 3;
B(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
B(x:x+44,y:y+44) = board(i,j);
end
end
imshow(B,[0 4]);
board(board==4) = board(board==4)*0;
end
function getMarble()
board(board==0) = board(board==0)+4;
b = zeros(305);
b(:,152:154) = 3;
b(152:154,:) = 3;
for i=1:6
for j=1:6
x = (i*5)+1+(i-1)*45;
y = (j*5)+1+(j-1)*45;
b(x:x+44,y:y+44) = board(i,j);
end
end
imshow(b,[0 4]);
i = 0;
while(i~=4)
[x,y] = ginput(1);
if(x<0 || x>305 || y<0 || y>305)
i = 0;
else
i = b(ceil(y),ceil(x));
end
end
y = ceil(y/50);
x = ceil(x/50);
board(y,x) = plrO;
end
function rotate()
block = 0;
vector = 'non';
while(block<1 || block>4)
block = str2double(cell2mat(inputdlg('chose a block: 1/2/3/4','board rotation')));
end
switch block
case 1
k=1; z=1;
case 2
k=1; z=4;
case 3
k=4; z=1;
case 4
k=4; z=4;
end
while(~strcmp(vector,'left') && ~strcmp(vector,'right'))
vector = questdlg('rotate left or right','Rotation','left','right','right');
end
if(strcmp(vector,'left'))
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2));
else
board(k:k+2,z:z+2)=rot90(board(k:k+2,z:z+2),3);
end
end
end
as ThP said, i have to add drawnow() function at the end of drawTable.
k = 0.019;
Pstar = 100;
H = 33;
h = 0.1;
X = 36;
N = round(X/h);
t = zeros(1,N+1);
P = zeros(1,N+1);
P(1) = 84;
t(1) = 0;
yHeun = zeros(1,N+1);
yHeun(1)=84;
a = 1; b = 100;
while b-a >0.5
c = (a+b)/2;
for n = 1:N
t(n+1) = t(n) + h;
Inside = nthroot(sin(2*pi*t/12),15);
Harvest = c*0.5*(Inside+1);
P(n+1) = P(n) + h*(k*P(n)*(Pstar-P(n))-Harvest(n));
if P < 0
P = 0;
end
yHeun(n+1) = yHeun(n) + h*0.5*((k*P(n)*(Pstar-P(n))-Harvest(n))+(k*P(n+1)*(Pstar-P(n+1))-Harvest(n+1)));
end
if sign(yHeun(c)) == sign(yHeun(a))
c = a;
else
c = b;
end
end
disp(['The root is between ' num2str(a) ' and ' num2str(b) '.'])
This is the code i'm trying to run and i know it probably sucks but im terrible at coding and every time i try to run the code, it says:
Attempted to access yHeun(50.5); index must be a positive integer or
logical.
Error in Matlab3Q4 (line 30)
if sign(yHeun(c)) == sign(yHeun(a))
I don't have ANY idea how to make yHeun(c or a or whatever) return anything that would be an integer. I dont think i did the while+for loop right either.
Question: "Begin with the higher bound of H being 100 (the high value results in a population of 0 after 36 months), and the lower bound being 1. Put the solver from Problem #3 above in the middle of a while loop and keep bisecting the higher and lower bounds of H until the difference between the higher and lower bound is less than 0.5."
I guess that line 30 (with the error) is this one:
if sign(yHeun(c)) == sign(yHeun(a))
Here, I guess c is equal to 50.5, as a result of c = (a+b)/2 above (BTW you can discover whether I guessed right by debugging - try adding disp(c) before line 30).
To force a number to be an integer, use floor:
c = floor((a+b)/2);
It seems you are trying to use some sort of divide-and-conquer algorithm; it should be enough to stop when b - a is equal to 1.
The following is my full code: (Most of it isn't useful for what I'm asking, but I just put in the entire code for context, the part of the code that is causing me trouble is towards the end)
clc
clear
P = xlsread('b3.xlsx', 'P');
d = xlsread('b3.xlsx', 'd');
CM = xlsread('b3.xlsx', 'Cov');
Original_PD = P; %Store original PD
LM_rows = size(P,1)+1; %Expected LM rows
LM_columns = size(P,2); %Expected LM columns
LM_FINAL = zeros(LM_rows,LM_columns); %Dimensions of LM_FINAL
% Start of the outside loop
for k = 1:size(P,2)
P = Original_PD(:,k);
interval = cell(size(P,1)+2,1);
for i = 1:size(P,1)
interval{i,1} = NaN(size(P,1),2);
interval{i,1}(:,1) = -Inf;
interval{i,1}(:,2) = d;
interval{i,1}(i,1) = d(i,1);
interval{i,1}(i,2) = Inf;
end
interval{i+1,1} = [-Inf*ones(size(P,1),1) d];
interval{i+2,1} = [d Inf*ones(size(P,1),1)];
c = NaN(size(interval,1),1);
for i = 1:size(c,1)
c(i,1) = mvncdf(interval{i,1}(:,1),interval{i,1}(:,2),0,CM);
end
c0 = c(size(P,1)+1,1);
f = c(size(P,1)+2,1);
c = c(1:size(P,1),:);
b0 = exp(1);
b = exp(1)*P;
syms x;
eqn = f*x;
for i = 1:size(P,1)
eqn = eqn*(c0/c(i,1)*x + (b(i,1)-b0)/c(i,1));
end
eqn = c0*x^(size(P,1)+1) + eqn - b0*x^size(P,1);
x0 = solve(eqn);
for i = 1:size(x0)
id(i,1) = isreal(x0(i,1));
end
x0 = x0(id,:);
x0 = x0(x0 > 0,:);
clear x;
for i = 1:size(P,1)
x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end
x = [x0'; x];
x = double(x);
x = x(:,sum(x <= 0,1) == 0)
lamda = -log(x);
LM_FINAL(:,k) = lamda;
end
% end of the outside loop
The important part of the above loop is towards the end:
x = x(:,sum(x <= 0,1) == 0)
This condition is sometimes not satisfied and hence the variable x is empty, which means LM_FINAL(:,k) = lamda is also empty. When this happens, I get the error:
x =
Empty matrix: 43-by-0
Improper assignment with rectangular empty matrix.
Error in Solution (line 75)
LM_FINAL(:,k) = lamda;
How can I skip this error so that the column for LM_FINAL remains as empty, but the loop continues (so that the rest of LM_FINAL's columns are filled) rather than terminating?
You can use try and catch phrase to explicitly handle errors inside loop (or elsewhere in your code).
I'm really a noobie in Matlab, and i was making a program in it. This program just tries to read a binary number, for example (00011), the first 3 characters dictate what operation it will make, and the rest are the ones that are going to enter the operation (add, multiply, etc.). But an error keeps killing me, the "index exceeds matrix dimensions", i understand that matlab autmatically applies dimensions to a matrix, and this keeps me bugging on my back ...
here's the code.
function res = decPGL(varargin)
persistent rInicial
global r alto
if isempty(varargin)
res = rInicial;
elseif isequal(varargin{1},'r') || isequal(varargin{1},'R')
rInicial = varargin{2};
res = rInicial;
else
alto = 0; % bandera que termina el programa
programa = varargin{1}; % vector del programa completo
ins = 1; % número de instrucción que se va a ejecutar
r = rInicial; % estado inicial de registros
while ins<=length(programa) && ~alto
unPaso(programa(ins));
ins = ins + 1;
end
res = r;
end
function unPaso(segmento)
% executes a segment of the program
global r alto
hh4 = ihighh(segmento,4);
i = ilow(ihighh(segmento,2),2)+1;
j = ilow(segmento,2)+1;
if hh4 <= 5
switch hh4
case 0
r(i) = r(i) + r(j);
case 1
r(i) = r(i) - r(j);
case 2
r(i) = r(i) * r(j);
case 3
if r(j) ~= 0
r(i) = r(i)/r(j);
end
case 4
r(i) = j;
case 5
t = r(i);
r(i) = r(j);
r(j) = t;
end
elseif hh4==6
switch i
case 1
r(j) = exp(r(j));
case 2
r(j) = log(abs(r(j)));
case 3
r(j) = r(j)^2;
case 4
r(j) = sqrt(abs(r(j)));
end
elseif hh4==7
switch i
case 1
r(j) = -r(j);
case 2
r(j) = sin(r(j));
case 3
r(j) = cos(r(j));
case 4
r(1) = r(j);
alto = 1;
end
end
The problem is in the "r" variable, when is in the switch and a case is chosen, marks the error "Index exceeds matrix dimensions".
Any ideas or suggestions to solve this?
Thanks in advance.
PS: Forgot to put the ihighh code and the i low ... sorry ... here it is ....
%%ihigh
function res = ihigh(p, m, varargin)
if length(varargin)>=1
B = varargin{1};
else
B = 2;
end
res = p - mod(p,B.^m);
%%ihighh
function res = ihighh(p, m, varargin)
if length(varargin)>=1
B = varargin{1};
else
B = 2;
end
res = ihigh(p,m,B)./(B.^m);
%%ilow
function res = ilow(p, m, varargin)
if length(varargin)>=1
B = varargin{1};
else
B = 2;
end
res = mod(p,B.^m);
I think your code is incomplete. But anyhow, it is more useful if you debug your code yourself.
In MATLAB this can be done easily by the dbstop if error command. Then run your program and it will switch to debug mode whenever an uncaught error occurs. You should then manually investigate the size of r and what index you try to access. These will not match, so you should determine whether the matrix is too small or your index is in a wrong range and correct for that.
To quit from debug mode, enter the command dbquit and to prevent MATLAB from switching to debug mode automatically, just run dbclear if error.
More information on the debugger can be found in the MATLAB documentation.