How to use double do loop in Scheme? - scheme

I want to use "do" command to show(1 1)(1 2)(1 3)(2 1)(2 2)(2 3)(3 1)(3 2)(3 3)
and my code is below:
(lambda ( )
(define a 1)
(define b 1)
(do ((a 1 (+ a 1))) (= a 3)
(do ((b 1 (+ b 1))) (= b 3)
(display a b)
)))
But this only show3as the result. Did I do something wrong? How should I correct it?
To Michael Vehrs,
Thank a lot, it really works! But I'm still confusing about the exit condition. I tried to change the>in your code to=and it shows(1 1)(1 2)(2 1)(2 2). Is it because it stops when a = 3 so it won't print?
So "list" command can combine several variables. But how about "newline" command? I tried to remove it and it just add another () in the last.
Thank you for the answer. I'm a new Scheme learner trying to use it on TracePro. Do you have any tip(book, Youtube video, website) for me about learning Scheme? Any advise would help.

A do loop is just syntax sugar for a recursive function. You might as well get used to write it directly. Here is a way to do it with one named let with two variables and an accumulator.
(let loop ((a 3) (b 3) (acc '()))
(cond ((zero? a) acc) ; finished
((zero? b) (loop (sub1 a) 3 acc)) ; b finsihed, reduce a and reset b
(else (loop a (sub1 b) (cons (list a b) acc))))) ; reduce b and add to front of acc
; ==> ((1 1) (1 2) (1 3) (2 1) (2 2) (2 3) (3 1) (3 2) (3 3))
Notice this makes the result in reverse order so it's optimal for lists that always are created in reverse order since that only can add new element in front.

You mean:
(lambda ()
(do ((a 1 (+ a 1)))
((> a 3) (newline))
(do ((b 1 (+ b 1)))
((> b 3))
(display (list a b))))))
Your code has a number of problems: The exit condition for the do loop is incorrect (and makes your procedure return 3). display takes a single object and an optional port as arguments. Defining your variables a and b is unnecessary, since the do construct defines new loop variables anyway.

Related

Combinations with pairs

I am trying to combine a list of pairs in scheme to get all possible combinations. For example:
((1 2) (3 4) (5 6)) --> ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
I've been able to solve it (I think) using a "take the first and prepend it to the cdr of the procedure" with the following:
(define (combine-pair-with-list-of-pairs P Lp)
(apply append
(map (lambda (num)
(map (lambda (pair)
(cons num pair)) Lp)) P)))
(define (comb-N Lp)
(if (null? Lp)
'(())
(combine-pair-with-list-of-pairs (car Lp) (comb-N (cdr Lp)))))
(comb-N '((1 2)(3 4)(5 6)))
; ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
However, I've been having trouble figuring out how I can use a procedure that only takes two and having a wrapper around it to be able to define comb-N by calling that function. Here it is:
(define (combinations L1 L2)
(apply append
(map (lambda (L1_item)
(map (lambda (L2_item)
(list L1_item L2_item))
L2))
L1)))
(combinations '(1) '(1 2 3))
; ((1 1) (1 2) (1 3))
I suppose the difficulty with calling this function is it expects two lists, and the recursive call is expecting a list of lists as the second argument. How could I call this combinations function to define comb-N?
difficulty? recursion? where?
You can write combinations using delimited continuations. Here we represent an ambiguous computation by writing amb. The expression bounded by reset will run once for each argument supplied to amb -
(define (amb . lst)
(shift k (append-map k lst)))
(reset
(list (list (amb 'a 'b) (amb 1 2 3))))
((a 1) (a 2) (a 3) (b 1) (b 2) (b 3))
how it works
The expression is evaluated through the first amb where the continuation is captured to k -
k := (list (list ... (amb 1 2 3)))
Where applying k will supply its argument to the "hole" left by amb's call to shift, represented by ... above. We can effectively think of k in terms of a lambda -
k := (lambda (x) (list (list x (amb 1 2 3)))
amb returns an append-map expression -
(append-map k '(a b))
Where append-map will apply k to each element of the input list, '(a b), and append the results. This effectively translates to -
(append
(k 'a)
(k 'b))
Next expand the continuation, k, in place -
(append
(list (list 'a (amb 1 2 3))) ; <-
(list (list 'b (amb 1 2 3)))) ; <-
Continuing with the evaluation, we evaluate the next amb. The pattern is continued. amb's call to shift captures the current continuation to k, but this time the continuation has evolved a bit -
k := (list (list 'a ...))
Again, we can think of k in terms of lambda -
k := (lambda (x) (list (list 'a x)))
And amb returns an append-map expression -
(append
(append-map k '(1 2 3)) ; <-
(list (list 'b ...)))
We can continue working like this to resolve the entire computation. append-map applies k to each element of the input and appends the results, effectively translating to -
(append
(append (k 1) (k 2) (k 3)) ; <-
(list (list 'b ...)))
Expand the k in place -
(append
(append
(list (list 'a 1)) ; <-
(list (list 'a 2)) ; <-
(list (list 'a 3))) ; <-
(list (list 'b (amb 1 2 3))))
We can really start to see where this is going now. We can simplify the above expression to -
(append
'((a 1) (a 2) (a 3)) ; <-
(list (list 'b (amb 1 2 3))))
Evaluation now continues to the final amb expression. We will follow the pattern one more time. Here amb's call to shift captures the current continuation as k -
k := (list (list 'b ...))
In lambda terms, we think of k as -
k := (lambda (x) (list (list 'b x)))
amb returns an append-map expression -
(append
'((a 1) (a 2) (a 3))
(append-map k '(1 2 3))) ; <-
append-map applies k to each element and appends the results. This translates to -
(append
'((a 1) (a 2) (a 3))
(append (k 1) (k 2) (k 3))) ; <-
Expand k in place -
(append
'((a 1) (a 2) (a 3))
(append
(list (list 'b 1)) ; <-
(list (list 'b 2)) ; <-
(list (list 'b 3)))) ; <-
This simplifies to -
(append
'((a 1) (a 2) (a 3))
'((b 1) (b 2) (b 3))) ; <-
And finally we can compute the outermost append, producing the output -
((a 1) (a 2) (a 3) (b 1) (b 2) (b 3))
generalizing a procedure
Above we used fixed inputs, '(a b) and '(1 2 3). We could make a generic combinations procedure which applies amb to its input arguments -
(define (combinations a b)
(reset
(list (list (apply amb a) (apply amb b)))))
(combinations '(a b) '(1 2 3))
((a 1) (a 2) (a 3) (b 1) (b 2) (b 3))
Now we can easily expand this idea to accept any number of input lists. We write a variadic combinations procedure by taking a list of lists and map over it, applying amb to each -
(define (combinations . lsts)
(reset
(list (map (lambda (each) (apply amb each)) lsts))))
(combinations '(1 2) '(3 4) '(5 6))
((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
Any number of lists of any length can be used -
(combinations
'(common rare)
'(air ground)
'(electric ice bug)
'(monster))
((common air electric monster)
(common air ice monster)
(common air bug monster)
(common ground electric monster)
(common ground ice monster)
(common ground bug monster)
(rare air electric monster)
(rare air ice monster)
(rare air bug monster)
(rare ground electric monster)
(rare ground ice monster)
(rare ground bug monster))
related reading
In Scheme, we can use Olivier Danvy's original implementation of shift/reset. In Racket, they are supplied via racket/control
(define-syntax reset
(syntax-rules ()
((_ ?e) (reset-thunk (lambda () ?e)))))
(define-syntax shift
(syntax-rules ()
((_ ?k ?e) (call/ct (lambda (?k) ?e)))))
(define *meta-continuation*
(lambda (v)
(error "You forgot the top-level reset...")))
(define abort
(lambda (v)
(*meta-continuation* v)))
(define reset-thunk
(lambda (t)
(let ((mc *meta-continuation*))
(call-with-current-continuation
(lambda (k)
(begin
(set! *meta-continuation* (lambda (v)
(begin
(set! *meta-continuation* mc)
(k v))))
(abort (t))))))))
(define call/ct
(lambda (f)
(call-with-current-continuation
(lambda (k)
(abort (f (lambda (v)
(reset (k v)))))))))
For more insight on the use of append-map and amb, see this answer to your another one of your questions.
See also the Compoasable Continuations Tutorial on the Scheme Wiki.
remarks
I really struggled with functional style at first. I cut my teeth on imperative style and it took me some time to see recursion as the "natural" way of thinking to solve problems in a functional way. However I offer this post in hopes to provoke you to reach for even higher orders of thinking and reasoning. Recursion is the topic I write about most on this site but I'm here saying that sometimes even more creative, imaginative, declarative ways exist to express your programs.
First-class continuations can turn your program inside-out, allowing you to write a program which manipulates, consumes, and multiplies itself. It's a sophisticated level of control that's part of the Scheme spec but only fully supported in a few other languages. Like recursion, continuations are a tough nut to crack, but once you "see", you wish you would've learned them earlier.
As suggested in the comments you can use recursion, specifically, right fold:
(define (flatmap foo xs)
(apply append
(map foo xs)))
(define (flatmapOn xs foo)
(flatmap foo xs))
(define (mapOn xs foo)
(map foo xs))
(define (combs L1 L2) ; your "combinations", shorter name
(flatmapOn L1 (lambda (L1_item)
(mapOn L2 (lambda (L2_item) ; changed this:
(cons L1_item L2_item)))))) ; cons NB!
(display
(combs '(1 2)
(combs '(3 4)
(combs '(5 6) '( () )))))
; returns:
; ((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
So you see, the list that you used there wasn't quite right, I changed it back to cons (and thus it becomes fully the same as combine-pair-with-list-of-pairs). That way it becomes extensible: (list 3 (list 2 1)) isn't nice but (cons 3 (cons 2 (cons 1 '()))) is nicer.
With list it can't be used as you wished: such function receives lists of elements, and produces lists of lists of elements. This kind of output can't be used as the expected kind of input in another invocation of that function -- it would produce different kind of results. To build many by combining only two each time, that combination must produce the same kind of output as the two inputs. It's like +, with numbers. So either stay with the cons, or change the combination function completely.
As to my remark about right fold: that's the structure of the nested calls to combs in my example above. It can be used to define this function as
(define (sequence lists)
(foldr
(lambda (list r) ; r is the recursive result
(combs list r))
'(()) ; using `()` as the base
lists))
Yes, the proper name of this function is sequence (well, it's the one used in Haskell).

Generating permutations in Lisp withous map functions

I want to generate in Lisp the list of all permutations of a set. This is what I tried:
(defun ins(e n l)
(cond
((equal n 1) (cons e l))
(T (cons (car l) (ins e (1- n) (cdr l))))
)
)
;; (print (ins '1 1 '(2 3)))
;; (print (ins '1 2 '(2 3)))
;; (print (ins '1 3 '(2 3)))
(defun insert(e n l)
(cond
((equal n 0) nil)
(T (cons (ins e n l) (insert e (1- n) l) ))
)
)
;; (print (insert '1 3 '(2 3)))
(defun inserare(e l)
(insert e (1+ (length l)) l)
)
;(print (inserare '1 '(2 3))) -> ((2 3 1) (2 1 3) (1 2 3))
And from here I just can't make the final permutations function. I tried something like this:
(defun perm(L)
(cond
((null L) nil)
(T (append (perm (cdr L)) (inserare (car L) L)))
)
)
But this is not the good approach
Here is one way.
First of all, if you have a list like (x . y) and you have the permutations of y you will need to create from them the permutations of (x . y). Well consider one of these permutations p, and let this be (p1 p2 ...). From this you will need to make a bunch of permutations including x: (x p1 p2 ...), (p1 x p2 ...), (p1 p2 x ...) ... (p1 p2 ... x).
So let's write a function to do this: a function which given some object and a list will 'thread' the object through the list creating a bunch of new lists with the object inserted at every point. For reasons that will become clear this function is going to take an extra argument which is the list of things to attach the new permutations to the front of. It's also going to use a little local function to do the real work.
Here it is:
(defun thread-element-through-list (e l onto)
(labels ((tetl-loop (erofeb after into)
(if (null after)
(cons (nreverse (cons e erofeb)) into)
(tetl-loop (cons (first after) erofeb)
(rest after)
(cons (revappend (cons e erofeb) after) into)))))
(tetl-loop '() l onto)))
I'm not going to explain the details of this function, but there are a couple of things worth knowing:
tetl-loop is thread-element-through-list-loop;
erofeb is before backwards, because the elements are in reverse order on it;
the nreverse is just a gratuitous hack because at that point erofeb is otherwise dead – there is effectively no mutation in this function.
And we can test it:
> (thread-element-through-list 1 '(2 3) '())
((2 3 1) (2 1 3) (1 2 3))
Now, OK, what we actually have is not just one permutation of y, we have a list of them. And we need to thread x through each of them, using `thread-element-through-list. So we need a function to do that.
(defun thread-element-through-lists (e ls onto)
(if (null ls)
onto
(thread-element-through-lists
e (rest ls)
(thread-element-through-list e (first ls) onto))))
This also has an argument which defines what it's adding its results to, and you can see how this onto list now gets passed around to build the list.
And we can test this
> (thread-element-through-lists '1 '((2 3) (3 2)) '())
((3 2 1) (3 1 2) (1 3 2) (2 3 1) (2 1 3) (1 2 3))
Look at that carefully. I gave thread-element-through-lists, 1, and a list which was the permutations of (2 3), and it has turned out for me the permutations of (1 2 3). So what you now need to do (which I am not going to do for you) is to write a function which:
knows the permutations of () (which is () and of a single-element list (which is a list containing that list)`;
uses thread-elements-through-lists together with a recursive call to itself to compute the permutations of any longer list.

Add successive integers with recursive tests (conditionals)

My recursive function correctly sums all the integers, inclusively, between a and b. However, when I swap my arguments, the result is incorrect. I am reading SICP. My code is (scheme):
(define (sum-integers a b)
(if (> a b)
(if (= (- a 1) b)
(+ a b)
(+ a(sum-integers (- a 1) b)))
(+ a (sum-integers (+ a 1) b))))
(sum-integers 5 2)
(sum-integers 2 5)
I'm sure my compiler is applicative order,so I think the output should be the same.
(sum-integers 5 2)
(sum-integers 2 5)
In fact,
(sum-integers 5 2) ==> 14
(sum-integers 2 5) ==> 25
But 2+3+4+5 = 5+4+3+2 = 14.
Why are my results different?
In your second test case, which displays the bug, your loop doesn't terminate until a = 6 and b = 5. Then it adds an extra 6 and 5 to the total of 14, to get 25.
The reason you found this bug tricky to find may be because the code was more complex than it could be, or because you haven't yet learned how to trace recursive code.
I also noticed that your code indentation is not consistent. Let your editor indent your code for you, to help you follow the logic.
I have written up the code for the design #alfasin mentioned in the comments. You can see the simplicity makes it easier to debug. If a > b then we just swap the arguments and carry on as before.
I think the key to thinking about this is to make sure that the operation that you want to repeat (here it is addition) appears only once in your function.
(define (sum2-integers a b)
(if (> a b)
(sum2-integers b a) ; if the wrong way round, swap them
(if (= a b) ; termination condition
b
(+ a (sum2-integers (+ a 1) b)))))
> (sum2-integers 5 2)
14
> (sum2-integers 2 5)
14
One step further towards simplicity. I find that the multi-way conditional branch cond is much more readable than nested ifs, as there are really three branches in this code.
(define (sum3-integers a b)
(cond [(> a b) (sum3-integers b a)]
[(= a b) b]
[else (+ a (sum3-integers (+ a 1) b))]))
The condition if (> a b) creates a different flow when you send 5,2 vs. 2,5:
When you send a=5,b=2 it means that a > b so we'll get into the if, and since 5-1 > 2 the recursive call will be to (+ a(sum-integers (- a 1) b)).
When you send a=2, b=5 the condition if (> a b) will return false and the recursive call will be the last line: (+ a (sum-integers (+ a 1) b))
As you can see:
(+ a (sum-integers (- a 1) b)) is not the same as:
(+ a (sum-integers (+ a 1) b))
so no wonder you're getting different results.

Print value -and- call function?

I am new to scheme, and have the following question:
If I want a function to also print -the value- of an expression and then call a function, how would one come up to doing that?
For example, I need the function foo(n) to print the value of n mod 2 and call foo(n/2), I would've done:
(define foo (lambda (n) (modulo n 2) (foo (/ n 2))))
But that, of course, would not print the value of n mod 2.
Here is something simple:
(define foo
(lambda (n)
(display (modulo n 2))
(when (positive? n)
(foo (/ n 2)))))
Note the check of (positive? n) to ensure that you avoid (/ 0 2) forever and ever.
I'm terrible at Lisp, but here's an idea: Maybe you could define a function that prints a value and returns it
(define (debug x) (begin (display x) (newline) x))
Then just call the function like
(some-fun (debug (some expression)))
As #Juho wrote, you need to add a display. But, your procedure is recursive without a base case, so it will never terminate.
Try this:
(define foo
(lambda (n)
(cond
((integer? n) (display (modulo n 2))
(newline)
(foo (/ n 2)))
(else n))))
then
> (foo 120)
0
0
0
1
7 1/2
Usually when dealing with more than one thing it's common to build lists to present a solution when the procedure is finished.
(define (get-digits number base)
(let loop ((nums '()) (cur number))
(if (zero? cur)
nums
(loop (cons (remainder cur base) nums)
(quotient cur base)))))
(get-digits 1234 10) ; ==> (1 2 3 4)
Now, since you use DrRacket you have a debugger so you can actually step though this code but you rather should try to make simple bits like this that is testable and that does not do side effects.
I was puzzled when you were taling about pink and blue output until I opened DrRacket and indeed there it was. Everything that is pink is from the program and everything blue is normally not outputed but since it's the result of top level forms in the IDE the REPL shows it anyway. The differences between them are really that you should not rely on blue output in production code.
As other has suggested you can have debug output with display within the code. I want to show you another way. Imagine I didn't know what to do with the elements so I give you the opportunity to do it yourself:
(define (get-digits number base glue)
(let loop ((nums '()) (cur number))
(if (zero? cur)
nums
(loop (glue (remainder cur base) nums)
(quotient cur base)))))
(get-digits 1234 10 cons) ; ==> (1 2 3 4)
(define (debug-glue a d)
(display a)
(newline)
(cons a d))
(get-digits 1234 10 debug-glue) ; ==> (1 2 3 4) and displays "4\n3\n2\n1\n"

Iterative modulo by repeated subtraction?

I am trying to write an iterative procedure to do modulo arithmetic in scheme without using the built in procedures modulo, remainder or /. However I ran into a few problems while trying to write the code, which looks like this so far:
(define (mod a b)
(define (mod-iter a b)
(cond ((= b 0) 0)
((< b 0) (+ old_b new_b))))
(mod-iter a (- a b)))
As you can see, I ran into the problem of needing to add the original value of b to the current value of b. I am not sure how to go about that. Also, when i left the second conditional's answer to be primitive data (just to make sure the enitre procedure worked), I would get an "unspecified return value" error, and I'm not sure why it happens because the rest of my code loops (or so it seems?)
Thank you in advance for any insight to this.
When you define your mod-iter function with arguments (a b) you are shadowing the arguments defined in mod. To avoid the shadowing, use different identifiers, as such:
(define (mod a b)
(define (mod-iter ax bx)
(cond ((= bx 0) 0)
((< bx 0) (+ b bx))))
(mod-iter a (- a b)))
Note, this doesn't look like the proper algorithm (there is no recursive call). How do you handle the common case of (> bx 0)? You'll need something like:
(define (mod a b)
(define (mod-iter ax bx)
(cond ((= bx 0) 0)
((< bx 0) (+ b bx))
((> bx 0) ...))) ;; <- something here with mod-iter?
(mod-iter a (- a b)))
First if you don't want to capture a variable name, use different variable names in the inner function. Second i think the arguments are wrong compared to the built-in version. (modulo 5 6) is 5 and (modulo 6 5) is 1. Anyways here is a variation in logrirthmic time. That based on generating a list of powers of b (2 4 8 16 32 ...) is b is 2, all the way up to just under the value of a. Then by opportunistically subtracting these reversed values. That way problems like (mod (expt 267 34) 85) return an answer very quickly. (a few hundred primitive function calls vs several million)
(define (mod a-in b-in)
(letrec ((a (abs a-in))
(sign (if (< 0 b-in) - +))
(b (abs b-in))
(powers-list-calc
(lambda (next-exponent)
(cond ((> b a) '())
((= next-exponent 0)
(error "Number 0 passed as the second argument to mod
is not in the correct range"))
(else (cons next-exponent (powers-list (* b next-exponent))))))))
(let ((powers-list (reverse (powers-list-calc b))))
(sign
(let loop ((a a) (powers-L powers-list))
(cond ((null? powers-L) a)
((> a (car powers-L))
(loop (- a (car powers-L)) powers-L))
(else (loop a (cdr powers-L)))))))))

Resources