I've been experimenting with a Sudoku solver using recursion. The problem I've encountered it that the recursive function after finding the right solution will not terminate, but goes on until every number is tested at every position.
How do I terminate such loop in Matlab? Error condition 'error('...') within the function can break the execution, but is by no means a good solution to my problem.
Here is a sample code for similar recursion, producing all possible 2 element vectors for numbers from 1 to 4. I would like it to stop when both numbers are equal to 2.
%possible moves at each position
moveMat = zeros([1,2])+3;
lineInput = zeros([1,2]);
%start recursion
recurNumbers(moveMat, 0, lineInput)
function recurNumbers(moveMat, position, lineVariable)
position = position + 1;
%if all numbers are equal to 2 then try to exit the function
if ~all(lineVariable == 2)
%if all numbers are not equal to 2, try other combination
if position < length(lineVariable)+1
for move = 0 : moveMat(position)
moveMat(position) = move;
lineVariable(position) = lineVariable(position) + 1;
recurNumbers(moveMat,position,lineVariable)
disp(lineVariable)
end
end
else
disp(lineVariable)
return
end
end
Now it will print the vector '[2 2]' twice, which indicates that it recognised the condition, but the 'return' will not do what I imagined it to do.
Although it is not very clear to me what you are trying to achieve, I assume that the following function meets your stopping criterion.
function exit_fl = recurNumbers(moveMat, position, lineVariable)
exit_fl = 0;
if (all(lineVariable == 2))
% Show the result and exit
disp(lineVariable)
exit_fl = 1;
else
position = position + 1;
%if all numbers are not equal to 2, try other combination
if position < length(lineVariable)+1
for move = 0 : moveMat(position)
moveMat(position) = move;
lineVariable(position) = lineVariable(position) + 1;
% Receive the exit status of your function
ex_fl = recurNumbers(moveMat,position,lineVariable);
if (ex_fl == 1)
% If the criterion was met, then stop
exit_fl = 1;
return
end
end
end
end
end
Related
I made a simple function that loops between the rows and columns of an array using for loops. The loop is part of a function named checktakentest (Since I'm testing this method atm). I keep getting the error that there aren't enough input arguments.
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
if tttArray(h,j) == 1
%Is spot is taken, break loop
spotTaken = 1; break;
else
spotTaken = 0;
end
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
I tried also defining h and j previously as follows
h = [1,2,3];
j = [1,2,3];
Note that tttArray is a global variable defined in another function and its array values change in that function. A spot taken is 1, empty is 0. What arguments should I pass to the function and how do I know which ones to pass since this has been a recurring problem for me? A simple explanation would be appreciated. Note that I call the function via
checktakentest(tttArray)
Just remove the first if clause - at that point you don't have j initialized to a value, so you can't use it, yet:
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
If you call your function like this: checktakentest(tttArray) with tttArray beeing a mxn-matrix with m>2 and n>2 you should not get an error.
If you call it like this: checktakentest you will get the error you described (not enough input arguments).
I am new to matlab and I have couple of questions about it. First one, "Your function should terminate the sequence when either the value of ... or..." I use || in the code but it does not work as expected while && gives me the correct answer. Second question, how could the code be to display only the final answer?
Problem: calculate X which is represented by the sequence below
X = 1 - 1/2^2 + 1/3^2 - 1/4^2 +....
Requirement: Your function should terminate the sequence when either the value of 1/k^2 is less than 0.0001 or k is equal to k_max.
input k
Initialize x = 0
for loop i from 1 to k
if 1/i^2<0.0001 && i >= 100
break
end
Calculate X = (-1)^(i+1)./i^2 + X
end
You can use the break function as follows, where END_CONDITION is the condition you want to end your loop in.
if END_CONDITION
disp(X);
break;
end
To display the final answer, you can use the disp function. Eg. if your variable you want to print is called A then you use the following code.
disp(A)
Collectively this is your code. Since k_max terminates at the end of the for loop, we don't have to add any conditions to break out of the loop.
X = 0;
for i = 1:k
if 1/i^2<0.0001 || i==100
break;
end
X = (-1)^(i+1)./i^2 + X;
end
disp(X);
A common problem I have is the following:
Within a loop (usually a for loop) some constraints are - and have to be - checked at the beginning. Now sometimes if a condition if fulfilled, the code within the loop should run to the end of the current iteration step and then quit.
Usually I'd do it somehow like so
a = 0;
quit = 0;
for i = 1:1:11
if (a == 5) % Condition to be checked *before* the calculation
quit = 1; % Stop loop after this iteration
end
a = a + 1; % Calculation
...
if (quit == 1)
break;
end
end
But in a tight loop already this extra condition checking if (quit == 1) might give a relevant slow down. Also one needs to introduce an extra variable so I wonder how this is usually done or if there is a better way to do it...
why not do this way.
for i = 1:1:11
if (a == 5) % Condition to be checked *before* the calculation
func() --> do all the calculations
break; % Stop loop after this iteration
else
func() --> do all calculations
end
end
function func()
a = a+1
//all other calculations
end
Normally you can detect when to stop iterating. But if I understand your question, you can only detect when it should be the last iteration. You could try this:
a = 0;
i = 1;
while (i<=11)
if (a == 5)
i = 12; % Make sure this is the last iteration
else
i = i + 1;
end
a = a + 1;
end
What about:
for i = 1:11
quit = (a==5); % Condition to be checked *before* the calculation
a = a+1
if quit
break; % Stop loop after this iteration
end
end
Makes any difference?
- Make an infinite loop with logical variable condition set to 1
- Within the loop when stopping loop criteria rises set the logical
variable condition to 0
- loop will no longer run
count = 0;
stop = 11;
condition = 1;
while condition
count = count + 1;
--> do all the calculations before checking
condition = ~(a == 5 || count == stop);
--> do all the remaining calculations then exit from the loop
end
The while loop is enough
a = 0;
quit = 0;
while (a <= 5)
a++; % Calculation
...
end
Hi all I am working on checking for certain cases in a large loop, with in this large loop is this statement:
%Center Dialouge
timers_c = [start_dpc_sh_hi_timer_c, start_dpc_sh_lo_timer_c, start_ffm_sh_act_hi_timer_c,...
start_ffm_sh_act_lo_timer_c, start_hpot_eff_loss_timer_c, start_lfpt_dpsh_timer_c,...
start_pc_sh_time_c, start_post_tl_nl_c, start_pre_tl_nl_c, start_elec_lu_timer_c];
if perf_case_c ~= -1
for k = 1:10
if iscellstr(timers_c(k)) == 1
perf_case_timer_c = timers_c{k};
timer_set_c = 1;
end
end
end
To I identify the start time and the case type to be output in a dialogue message:
if timer_set_c == 1
pcase_c = msgbox([sprintf('%s'),perf_case_c,sprintf('\nMET:%s\n'),perf_case_timer_c],'PERFORMANCE CASE');
end
I can't get the if statement that determines which case has been determined to work. I am trying to use the change from -1 to a string somehow, but it doesn't quite work.
A minimal example would be
%Assume all timers initialized as zero
%Assume case ~= -1 (is a char array, string
timers_c = [timer1, timer2, timer3 ]
if case ~= -1
for k = 1:3
if iscellstr(timer_c(k)) ==1
case_time = timers(c{k});
time_set_flag = 1
end
end
end
...
and then outside of the loop would be the above msgbox
I have this problem about counting how many times the condition is true in for loop while using a timer object. so I set my timer object calling this function every 60 secs and it will check my condition in the database if X and Z are equal to 1, then it will do something. The problem is that I want it to count every time X and Z are both equal to 1 because I have another program changing values of X and Z every sec. If the count is equal to 1, 2, and 3 it will do differently. When I run it, it doesnt go more than 1 even though X and Z are equal to 1 for many times. Below are my code
a = timer('ExecutionMode', 'fixedRate','TimerFcn', 'func(1)', 'Period', 60);
start(a);
function [x] = func(y)
count = 0;
if x == y && z == y
count = count +1;
if count == 1
disp('1')
elseif count == 2
disp('2')
elseif count == 3
disp('3')
end
else
disp('same')
end
Your main problem is the count variable has function-local scope, so it's created every time the function is called and destroyed when the function ends. You need it to persist between calls the the function. One possibility is to make the count variable a global:
global count;
count = 0;
a = timer('ExecutionMode', 'fixedRate','TimerFcn', 'func(1)', 'Period', 60);
start(a);
function func(y)
global count;
if x == y && z == y
count = count + 1;
disp(num2str(count));
else
disp('same');
end
This code also replaces the if structure that made the various disp calls with a single call to disp. If your intention is to print out the count, this is a better method.
You are not closing the first if statement with an end. Therefore, if count == 1 and everything that follows is only executed when x== y && z == y
Close your first if statement and your code should work:
if x == y && z == y
count = count +1;
end
if count == 1
...
Note also that as you have written your code, you have count reset to 0 every time you enter the function, which means that count=count+1; will always be count = 0 + 1 = 1;
If you want to count how many times you get into a function, you must make the counter variable persistent, otherwise it will be set to zero in every call.