Nested Loop in Visual Lisp

Nested Loop in Visual Lisp

Anonymous
Not applicable
2,857 Views
16 Replies
Message 1 of 17

Nested Loop in Visual Lisp

Anonymous
Not applicable

Hello Fellows,

 

Is there a possibility to create a nested loop with Visual Lisp?

Let's say I want to count to 3 with while loop and for every digit I want to count again to 3.

 

So I assume I will get such result:

"  1 1 2 3

   2 1 2 3

   3 1 2 3 "

 

But in fact when I build my while loop:

(defun nl ()
  	(setq i 0 x 0)
  	(while (< i 3)
		(while (< x 3)
			(setq x (+ x 1))
		  	(princ (strcat " " (itoa x) " "))
		)
		(setq i (+ i 1))
	  	(princ (strcat " " (itoa i) " "))
	)
  	(princ)
)

I get this result:

" 1 2 3 1 2 3 "

 

What do I do wrong?

0 Likes
Accepted solutions (2)
2,858 Views
16 Replies
Replies (16)
Message 2 of 17

Anonymous
Not applicable

Well, it seem's to me that the logic is wrong. If your actually getting that output then the nest is working, its just going to 3 for x and then exiting that loop then going to the encompassing while loop. Quick glance but I think you will want to rethink the logic, I dont think theres an issue with the looping.

0 Likes
Message 3 of 17

ronjonp
Mentor
Mentor

I would use repeat if you know how many iterations you want to do. If the first element is the only change then try something like this:

(setq i 0)
(repeat 3 (print (cons (setq i (1+ i)) '(1 2 3))))

 

 

Message 4 of 17

Kent1Cooper
Consultant
Consultant
Accepted solution

Maybe something like this [untested]?

(defun nl (/ i x ending)
  (setq i 0); not x here
  (while (< i 3)
(setq x 0 ending ""); reset for each line (while (< x 3) (setq
x (1+ x) ending (strcat ending " " (itoa x)) )
); while (setq i (1+ i)) (princ (strcat "\n" (itoa i) ending))
); while (princ) )
Kent Cooper, AIA
Message 5 of 17

Ajilal.Vijayan
Advisor
Advisor
Accepted solution

@Anonymous wrote:

So I assume I will get such result:

"  1 1 2 3

   2 1 2 3

   3 1 2 3 "

 

I get this result:

" 1 2 3 1 2 3 "

 

What do I do wrong?


You need to reset the 'x' variable value to 0 inisde the 'i' while loop and may need to move the 'i' print statement to top to print the 'i' value before 'x' values

(defun nl ()
  	(setq i 0 x 0)
  	(while (< i 3)
		(setq i (+ i 1))
		(princ (strcat "\n " (itoa i) " "))
		(while (< x 3)
			(setq x (+ x 1))
		  	(princ (strcat " " (itoa x) " "))
		)
		(setq x 0)
	)
  	(princ)
)
Message 6 of 17

Kent1Cooper
Consultant
Consultant

@Kent1Cooper wrote:

Maybe something like this [untested]?....


Now tested:

 

Command: (nl)

1 1 2 3
2 1 2 3
3 1 2 3

 

And here's a version for use with any  number, taken as an argument to the function:

(defun nl (n / i x ending)
  (setq i 0); not x here
  (while (< i n)
    (setq x 0 ending ""); reset for each line
    (while (< x n)
      (setq
        x (1+ x)
	ending (strcat ending " " (itoa x))
      )
    ); while
    (setq i (1+ i))
    (princ (strcat "\n" (itoa i) ending))
  ); while
  (princ)
)

which gives results like these:

 

Command: (nl 4)

1 1 2 3 4
2 1 2 3 4
3 1 2 3 4
4 1 2 3 4

 

Command: (nl 7)

1 1 2 3 4 5 6 7
2 1 2 3 4 5 6 7
3 1 2 3 4 5 6 7
4 1 2 3 4 5 6 7
5 1 2 3 4 5 6 7
6 1 2 3 4 5 6 7
7 1 2 3 4 5 6 7

 

[I tried it with the argument up to 100, which worked as expected, but I won't burden the website with the result....]

Kent Cooper, AIA
Message 7 of 17

dbroad
Mentor
Mentor

If the point is to get the stated numbered strings in a particular order, then approaching it as a nested problem is the wrong approach (aka insane).  It increases the program workload by a factor of n. Consider this instead, which uses two loops. The second loop uses the results of the first instead of recreating it n times.

(defun nl(n / str x)
  (setq str "" x n)
  (repeat n
    (setq str (strcat (itoa x) " "str )
	  x (1- x)))
  (setq x 1)
  (repeat n
    (princ (strcat "\n" (itoa x)" " str))
    (setq x (1+ x)))
  (princ))
Architect, Registered NC, VA, SC, & GA.
Message 8 of 17

ronjonp
Mentor
Mentor

Just curious .. what problem are you applying this to?

0 Likes
Message 9 of 17

ronjonp
Mentor
Mentor

@dbroad wrote:

If the point is to get the stated numbered strings in a particular order, then approaching it as a nested problem is the wrong approach (aka insane).  It increases the program workload by a factor of n. Consider this instead, which uses two loops. The second loop uses the results of the first instead of recreating it n times.

(defun nl(n / str x)
  (setq str "" x n)
  (repeat n
    (setq str (strcat (itoa x) " "str )
	  x (1- x)))
  (setq x 1)
  (repeat n
    (princ (strcat "\n" (itoa x)" " str))
    (setq x (1+ x)))
  (princ))

Agreed that you should not recreate the same data within the loop over and over. Curiously enough yours and Kent's functions when tested with 500 are very similar in speed:

    (DB-NL 500).....68891 / 1.06 <fastest>
    (KC-NL 500).....72937 / 1.00 <slowest>
0 Likes
Message 10 of 17

hak_vz
Advisor
Advisor

To solve this I'm using a function from my matrix and fractions library that was posted

here but didn't receive any response on the forum.

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/sharing-my-matrix-and-fractions-libr... 

From this I use function create_ordered_vector.

 

(defun create_ordered_vector (n start step / r i) (setq i 0)(repeat n (setq r (cons (+ start (* i step)) r) i (+ i 1))(reverse r)))
(defun c:whatever (/ n step start base ret)
(setq
    n (getint "\nNumber of elements>")
    step (getint "\nIteration step>")
    start (getint "\nStart from >")
    base (create_ordered_vector n start step)
)
(foreach el base (setq ret (cons(cons el base) ret)))
(reverse ret)
)

For a various combination of start value, iteration step, and number of elements you get

 

whatever 4 1 1  
    (1 1 2 3 4)
    (2 1 2 3 4)
    (3 1 2 3 4)
    (4 1 2 3 4)

whatever 5 2 3
    (3 3 5 7 9 11)
    (5 3 5 7 9 11)
    (7 3 5 7 9 11) 
    (9 3 5 7 9 11)
    (11 3 5 7 9 11)
 
 
whatever 5 -3 10

(10 10 7 4 1 -2)
(7 10 7 4 1 -2)
(4 10 7 4 1 -2)
(1 10 7 4 1 -2)
(-2 10 7 4 1 -2)

Hope this will help you

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 11 of 17

Anonymous
Not applicable

This solution is simple and gives expected result, though it's not iterating within "inner loop".

0 Likes
Message 12 of 17

Anonymous
Not applicable

This solution is perfect! It's simply iterating within inner loop and appends the result to the outer loop. Exactly what I was looking for! Thank you!

0 Likes
Message 13 of 17

Anonymous
Not applicable

Thank you for feedback!

0 Likes
Message 14 of 17

Anonymous
Not applicable

I want to create a 2d array of hatch entities. Each hatch with higher R G or B color value.

 

Here's my first post explaining what am I trying to achieve:

 

https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/simple-routine-to-create-an-array-of...

0 Likes
Message 15 of 17

Anonymous
Not applicable

Thank you for this piece of code!

It's very elegant.

0 Likes
Message 16 of 17

dbroad
Mentor
Mentor

@ronjonp Interesting.  I imagine that is because most of the testing time is taken up in the princ statements. 

Architect, Registered NC, VA, SC, & GA.
0 Likes
Message 17 of 17

ronjonp
Mentor
Mentor

@dbroad Removed the princ ... bingo! 🙂

    (DB-NL 500).......1250 / 190.00 <fastest>
    (KC-NL 500).....237500 / 1.00 <slowest>
0 Likes