I have a maze file which is like this.
1111111
1001111
1101101
1101001
1100011
1111111
a format $direction indicating the direction
start end label
D D down
L L left
R R right
U U up
Then, I have a dataset indicating the start and end point.
Row Column
start 2 2
end 3 6
How can I record the moving direction from the start to the end like this?
direction row column
2 2
right 2 3
down 3 3
down 4 3
down 5 3
i have use array
array m(i,j)
if m(i,j) = 0 then
row=i;
column=j;
output;
however, it simply just not in the correct moving order.
Thanks if you can help.
Here's one way of doing this. Writing a more generalised maze-solving algorithm using SAS data step logic is left as an exercise for the reader, but this should work for labyrinths.
/* Define the format */
proc format;
value $direction
'D' = 'down'
'L' = 'left'
'R' = 'right'
'U' = 'up'
;
run;
data want;
/*Read in the maze and start/end points in (y,x) orientation*/
array maze(6,7) (
1,1,1,1,1,1,1,
1,0,0,1,1,1,1,
1,1,0,1,1,0,1,
1,1,0,1,0,0,1,
1,1,0,0,0,1,1,
1,1,1,1,1,1,1
);
array endpoints (2,2) (
2,2
3,6
);
/*Load the start point and output a row*/
x = endpoints(1,2);
y = endpoints(1,1);
output;
/*
Navigate through the maze.
Assume for the sake of simplicity that it is really more of a labyrinth,
i.e. there is only ever one valid direction in which to move,
other than the direction you just came from,
and that the end point is reachable
*/
do _n_ = 1 by 1 until(x = endpoints(2,2) and y = endpoints(2,1));
if maze(y-1,x) = 0 and direction ne 'D' then do;
direction = 'U';
y + -1;
end;
else if maze(y+1,x) = 0 and direction ne 'U' then do;
direction = 'D';
y + 1;
end;
else if maze(y,x-1) = 0 and direction ne 'R' then do;
direction = 'L';
x + -1;
end;
else if maze(y,x+1) = 0 and direction ne 'L' then do;
direction = 'R';
x + 1;
end;
output;
if _n_ > 15 then stop; /*Set a step limit in case something goes wrong*/
end;
format direction $direction.;
drop maze: endpoints:;
run;
Related
I would like to check if the value that has been entered by the users are Integer or not. I tried to using the below code, but it gives me the wrong output. When I entered a fractional value, it still shows me "it is an Integer".
prompt = {'Please Enter the start time:','Increment:','Stop time:'}; %Asking user to enter the data
dlgtitle = 'Input'; %Creating a title for the dialog box
dims = [1 40]; %Adjusting the dimensions
definput = {'0','0.01','10'}; %Using default values to warn users not to put text instead of number
answer = inputdlg(prompt,dlgtitle,dims,definput); %storing the three items of data the user enters
start = str2num(answer{1}); %Converting start value string to number
increment = str2num(answer{2}); %Converting increment value string to number
stop = str2num(answer{3}); %Converting stop value string to number
if start >= stop
f = msgbox('Start time cannot be greater than end time! Please re-enter!', 'Error!');
elseif increment >= stop
f = msgbox('The increment cannot be larger than the end time! Please re-enter!', 'Error!');
elseif start <= -1
f = msgbox('The start time can only be positive numbers! Please re-enter!', 'Error!' );
elseif stop <= -1
f = msgbox('The end time can only be positive numbers! Please re-enter!', 'Error!');
elseif increment <= -1
f = msgbox('The increment can only be positive numbers! Please re-enter!', 'Error!');
elseif isempty(str2num(answer{1}))
f = msgbox('Input must be a number! Please re-enter!', 'Error!');
elseif isempty(str2num(answer{2}))
f = msgbox('Input must be a number! Please re-enter!', 'Error!');
elseif isempty(str2num(answer{3}))
f = msgbox('Input must be a number! Please re-enter!', 'Error!');
end
start=int16(10); %define 'count' as an 8-bit integer
integer_check=isinteger(start)% is count an integer, 1 if yes, 0 if no
if integer_check==1 % if isinteger returns a ‘1’ display message
disp(' Yes it is an integer')
else % if isinteger returns a ‘0’ display message
disp(' No it is not an integer')
end
If is an integer, it doesn’t have a remainder if is divided over 1. So, instead of
integer_check = isinteger(start)
Use
integer_check = rem(start,1) == 0;
Here is my data from the Matlab output;
a Aerobic Anaerobic
'Ex_Cl' -0.00775597205802433 -0.00775597205802011
'Ex_Sulfate' -0.100000000000000 -0.100000000000000
'Ex_Cu2+' -0.00517064803868288 -0.00517064803868008
'Ex_Mg' -0.0129249011312688 -0.0129249011312618
'Ex_Ca2+' -0.00775597205802433 -0.00775597205802011
'Ex_NH3' 0 4.24088035850684
'Ex_H2O' -10 -10
'Ex_Biomass' 1.71896543839192 1.71896543839098
'Ex_Butyrate' 0 0
There are 184 rows altogether. The col names are a, Aerobic and Anaerobic respectively.
I am trying to create a for loop to just select the metabolites which are different between the aerobic and anaerobic, and also are only positive too.
The table was formed from d=table(a, Aerobic, Anaerobic).
Here is my code for trying to just get a new table which contains only the positive values which are different aerobic and anaerobic.
j=1
for i=1 : height (d)
if (b(i) ~= c(i))
difExc(j, 1:3) = d(i, 1:3)
j=j+1
else
continue;
end
end
And then I would like to create a new table
difExc=table(a, Aerobic, Anaerobic)
I've got the different bit, but I am not sure how to adjust the code to also say select only those which are positive and different between aerobic and anaerobic.
Any help would be appreciated.
Thank-you
You can use logical indexing to find the values that are different. This is the data I used
a = [...
"Ex_Cl"
"Ex_Sulfate"
"Ex_Cu2+"
"Ex_Mg"
"Ex_Ca2+"
"Ex_NH3"
"Ex_H2O"
"Ex_Biomass"
"Ex_Butyrate"];
Aerobic = [ ...
-0.00775597205802433
-0.100000000000000
-0.00517064803868288
-0.0129249011312688
-0.00775597205802433
0
-10
1.71896543839192
0];
Anaerobic = [ ...
-0.00775597205802011
-0.100000000000000
-0.00517064803868008
-0.0129249011312618
-0.00775597205802011
4.24088035850684
-10
1.71896543839098
0];
And this is finding the differences:
different = Aerobic ~= Anaerobic;
T = table(a(different), Aerobic(different), Anaerobic(different))
Result
T =
6×3 table
Var1 Var2 Var3
____________ __________ __________
"Ex_Cl" -0.007756 -0.007756
"Ex_Cu2+" -0.0051706 -0.0051706
"Ex_Mg" -0.012925 -0.012925
"Ex_Ca2+" -0.007756 -0.007756
"Ex_NH3" 0 4.2409
"Ex_Biomass" 1.719 1.719
%macro intercept(i1= ,i2= );
%let n = %sysfunc(countw(&i1));
%do i = 1 %to &n;
%let val_i1 = %scan(&i1,&i,'');
%let val_i2 = %scan(&i2,&i,'');
data scores;
set repeat_score2;
/* Segment 1 probablity score */
p1 = 0;
z1 = &val_i1 +
a * 0.03 +
r * -0.0047841 +
p * -0.000916081 ;
p1 = 1/(1+2.71828**-z1);
/* Segment 2 probablity score */
p2 = 0;
z2 = &val_i2 +
r * 0.09 +
m * 0.012786245 +
c * -0.00179618 +
p2 = 1/(1+2.71828**-z2);
logit_score = 0;
if max(p1,p2) = p1 then logit_score = 1;
else if max(p1,p2) = p2 then logit_score = 2;
run;
proc freq data = scores;
table logit_score * clu_ /nocol norow nopercent;
run;
%end;
%mend;
%intercept (i1=-0.456491042, i2=-3.207379842, i3=-1.380627318 , i4=0.035684096, i5=-0.855283373);
%intercept (i1=-0.456491042 0, i2=-3.207379842 -3.207379842, i3=-1.380627318 -1.380627318, i4=0.035684096 0.035684096,
i5=-0.855283373 -0.855283373);
I have the above macro which takes the intercept for the two of the above models and then calculates the probablity score and then assigns a a value to to a segment based on that probablity score.
The first problem with above macro is when I execute the macro with one argument each it's resolving macro variable 'n' to 2 and executing twice. First iteration, it's giving the right results while for second it's wrong.
For the second implementation(macro with two aruguments each) n is resolving to 3 and scan is resolving to both of those values together at a time (eg. i1 for the iteration itself is -0.45 and 0), If I remove the space, then it taking '.' to be the delimiter and resolving that to ( 0,45,0 - one for each iteration). I don't get any results for this case.
How do I get this to work the right way?
Thanks!!!
%SCAN and COUNTW function by default consider punctuation symbols and blanks as delimiters. Since your arguments include decimal points, you need to state explicitly that delimiter should be blank for both COUNTW and %SCAN. Which you have done for %SCAN, but not for COUNTW.
So the 2nd line of the code should be:
%let n = %sysfunc(countw(&i1,' '))
And I'm not sure if it's a typo or just formatting thing, but in your %SCAN functions third argument looks like two quotes together '', not quote-blank-quote ' ' as it should be.
I wrote my own function for Octave, but unfortunately aside of the final result value, the variable "result" is written to console on every change, which is an unwanted behavior.
>> a1 = [160 60]
a1 =
160 60
>> entr = my_entropy({a1}, false)
result = 0.84535
entr = 0.84535
Should be
>> a1 = [160 60]
a1 =
160 60
>> entr = my_entropy({a1}, false)
entr = 0.84535
I don't get the idea of ~ and it don't work, at least when I tried.
Code is as follows:
# The main difference between MATLAB bundled entropy function
# and this custom function is that they use a transformation to uint8
# and the bundled entropy() function is used mostly for signal processing
# while I simply use a straightforward solution usefull e.g. for learning trees
function f = my_entropy(data, weighted)
# function accepts only cell arrays;
# weighted tells whether return one weighed average entropy
# or return a vector of entropies per bucket
# moreover, I find vectors as the only representation of "buckets"
# in other words, vector = bucket (leaf of decision tree)
if nargin < 2
weighted = true;
end;
rows = #(x) size(x,1);
cols = #(x) size(x,2);
if weighted
result = 0;
else
result = [];
end;
for r = 1:rows(data)
for c = 1:cols(data) # in most cases this will be 1:1
omega = sum(data{r,c});
epsilon = 0;
for b = 1:cols(data{r,c})
epsilon = epsilon + ( (data{r,c}(b) / omega) * (log2(data{r,c}(b) / omega)) );
end;
if (-epsilon == 0) entropy = 0; else entropy = -epsilon; end;
if weighted
result = result + entropy
else
result = [result entropy]
end;
end;
end;
f = result;
end;
# test cases
cell1 = { [16];[16];[2 2 2 2 2 2 2 2];[12];[16] }
cell2 = { [16],[12];[16],[2];[2 2 2 2 2 2 2 2],[8 8];[12],[8 8];[16],[8 8] }
cell3 = { [16],[3 3];[16],[2];[2 2 2 2 2 2 2 2],[2 2];[12],[2];[16],[2] }
# end
In your code, you should end lines 39 and 41 with semicolon ;.
Lines finishing in semicolon aren't shown in stdout.
Add ; after result = result + entropy and result = [result entropy] in your code, or in general after any assignment that you don't want printed on screen.
If for some reason you can't modify the function, you can use evalc to prevent unwanted output (at least in Matlab). Note that the output in this case is obtained in char form:
T = evalc(expression) is the same as eval(expression) except that anything that would normally be written to the command window, except for error messages, is captured and returned in the character array T (lines in T are separated by \n characters).
As with any eval variant, this approach should be avoided if possible:
entr = evalc('my_entropy({a1}, false)');
i want to clarify how to control returning of variables from function in matlab,for exmaple let us consider this code
function [x y z]=percentage(a)
n=length(a);
maximum=0;
minimum=0;
subst=0;
minus=0;
plus=0;
minus_perc=0;
plus_perc=0;
for i=1:1:n
if a(i)>0
plus=plus+1;
else
minus=minus+1;
end
end
minuc_perc=minus/n;
plus_perc=plus/n;
maximum=max(minus_perc,plus_perc);
minimum=min(minus_perc,plus_perc);
subst=maximum-minimum;
x=plus_perc;
y=minus_perc;
z=subst*100;
if plus_perc>minus_perc
disp('among the successful people,relevant propession was choosen by');
disp(z)
disp('% people');
else
disp('among the successful people,irrelevant propession was choosen by');
disp(z);
disp('% people');
end
end
what i want to return is plus_proc,min_proc and subst,but when i run following command,get result like this
[c d e]=percentage(a)
among the successful people,relevant propession was choosen by
58.3333
% people
c =
0.5833
d =
0
e =
58.3333
so i think something is wrong,array is like this
a =
1 -1 1 1 -1 1 -1 -1 1 1 1 -1
so ones again,i want to return plus_proc,minus_proc,and subst
To return a variable in matlab you just assign into one of the specified return parameters. For example: to return the number five I would use:
function [foo] = gimmeFive()
foo = 5;
end
Your code is not giving you the right answer because you have a typo:
minuc_perc=minus/n;
should be
minus_perc=minus/n;
You could greatly simplify the function by taking advantage of the find function, like so:
Find the indeces of any element of a > 0, count them.
plus = length(find(a > 0));
plus_perc = plus ./ length(a);
Or if you want to cut even more out:
a > 0 gives us a vector of 0 and 1, so sum up the 1's
plus = sum(a > 0);
plus_perc = plus ./ length(a);