Here is an iterative example of a procedure computing the fibonacci sequence in SICP. The idea is:
a = fib(n+1) = a+b
b = fib(n) = a
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
Looking at it deeper, I don't understand why continuing the computation towards fib(n+1) is necessary. I found we could have written.
;; a and b are first and second integers respectively
;; in the recursive call, b would be replaced by a+b because it is the next number in the sequence
;; so now a will be replaced by the previous value of b because it is the previous value.
(define (fib2 n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter b (+ a b) (- count 1))))
Now, I really think the first example, the one continuing up to n+1 is really redundant. I don't understand why is that necessary. What's wrong with my proposed iterative example?
Bot procedures produce correct result. However, the first one retains the relationship between a and b: a is Fib(i+1) and b is Fib(i) where i=n-count. The second method uses the first iteration to swap a and b around, thus introducing one redundant iteration. This can be seen by taking the trace of procedures:
> (define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 1 1 2)
>(fib-iter 2 1 1)
>(fib-iter 3 2 0)
<2
2
> (define (fib-iter a b count)
(if (= count 0)
b
(fib-iter b (+ a b) (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 1 0 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2
What you actually want is something like this:
> (define (fib n)
(if (zero? n)
0
(fib-iter 0 1 (- n 1))))
(define (fib-iter a b count)
(if (zero? count)
b
(fib-iter b (+ a b) (- count 1))))
> (trace fib-iter)
> (fib 3)
>(fib-iter 0 1 2)
>(fib-iter 1 1 1)
>(fib-iter 1 2 0)
<2
2
Notice, there is one less iteration. However, I'm doing extra work in procedure fib.
There is nothing wrong. The two approaches give the same result.
#lang racket
(define (fib n)
(fib-iter 1 0 n))
(define (fib-iter a b count)
(if (= count 0)
b
(fib-iter (+ a b) a (- count 1))))
(define (fib2 n)
(fib-iter2 1 0 n))
(define (fib-iter2 a b count)
(if (= count 0)
b
(fib-iter2 b (+ a b) (- count 1))))
(define xs '(0 1 2 3 4 5 6 7 8 9 10))
(map fib xs)
(map fib2 xs)
The output is:
'(0 1 1 2 3 5 8 13 21 34 55)
'(0 1 1 2 3 5 8 13 21 34 55)
This shows that you are indeed computing the same sequence.
Related
I am looking on how to translate this pseudocode to idiomatic scheme:
for c in range(1, 1000):
for b in range(1, c):
for a in range(1, b):
do something if condition is true
Your pseudocode is translated into Scheme straightforwardly enough as a sequence of nested named lets, as
(let loopc ((c 1)) ; start the top loop with c = 1,
(if (> c 1000) ; if `c > 1000`,
#f ; exit the top loop ; or else,
(let loopb ((b 1)) ; start the first-nested loop with b = 1,
(if (> b c) ; if `b > c`,
(loopc (+ c 1)) ; end the first-nested loop, and
; continue the top loop with c := c+1 ; or else,
(let loopa ((a 1)) ; start the second-nested loop with a = 1,
(if (> a b) ; if `a > b`,
(loopb (+ b 1)) ; end the second-nested loop, and
; continue the first-nested loop with b := b+1
(begin ; or else,
(if condition ; if condition holds,
(do_some a b c) ; do something with a, b, c,
#f) ; and then,
(loopa (+ a 1)) ; continue the second-nested loop with a := a+1
)))))))
Of course it's a bit involved and error prone. On the other hand it is easy to shortcut the innermost loop (on as) and restart the top one (on cs) directly, by calling loopc from within loopa (always in tail position, NB !), should the need arise.
For example, the above code is directly applicable to the problem which you state in the comments, of finding a Pythagorean triplet which sums to 1000. Moreover, when you've hit upon the solution, you can directly call (loopc 1001) to immediately exit the whole threefold nested loops construction.
As a side note,
for c in range(3, 1000):
for b in range(2, c):
for a in range(1, b):
if a**2 + b**2 == c**2 and a + b + c == 1000:
print(a * b * c)
is not the most efficient solution. That would be, at least, first,
for c in range(3, 1000):
for b in range(2, 1000-c-1):
for a in range(1, 1000-c-b):
if a**2 + b**2 == c**2 and a + b + c == 1000:
print(a * b * c)
and furthermore,
for c in range(3, 1000):
c2 = c**2
for b in range(2, 1000-c-1):
a = 1000-c-b
if a**2 + b**2 == c2:
print(a * b * c)
# exit the loops
It is pretty easy to express any kind of loop (and indeed much more general control structures) in Scheme. For instance if you want a loop which simply counts you can do it like this:
(let loop ([i 0])
(if (>= i 10)
(values)
(begin
(display i)
(loop (+ i 1)))))
And you can obviously nest these.
But this is a lot less easy to read than, for instance, what you would write in Python:
for i in range(10):
print(i)
Well, OK. But Lisp-family languages are about building languages: if the syntax you want does not exist, you make it exist. Here is an example of doing that:
(define-syntax nloop*
;; Nested numerical loop
(syntax-rules ()
[(_ () form ...)
(begin form ...
(values))]
[(_ ((variable lower-inclusive upper-exclusive) more ...) form ...)
(let loop ([variable lower-inclusive])
(if (< variable upper-exclusive)
(begin
(nloop* (more ...) form ...)
(loop (+ variable 1)))
(values)))]
[(_ ((variable start-inclusive end-exclusive step) more ...) form ...)
(let ([cmp? (if (>= step 0) < >)])
(let loop ([variable start-inclusive])
(if (cmp? variable end-exclusive)
(begin
(nloop* (more ...) form ...)
(loop (+ variable step)))
(values))))]))
And now:
> (nloop* ((i 0 10))
(print i))
0123456789
But also
> (nloop* ((i 0 10)
(j 20 0 -4))
(displayln (list i j)))
(0 20)
(0 16)
(0 12)
(0 8)
(0 4)
...
(9 20)
(9 16)
(9 12)
(9 8)
(9 4)
So this nloop* construct I have just invented will do perfectly general numerical loops, including nested ones (this is why the *: nloop (which does not exist) would loop in parallel).
Of course in industrial-strength scheme-derived languages like Racket there are already constructs for doing this:
(for ([i (in-range 10)])
(for ([j (in-range 20 0 -4)])
(displayln (list i j))))
would be the idiomatic Racket way of doing this. But for and all its variants and infrastructure are just language constructs that you could in principle write yourself in a very bare-bones Scheme.
These are languages which are designed for building languages.
There are incredible many ways to cope with your problem. Here is the simplest that passed in my mind now:
(define iota
(lambda (n k)
((lambda (s) (s s 1))
(lambda (s x)
(k x)
(or (= n x)
(s s (+ x 1)))))))
(iota 1000
(lambda (c)
(iota c
(lambda (b)
(iota b
(lambda (a)
(newline)
(display a) (display " ")
(display b) (display " ")
(display c) (display " ")))))))
If the initial interval of c is 1..3 instead of 1..1000, the nested code will contain these values of (a b c):
a b c
1 1 1
1 1 2
1 2 2
2 2 2
1 1 3
1 2 3
2 2 3
1 3 3
2 3 3
3 3 3
I am trying to change the elements on a list based on a criteria. Let's say I have a list,
L = '(0 1 1 0 0). I want only the first "zero" found in this list as "zero", and for any other "zero" in that list, I want them to be 1. So the list of my example will become L = '(0 1 1 1 1). This is what I have done so far,
(let dLoop ((L '(0 1 1 0 0))
(i 0)
(j 1))
(if (and (<= i (length L)) (<= j (- (length L) 1)))
(begin
(if (zero? (list-ref L i))
(begin
(cond
[(zero? (list-ref L j)) (list-set L j 1)]
[else (dLoop L i (add1 j))]
)
)
(dLoop L (add1 i) (add1 j))))
L))
This only returns, L = '(0 1 1 1 0)
For some reason, the moment it finds the first duplicate zero, the code terminates! I would really appreciate some insights regarding this issue
In your (cond) expression, you don't have a recursive call to dLoop if (zero? (list-ref L j)) case evaluates. This causes the (cond) to return, then the (begin) returns and finally exits out of you (let) expression. Adding on to what Lazer said however, this is kinda not the standard scheme approach, let alone very efficient since (list-ref) on linked-lists is O(n) each time. Perhaps try something like:
(define (find-and-map-rest lst pred f)
(cond [(null? lst) lst]
;; found the thing
[(pred (car lst)) (cons (car lst)
(map f (cdr lst)))]
;; didn't find the thing... yet
[else (cons (car lst)
(find-and-map-rest (cdr lst)
pred f))]))
(define (zero->one x)
(if (zero? x) 1 x))
(find-and-map-rest '(0 1 1 0 0) zero? zero->one)
Realistic code is probably not going to do all of that consing for a task like this. All that the code really needs to do is find the first zero, take the first part of the list up to and including that zero, and append it to a list of ones as long as the rest of the input list. If no zero is found, the result is just the input list:
(define (f xs)
(let ((rest (member 0 xs)))
(if rest
(let ((ones-count (sub1 (length rest))))
(append (take xs (- (length xs) ones-count))
(make-list ones-count 1)))
xs)))
Sample interaction:
scratch.rkt> (f '(0))
'(0)
scratch.rkt> (f '(1))
'(1)
scratch.rkt> (f '(0 1 1 0 0))
'(0 1 1 1 1)
scratch.rkt> (f '(1 1 0 1 1 1 0 0 1 0 1 0))
'(1 1 0 1 1 1 1 1 1 1 1 1)
I want to apply the function (* x 2) to every other element in a list and return the entire list using the loop macro. The solution I've come up with so far is this:
(defun double-every-other (xs)
(loop for x in xs by #'cddr collect (* x 2)))
However, this will double every other element and only return the elements that were doubled, so if I executed:
(double-every-other '(1 2 3 4))
The result would be:
'(4 8)
But I want the result to be:
'(1 4 3 8)
Is there a way I can do this using (loop)?
Another version with less math:
(defun double-every-other (list)
(loop
for (a b) on list by #'cddr
collect a
when b collect (* b 2)))
(double-every-other '(1 2 3 4))
=> (1 4 3 8)
(double-every-other '(1 2 3 4 5))
=> (1 4 3 8 5)
Obviously, you won't be able to abstract the N as easily as the other answer (if you are thinking "macro", stop now). Here we iterate using the on keyword, which means each sublist is visited in turn. Since we use by #'cddr, every other sublist is skipped. The destructuring syntax (a b) binds the first and second elements of the visited list.
You can for instance test an integer increasing while the list is scanned:
(defun double-every-other (xs)
(loop for x in xs
for i from 1
if (oddp i)
collect x
else collect (* x 2)))
(defun double-every-other (xs)
(loop for x in xs
for doublep = nil then (not doublep)
collect (if doublep (* x 2) x)))
another version, without loop at all:
(defun make-cycled (&rest items)
(setf (cdr (last items)) items))
(mapcar #'funcall
(make-cycled #'identity (lambda (x) (* 2 x)))
'(10 9 8 7 6 5 4 3))
;;=> (10 18 8 14 6 10 4 6)
You could use the loop "on" list iteration primitive. This takes a list of loop variables that will be "smeared" across the list, with the last being the tail of the entire remaining list. The conditional loop for is necessary to avoid multiplying nil if we have an odd number of arguments.
(defun double-every-other (list)
(loop for (single double tail) on list by #'cddr
if (null double)
collect single
else
append (list single (* 2 double))))
And if we try to run it:
* (double-every-other '(1 2 3 4 5))
(1 4 3 8 5)
I am a newbie in clojure and came across a problem which says, multiply first n elements in a sequence by some number 'x' (non recursively). So for example
(multiply-n-by-x [1 2 3 4 5] 2 10) => [10 20 30 4 5]
So here i understood that i need to loop over the sequence n times and then stop, but i am unable to do that. If someone could guide me on how to do about it, it would be great.
Same as Shawn's answer but with destructuring and split-at (a bit less redundant):
(defn multiply-n-by-x [s n x]
(let [[s1 s2] (split-at (inc n) s)]
(concat (map #(* x %) s1) s2)))
I think the easy way is :
(defn multiply-n-by-x [seq n m]
(concat (map #(* m %) (take (inc n) seq)) (drop (inc n) seq) )
)
This does what you want:
(defn multiply-n-by-x [sq n x]
(for [i (range (count sq)) ;for i in range 0 to number of elements in sq
:let [element (nth sq i)]] ;bind element to the nth item in sq
(if (<= i n) ;if index below n, return the multiplied element, otherwise return the element as is
(* x element)
element)))
whatever you return inside the for macro gets put into a sequence so the end result is collection.
Lazy sequences capture delayed recursion. take, drop, split and for are lazy constructions. We can avoid them by computing the altered head of the sequence eagerly, as follows:
(defn multiply-n-by-x [coll n x]
(loop [head [], coll coll, n n]
(if (and (seq coll) (>= n 0))
(recur (conj head (* (first coll) x)) (rest coll) (dec n))
(concat head coll))))
For example,
(multiply-n-by-x [1 2 3 4 5] 2 10)
;(10 20 30 4 5)
By the way, the convention in Clojure is to give the count of a slice, not the index of the final element, which is one less.
(range 3)
;(0 1 2)
Why does this code not print out the content of the array -
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(aref state x y))))
Here I am passing a 3x3 matrix which is built like this -
`(setq i (make-array '(3,3) :initial-contents '((0 1 3) (4 2 5) (7 8 6))))`
I am calling - (loopfn i)
Edit--------
#Greg
Thanks for pointing that out...
I had the following question..
Why does this print the output ...
(defun loopfn ()
(loop for x from 0 to 3 do
(if (eq x 2)(return (list x)))))
Where as this prints a nil...
(defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (eq x 2)(return (list x y))))))
I am calling
(loopfn)
Your code does not print anything. That's also what you want - usually.
But you want functions to return something useful.
So you need to understand the difference between printing and having a REPL printing a return value.
CL-USER > 3
3
Above returns 3. The Read-Eval-Print-Loop prints the return value.
CL-USER > (print 3)
3
3
Above prints a newline and then two times the 3. Why?
The first is the side-effect of the PRINT call which prints the newline and then its argument.
The second is the REPL printing the return value.
Note also the EQ is not for numeric comparisons. Use EQL instead.
See: http://www.lispworks.com/documentation/lw50/CLHS/Body/f_eql.htm
As for your second question, (return ...) is equivalent to (return-from NIL ...) so you just return from your inner LOOP into the outer one. Use this instead:
[11]> (defun loopfn ()
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(if (= x 2) (return-from loopfn (list x y))))))
[12]> (loopfn)
(2 0)
Another possibility is to collect more values than just one, as in
[36]> (defun loopfn ()
(loop for x from 0 to 2 nconc
(loop for y from 0 to 2
if (= y 2)
collect (list x y))) )
LOOPFN
[37]> (loopfn)
((0 2) (1 2) (2 2))
Your call to aref is getting the specified element, but you're not doing anything with it. You could stick it on to a list which is then returned:
(defun loopfn (state)
(let ((result '()))
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(setf result (cons (aref state x y) result))))
result))
or you could just print it out:
(defun loopfn (state)
(loop for x from 0 to 2 do
(loop for y from 0 to 2 do
(format t "~a~%" (aref state x y)))))
The former is far more useful ; you want to return things which can then be further processed, and anything that gets passed to the top level will be printed out for you.
As long as you are using LOOP you can easily gather up your values with COLLECT, APPEND, etc., which is the idiomatic way to do it.
This was neatly covered in this forum topic.
The outer loop has no clause which would cause a return value.
Some code examples from that thread:
(defun print-2d-array-as-table (array)
(loop for i from 0 below (array-dimension array 0)
do (loop for j from 0 below (array-dimension array 1)
do (princ (aref array i j))
(if (= j (1- (array-dimension array 1)))
(terpri)
(princ #\Space)))))
and one loop:
(defun print-2d-array-as-table (array)
(loop for i below (array-total-size array) do
(if (zerop (mod i (array-dimension array 0)))
(terpri)
(princ #\Space))
(princ (row-major-aref array i))))
For your second question, in the loop that doesn't print, (eq x 2) is never true. You have modified the loop bounds from 0 to 3 to 0 to 2, so x never reaches 2. Since there is no explicit (return ...) executed, the function returns nil.