(Recursive) nested loops and IFs?
12-17-2015, 07:17 AM (This post was last modified: 12-17-2015 07:24 AM by chromos.)
Post: #1
 chromos Member Posts: 193 Joined: Jun 2015
(Recursive) nested loops and IFs?
Hi,
I'm writting solver for incomplete coordinates for multi caches (is there any geocacher out there?) which solves (brute force) inequalities, but their quantity and number of variables (and their names) is obtained from user via INPUT.

For six inequalities and four variables I have this static code:
(L1...coords via user input, something like {"5","0","3","5","(A+1)","(B)","(B-A-4)","0","1","5","2","4","(C-14)","(D-8)","(C-D+3)"}
L2...List of variable names,
L3, L4...Lists of variable boundaries,
L5...List of expressions
L6...valid variable values
Digitsum... digit sum of whole coordinates)

PHP Code:
SUBRFROMTO()BEGINFOR Loop1 FROM L3(1) TO L4(1) DO PRINT();  PRINT("                        Completed: "+(Loop1*100/(L4(1)-L3(1)))+" %"); FOR Loop2 FROM L3(2) TO L4(2) DO  FOR Loop3 FROM L3(3) TO L4(3) DO   FOR Loop4 FROM L3(4) TO L4(4) DO    TempList:={};    FOR Loop FROM 1 TO SIZE(L2) DO     EXPR(L2(Loop)+":=Loop"+STRING(Loop));     TempList(0):=EXPR(L2(Loop));    END;    Temp:=0;    IF DigitSum>0 THEN     FOR Loop FROM 1 TO SIZE(L5) DO      Temp:=Temp+EXPR(L5(Loop));     END;    END;    IF (NOT(DigitSum>0) OR Temp==DigitSum-SubDigitSum) THEN     IF (EXPR(L5(1))>=0 AND EXPR(L5(1))<=9) THEN      IF (EXPR(L5(2))>=0 AND EXPR(L5(2))<=9) THEN       IF (EXPR(L5(3))>=0 AND EXPR(L5(3))<=9) THEN        IF (EXPR(L5(4))>=0 AND EXPR(L5(4))<=9) THEN         IF (EXPR(L5(5))>=0 AND EXPR(L5(5))<=9) THEN          IF (EXPR(L5(6))>=0 AND EXPR(L5(6))<=9) THEN           L8(0):=""+EXPR(L1(1))+EXPR(L1(2))+"° "+EXPR(L1(3))+EXPR(L1(4))+"."+EXPR(L1(5))+EXPR(L1(6))+EXPR(L1(7));           L9(0):=""+EXPR(L1(8))+EXPR(L1(9))+EXPR(L1(10))+"° "+EXPR(L1(11))+EXPR(L1(12))+"."+EXPR(L1(13))+EXPR(L1(14))+EXPR(L1(15));           L6(0):=TempList;           Dist:=acos(sin(PublLat)*sin(FUNCDMTODEG(L8(SIZE(L8))))+cos(PublLat)*cos(FUNCDMTODEG(L8(SIZE(L8))))*cos(FUNCDMTODEG(L9(SIZE(L9)))-PublLon));           IFERR(acos((sin(FUNCDMTODEG(L8(SIZE(L8))))-sin(PublLat)*cos(Dist))/(sin(Dist)*cos(PublLat)))) THEN            L0(0):=ROUND(6371*π/180*Dist,-3)+" km  error°";           ELSE            θ:=360-acos((sin(FUNCDMTODEG(L8(SIZE(L8))))-sin(PublLat)*cos(Dist))/(sin(Dist)*cos(PublLat)));            L0(0):=ROUND(6371*π/180*Dist,-3)+" km  "+ROUND(θ,0)+"°";           END;          END;         END;        END;       END;      END;     END;    END;   END;  END; END;END;END;

I tried to build it recursively, but this is my first encounter with recursion so I can't find syntax which works.

I tried it with another approach where I packed everything as text and then I execute it via EXPR(...) and it works. Dissadvantage is unreadable code and everything must be in one string otherwise FOR and END will collapse.

Can anybody show me how build nested loops and IFs if I don't know their quantity beforehand?

Some screenshots:

Geocaching Coords Solver, Number of triangles Puzzle
12-17-2015, 07:28 AM (This post was last modified: 12-17-2015 07:30 AM by chromos.)
Post: #2
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?

Geo Coords Solver.hpprgm (Size: 20 KB / Downloads: 3) Because there is five attachments limit, I give program for interested people into this post.
(Programm counts distance and bearing correctly for North East hemisphere and can solve for six inequalities and four variables only.)

Geocaching Coords Solver, Number of triangles Puzzle
12-17-2015, 11:50 AM
Post: #3
 Didier Lachieze Senior Member Posts: 1,365 Joined: Dec 2013
RE: (Recursive) nested loops and IFs?
You can replace the nested IFs with a single IF which will work for any size of L5.

Replace:
Code:
      IF (EXPR(L5(1))>=0 AND EXPR(L5(1))<=9) THEN       IF (EXPR(L5(2))>=0 AND EXPR(L5(2))<=9) THEN        IF (EXPR(L5(3))>=0 AND EXPR(L5(3))<=9) THEN         IF (EXPR(L5(4))>=0 AND EXPR(L5(4))<=9) THEN          IF (EXPR(L5(5))>=0 AND EXPR(L5(5))<=9) THEN           IF (EXPR(L5(6))>=0 AND EXPR(L5(6))<=9) THEN            [...]           END;          END;         END;        END;       END;       END;

By:
Code:
      IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5)) THEN        [...]      END;

Thanks for publishing your program, do you have some data samples that could be used to test it?
12-17-2015, 12:15 PM (This post was last modified: 12-17-2015 12:26 PM by chromos.)
Post: #4
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
Thank you Didier, I'll try your code.

I am testing my program on this cache:

Bysterske vyhlidky

This is unfortunately in czech language so importatnt data are:

Coords to solve:
N 50°35.(A+1) (B) (B-A-4)
E 015°24.(C-14) (D-8) (C-D+3)

Enter it as showed (without N and E letters and without ° character and without parentheses).

Digit sum for solved coords is 49.

Starting published coordinates are:
N 50° 36.404 E 015° 24.120
Enter it as showed (without N and E letters and without ° character).

I don't know if you are geocacher, so expressions in parentheses aren't multiplied with each other. Instead of, every pair of parentheses is one digit to solve.

Meanwhile I updated my program (for example there wasn't handled case when no coords were found.

Geocaching Coords Solver, Number of triangles Puzzle
12-17-2015, 04:17 PM (This post was last modified: 12-17-2015 04:45 PM by Didier Lachieze.)
Post: #5
 Didier Lachieze Senior Member Posts: 1,365 Joined: Dec 2013
RE: (Recursive) nested loops and IFs?
Here is a way to replace the nested loops by a single one using a list (LoopIdx) to store the different loop index values. LoopIdx is replacing Loop1, Loop2, Loop3 & Loop4 and allows for a dynamic number of variables as it is sized according to the size of your L3.

PHP Code:
SUBRFROMTO()BEGIN LOCAL n, Idx, LoopIdx, s; PRINT();  PRINT("                        Completed: 0 %");LoopIdx:=L3;s:=SIZE(L3);FOR Idx FROM 1 TO ΠLIST(L4-L3) DO  TempList:={};  FOR Loop FROM 1 TO SIZE(L2) DO   EXPR(L2(Loop)+":=LoopIdx("+STRING(Loop)+ ")");   TempList(0):=EXPR(L2(Loop));  END;  Temp:=0;  IF DigitSum>0 THEN   FOR Loop FROM 1 TO SIZE(L5) DO    Temp:=Temp+EXPR(L5(Loop));   END;  END;  IF (NOT(DigitSum>0) OR Temp==DigitSum-SubDigitSum) THEN   IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5)) THEN    L8(0):=""+EXPR(L1(1))+EXPR(L1(2))+"° "+EXPR(L1(3))+EXPR(L1(4))+"."+EXPR(L1(5))+EXPR(L1(6))+EXPR(L1(7));    L9(0):=""+EXPR(L1(8))+EXPR(L1(9))+EXPR(L1(10))+"° "+EXPR(L1(11))+EXPR(L1(12))+"."+EXPR(L1(13))+EXPR(L1(14))+EXPR(L1(15));    L6(0):=TempList;    Dist:=acos(sin(PublLat)*sin(FUNCDMTODEG(L8(0)))+cos(PublLat)*cos(FUNCDMTODEG(L8(0)))*cos(FUNCDMTODEG(L9(0))-PublLon));    IFERR(acos((sin(FUNCDMTODEG(L8(0)))-sin(PublLat)*cos(Dist))/(sin(Dist)*cos(PublLat)))) THEN     L0(0):=ROUND(6371*π/180*Dist,-3)+" km  error°";    ELSE     θ:=360-acos((sin(FUNCDMTODEG(L8(0)))-sin(PublLat)*cos(Dist))/(sin(Dist)*cos(PublLat)));     L0(0):=ROUND(6371*π/180*Dist,-3)+" km  "+ROUND(θ,0)+"°";    END;   END;  END;  //increment LoopIdx  LoopIdx(s):=LoopIdx(s)+1;  FOR n FROM s DOWNTO 1 DO    IF LoopIdx(n)>L4(n) THEN      LoopIdx(n):=L3(n);      LoopIdx(n-1):= LoopIdx(n-1)+1;      IF n==2 THEN       PRINT();        PRINT("                              Completed: "+ROUND(100*(1+LoopIdx(1)-L3(1))/(1+L4(1)-L3(1)),0)+" %");      END;    END;  END;END;END;

It is working with the test case you provided.
I'm not a geocacher but I know some people who are and may be interested by your program.

• added some local variables : n, Idx, LoopIdx, s
• initialized LoopIdx to L3 : list of the start values, and s to the size of L3
• replaced the nested FOR loops by a single one from 1 to the total of loops to be done: product of differences between upper and lower values in L4 and L3
• modified the expression in the first loop to replace Loopi by LoopIdx(i)
• added the increment of the LoopIdx values at the end of the FOR loop, including the progress PRINT instruction
12-17-2015, 08:20 PM (This post was last modified: 12-17-2015 08:25 PM by chromos.)
Post: #6
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
Thank you, Didier, you helped me very much.

PHP Code:
IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5)) THEN  [...]END;
1) Lines above works perfectly. I tried to understand them, but not much successfuly. ΠLIST is importatnt or it may be ∑LIST too? I know, I could try it myself. :-)

2) Nested loops: I didn't try your code yet, but I will. There is ΠLIST again so I should study its usability much more.

-----
Meanwhile I updated my program again and I replaced nested loops with strings executed via EXPR. Fortunately, code isn't unreadable (I moved lines within FOR-DO and END; into subroutine which helped).

Before:
PHP Code:
FOR Loop1 FROM L3(1) TO L4(1) DO FOR Loop2 FROM L3(2) TO L4(2) DO  FOR Loop3 FROM L3(3) TO L4(3) DO   FOR Loop4 FROM L3(4) TO L4(4) DO    [...]   END;  END; END; PRINT();  PRINT("                        Completed: "+ROUND(100*(1+Loop1-L3(1))/(1+L4(1)-L3(1)),0)+" %");END;

After (I declared Loop1, ... , Loop20 for sufficient headroom):
PHP Code:
//nested loops preparationTempFor:="";TempEnd:="";TempBody:="";FOR Loop FROM 2 TO SIZE(L2) DO TempFor:=TempFor+"FOR Loop"+STRING(Loop)+" FROM L3("+STRING(Loop)+") TO L4("+STRING(Loop)+") DO "; TempEnd:=TempEnd+"END; ";END;TempBody:="SUBRVALIDCOORDS();";//end of preparationFOR Loop1 FROM L3(1) TO L4(1) DO EXPR(TempFor+TempBody+TempEnd); PRINT();  PRINT("                        Completed: "+ROUND(100*(1+Loop1-L3(1))/(1+L4(1)-L3(1)),0)+" %");END;
Maybe it isn't elegant solution, but at least I know what I'm doing.

I found interesting feature (or is it bug?): list variable cannot be used as FOR-DO counter (which is a pity).

Example:
PHP Code:
LoopList:=MAKELIST(0,X,1,15);PRINT(LoopList); // → {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}FOR LoopList(1) FROM L3(1) TO L4(1) DO  PRINT(LoopList); // → 0 (and program stops.)END;

----
It seems the program works now with any number of inequalities and with number of variables up to 20 which is more than enough. I will test it on more caches before uploading.

Thank you again very much, Didier.

Geocaching Coords Solver, Number of triangles Puzzle
12-18-2015, 08:06 AM (This post was last modified: 12-18-2015 09:35 AM by Didier Lachieze.)
Post: #7
 Didier Lachieze Senior Member Posts: 1,365 Joined: Dec 2013
RE: (Recursive) nested loops and IFs?
(12-17-2015 08:20 PM)chromos Wrote:
PHP Code:
IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5)) THEN  [...]END;
1) Lines above works perfectly. I tried to understand them, but not much successfully. ΠLIST is important or it may be ∑LIST too? I know, I could try it myself. :-)

In this case you have to use ΠLIST: ΠLIST(list) returns the product of the list elements which is the equivalent of a Boolean AND while ∑LIST(list) returns the sum of the list elements which is the equivalent of a Boolean OR.

Nested IF conditions can be replaced by ANDs:

PHP Code:
IF (EXPR(L5(1))>=0 AND EXPR(L5(1))<=9) THEN  IF (EXPR(L5(2))>=0 AND EXPR(L5(2))<=9) THEN    IF (EXPR(L5(3))>=0 AND EXPR(L5(3))<=9) THEN

is the same as:

PHP Code:
IF (EXPR(L5(1))>=0 AND EXPR(L5(1))<=9) AND (EXPR(L5(2))>=0 AND EXPR(L5(2))<=9) AND (EXPR(L5(3))>=0 AND EXPR(L5(3))<=9) THEN

EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5) returns a list with the result of the test for each element of L5, either 0 (false) or 1 (true).
Then ΠLIST returns the product (AND) of all these results: 0 (false) if at least one is false and 1 (true) if all are true.
As we work with lists this is not tied to the number of variables.

(12-17-2015 08:20 PM)chromos Wrote:  2) Nested loops: I didn't try your code yet, but I will. There is ΠLIST again so I should study its usability much more.

Here L4-L3 returns a list of the differences between the elements of L4 and L3, so ΠLIST(L4-L3) returns the product of these differences which gives the total number of loops to do.
12-18-2015, 10:25 PM (This post was last modified: 12-18-2015 10:58 PM by chromos.)
Post: #8
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
This...
(12-18-2015 08:06 AM)Didier Lachieze Wrote:  ... ΠLIST(list) returns the product of the list elements which is the equivalent of a Boolean AND...
... and this...
Quote:... As we work with lists this is not tied to the number of variables...
... is explanation I needed. Thank you.

----

I updated Geo Coords Solver again, most visible thing is better workflow.

On this link is czech geocache -you can use e.g. google translator, so you can try to solve it. :-) (Hint - closest coordinates are usually the right ones).

Geocaching Coords Solver, Number of triangles Puzzle
12-18-2015, 10:40 PM
Post: #9
 Didier Lachieze Senior Member Posts: 1,365 Joined: Dec 2013
RE: (Recursive) nested loops and IFs?
One more thing :
PHP Code:
IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9",L5)) THEN  [...]END;

can be replaced by :
PHP Code:
IF ΠLIST(EXPR(L5+">=0") AND EXPR(L5+"<=9")) THEN  [...]END;
12-18-2015, 11:32 PM
Post: #10
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
I had unhandled A/B type expressions, so I modified your previous code into...
PHP Code:
IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9 AND FP(EXPR(&1))==0",L5)) THEN
... and it works.
PHP Code:
IF ΠLIST(EXPR(L5+">=0") AND EXPR(L5+"<=9") AND EXPR(FP(L5)+"==0")) THEN
... it doesn't work. Your unmodified code works.

Geocaching Coords Solver, Number of triangles Puzzle
12-19-2015, 12:00 AM
Post: #11
 Didier Lachieze Senior Member Posts: 1,365 Joined: Dec 2013
RE: (Recursive) nested loops and IFs?
(12-18-2015 11:32 PM)chromos Wrote:  In your new code...
PHP Code:
IF ΠLIST(EXPR(L5+">=0") AND EXPR(L5+"<=9") AND EXPR(FP(L5)+"==0")) THEN
... it doesn't work. Your unmodified code works.

L5 is a list of strings, not a list of reals so FP(L5) doesn't work.
This should work but it starts to look a bit ugly:
PHP Code:
IF ΠLIST(EXPR(L5+">=0") AND EXPR(L5+"<=9") AND EXPR("FP("+L5+")==0")) THEN
12-19-2015, 12:05 AM
Post: #12
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
You're right. I'm too tired from it probably. :-)

Geocaching Coords Solver, Number of triangles Puzzle
01-17-2017, 11:46 AM (This post was last modified: 01-17-2017 11:48 AM by chromos.)
Post: #13
 chromos Member Posts: 193 Joined: Jun 2015
RE: (Recursive) nested loops and IFs?
Does anybody know why this stopped working in latest Prime firmware?
(in L5 are stringed expressions, something like "(A+B)").

PHP Code:
IF ΠLIST(EXPR(L5+">=0") AND EXPR(L5+"<=9") AND EXPR("FP("+L5+")==0")) THEN

I replaced it with:

PHP Code:
IF ΠLIST(EXECON("EXPR(&1)>=0 AND EXPR(&1)<=9 AND FP(EXPR(&1))==0",L5)) THEN
... and this works, so I don't need another solution. I'm just curious why former code no longer works.

Geocaching Coords Solver, Number of triangles Puzzle
 « Next Oldest | Next Newest »

User(s) browsing this thread: 1 Guest(s)