Collect-like and J style

For the Compleat Fan
Locked
Excalibor
Posts: 47
Joined: Wed May 26, 2004 9:48 am
Location: Madrid, Spain

Collect-like and J style

Post by Excalibor »

Greetings!

LTNS, actually... I'm unrusting myself with an interesting page I found, essays in J language ( http://www.jsoftware.com/jwiki/Essays ).

I am trying the first one, the Collatz conjecture, http://www.jsoftware.com/jwiki/Essays/C ... Conjecture , and I was wondering how do you do in idiomatic newlisp the kind of collect that's displayed there, which is a kind of fold operation:

"apply function recursively and accumulate the results until it returns nil..."
"

I haven't really thought a lot about it yet, and my first attempt, which I offer below, is pretty naive, although it works...

anyone up to discuss about this?

thanks!

PS- the code:

Code: Select all

(context 'collatz)

(define (collatz1 n)
  (if (<= n 1)
	nil
	(if (= (mod n 2) 0)
	  (/ n 2)
	  (+ 1 (* 3 n)) ) ) )

(define (collatz:collatz n)
  (let ((ret '()))
	(do-while (> n 1)
		(setq n (collatz1 n))
		(push n ret -1) )
	ret ) )

(context 'MAIN)

> (collatz:collatz 9)
(28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)
[/code]

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Here is a proper recursive solution:

Code: Select all

; recursive solution
(define (collatz n)
    (let (result '())
        (if (= n 1)
            (append result '(1))
            (begin
                (set 'k (if (= (% n 2) 0)
                    (/ n 2)
                    (+ 1 (* 3 n))))
                (set 'result (cons n (collr k)))))))

(collatz 9) =>
(9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)
but the link doesn't really describe it as a recursive solution and an iterative is about 3 times faster and shorter too:

Code: Select all

; non-recursive solution
(define (collatz n)
    (let (result (list n))
        (do-until (= n 1)
            (set 'n (push (if (= (% n 2) 0)
                        (/ n 2)
                        (+ 1 (* 3 n))) result -1)))
        result))

(collatz 9) =>
(9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)
the result sequence should also contain the first value

Lutz

ps: good to see you here Excalibor (for those who do not know, Excalibor contributed the orginal Vi syntax file).

Excalibor
Posts: 47
Joined: Wed May 26, 2004 9:48 am
Location: Madrid, Spain

Post by Excalibor »

Lutz,

thanks for the help, it was pretty, well, helpful... :-)

Below I provide a 'collect' function that does kind-of foldr as I'd like to...

crude, but it could be useful:

Code: Select all

(define (collect f n)
  (let ((done false) (result (list n)))
    (do-while (nil? done)
      (begin
        (setq n (f n))
        (if (nil? n)
          (set 'done true)
          (push n result -1) ) ) )
  result ) )
This allows to write:

Code: Select all

> (collect collatz:collatz1 9)
(9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1)
which is kinda nice... :-)

anyway... it looked like an interesting problem to try in different environments, the article goes on with pretty interesting stuff (even if J is almost like line-noise!)...

thanks again!
dwd

PS- maybe a macro would be more useful, but I'm not really sure... If the function returns nil as it's 'termination' value, it's okay this way, but things better converge rather fast, or the stack would be smashed... anyway, it works for the time being... :-)

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

Excalibor wrote:

Code: Select all

(define (collect f n)
  (let ((done false) (result (list n)))
    (do-while (nil? done)
      (begin
        (setq n (f n))
        (if (nil? n)
          (set 'done true)
          (push n result -1) ) ) )
  result ) )
Just a note: there is no 'false' in newLISP - use 'nil' in (done false).

Fanda

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

also instead of:

Code: Select all

(do-while (nil? done) ... )
do:

Code: Select all

(do-until done ...)
Lutz

Locked