Do two things in Racket "for loop" - for-loop

I'm running a for loop in racket, for each object in my list, I want to execute two things: if the item satisfies the condition, (1) append it to my new list and (2) then print the list. But I'm not sure how to do this in Racket.
This is my divisor function: in the if statement, I check if the number in the range can divide N. If so, I append the item into my new list L. After all the loops are done, I print L. But for some unknown reason, the function returns L still as an empty list, so I would like to see what the for loop does in each loop. But obviously racket doesn't seem to take two actions in one "for loop". So How should I do this?
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
)
write L)
Thanks a lot in advance!

Note: This answer builds on the answer from #uselpa, which I upvoted.
The for forms have an optional #:when clause. Using for/fold:
#lang racket
(define (divisors N)
(reverse (for/fold ([xs '()])
([n (in-range 1 N)]
#:when (zero? (modulo N n)))
(displayln n)
(cons n xs))))
(require rackunit)
(check-equal? (divisors 100)
'(1 2 4 5 10 20 25 50))
I realize your core question was about how to display each intermediate list. However, if you didn't need to do that, it would be even simpler to use for/list:
(define (divisors N)
(for/list ([n (in-range 1 N)]
#:when (zero? (modulo N n)))
n))
In other words a traditional Scheme (filter __ (map __)) or filter-map can also be expressed in Racket as for/list using a #:when clause.
There are many ways to express this. I think what all our answers have in common is that you probably want to avoid using for and set! to build the result list. Doing so isn't idiomatic Scheme or Racket.

It's possible to create the list as you intend, as long as you set! the value returned by append (remember: append does not modify the list in-place, it creates a new list that must be stored somewhere) and actually call write at the end:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)]) ; generate a stream in the range 1..N
(when (zero? (modulo N i)) ; use `when` if there's no `else` part, and `zero?`
; instead of `(equal? x 0)`
(set! L (append L (list i))) ; `set!` for updating the result
(write L) ; call `write` like this
(newline)))) ; insert new line
… But that's not the idiomatic way to do things in Scheme in general and Racket in particular:
We avoid mutation operations like set! as much as possible
It's a bad idea to write inside a loop, you'll get a lot of text printed in the console
It's not recommended to append elements at the end of a list, that'll take quadratic time. We prefer to use cons to add new elements at the head of a list, and if necessary reverse the list at the end
With all of the above considerations in place, this is how we'd implement a more idiomatic solution in Racket - using stream-filter, without printing and without using for loops:
(define (divisor N)
(stream->list ; convert stream into a list
(stream-filter ; filter values
(lambda (i) (zero? (modulo N i))) ; that meet a given condition
(in-range 1 N)))) ; generate a stream in the range 1..N
Yet another option (similar to #uselpa's answer), this time using for/fold for iteration and for accumulating the value - again, without printing:
(define (divisor N)
(reverse ; reverse the result at the end
(for/fold ([acc '()]) ; `for/fold` to traverse input and build output in `acc`
([i (in-range 1 N)]) ; a stream in the range 1..N
(if (zero? (modulo N i)) ; if the condition holds
(cons i acc) ; add element at the head of accumulator
acc)))) ; otherwise leave accumulator alone
Anyway, if printing all the steps in-between is necessary, this is one way to do it - but less efficient than the previous versions:
(define (divisor N)
(reverse
(for/fold ([acc '()])
([i (in-range 1 N)])
(if (zero? (modulo N i))
(let ([ans (cons i acc)])
; inefficient, but prints results in ascending order
; also, `(displayln x)` is shorter than `(write x) (newline)`
(displayln (reverse ans))
ans)
acc))))

#sepp2k has answered your question why your result is always null.
In Racket, a more idiomatic way would be to use for/fold:
(define (divisor N)
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (append res (list i))))
(displayln newres)
newres)
res)))
Testing:
> (divisor 100)
(1)
(1 2)
(1 2 4)
(1 2 4 5)
(1 2 4 5 10)
(1 2 4 5 10 20)
(1 2 4 5 10 20 25)
(1 2 4 5 10 20 25 50)
'(1 2 4 5 10 20 25 50)
Since append is not really performant, you usually use cons instead, and end up with a list you need to reverse:
(define (divisor N)
(reverse
(for/fold ((res null)) ((i (in-range 1 N)))
(if (zero? (modulo N i))
(let ((newres (cons i res)))
(displayln newres)
newres)
res))))
> (divisor 100)
(1)
(2 1)
(4 2 1)
(5 4 2 1)
(10 5 4 2 1)
(20 10 5 4 2 1)
(25 20 10 5 4 2 1)
(50 25 20 10 5 4 2 1)
'(1 2 4 5 10 20 25 50)

To do multiple things in a for-loop in Racket, you just write them after each other. So to display L after each iteration, you'd do this:
(define (divisor N)
(define L '())
(for ([i (in-range 1 N)])
(if (equal? (modulo N i) 0)
(append L (list i))
L)
(write L))
L)
Note that you need parentheses to call a function, so it's (write L) - not write L. I also replaced your write L outside of the for-loop with just L because you (presumably) want to return L from the function at the end - not print it (and since you didn't have parentheses around it, that's what it was doing anyway).
What this will show you is that the value of L is () all the time. The reason for that is that you never change L. What append does is to return a new list - it does not affect the value of any its arguments. So using it without using its return value does not do anything useful.
If you wanted to make your for-loop work, you'd need to use set! to actually change the value of L. However it would be much more idiomatic to avoid mutation and instead solve this using filter or recursion.

'Named let', a general method, can be used here:
(define (divisors N)
(let loop ((n 1) ; start with 1
(ol '())) ; initial outlist is empty;
(if (< n N)
(if(= 0 (modulo N n))
(loop (add1 n) (cons n ol)) ; add n to list
(loop (add1 n) ol) ; next loop without adding n
)
(reverse ol))))
Reverse before output since items have been added to the head of list (with cons).

Related

Geometric Series function in Scheme language

Im trying to learn scheme and Im having trouble with the arithmetic in the Scheme syntax.
Would anyone be able to write out a function in Scheme that represents the Geometric Series?
You have expt, which is Scheme power procedure. (expt 2 8) ; ==> 256 and you have * that does multiplication. eg. (* 2 3) ; ==> 6. From that you should be able to make a procedure that takes a n and produce the nth number in a specific geometric series.
You can also produce a list with the n first if you instead of using expt just muliply in a named let, basically doing the expt one step at a time and accumulate the values in a list. Here is an example of a procedure that makes a list of numbers:
(define (range from to)
(let loop ((n to) (acc '())
(if (< n from)
acc
(loop (- 1 n) (cons n acc)))))
(range 3 10) ; ==> (3 4 5 6 7 8 9 10)
Notice I'm doing them in reverse. If I cannot do it in reverse I would in the base case do (reverse acc) to get the right order as lists are always made from end to beginning. Good luck with your series.
range behaves exactly like Python's range.
(define (range from (below '()) (step 1) (acc '()))
(cond ((null? below) (range 0 from step))
((> (+ from step) below) (reverse acc))
(else (range (+ from step) below step (cons from acc)))))
Python's range can take only one argument (the upper limit).
If you take from and below as required arguments, the definition is shorter:
(define (range from below (step 1) (acc '()))
(cond ((> (+ from step) below) (reverse acc))
(else (range (+ from step) below step (cons from acc)))))
Here is an answer, in Racket, that you probably cannot submit as homework.
(define/contract (geometric-series x n)
;; Return a list of x^k for k from 0 to n (inclusive).
;; This will be questionable if x is not exact.
(-> number? natural-number/c (listof number?))
(let gsl ((m n)
(c (expt x n))
(a '()))
(if (zero? m)
(cons 1 a)
(gsl (- m 1)
(/ c x)
(cons c a)))))

how to append elements in a list in Scheme

I have made a program that returns the number of a fibonacci series by using tail recursion, and I would like to add its results to a list. I have done the following:
(define listAux '())
(define (fibTail n1 n2 c)
(if (= c 0)
(appendList -1)
(begin
(appendList n2)
(fibT (+ n1 n2) n1 (- c 1))
)))
(define (appendList n)
(if (= n -1)
listAux
(append (list n) listAux)))
(define (fib n)
(fibTail 1 0 n))
I would like that appendList returns a list with the elements of the fibonacci series, when I call it like (fib 8) for example.
Any help?
Thanks
When programming in Lisp, we avoid using append for building lists - it's very inefficient because to insert a single element at the end, we have to traverse the whole list... and then again, and again. It's better to build the list in reverse order using cons and invert it at the end. Also, the ideal way of writing a tail recursion is to accumulate the results in a parameter, not in an externally defined variable (which anyway won't work, unless you set! its value somewhere). This is what I mean:
(define (fib n)
(fibTail 1 0 n '()))
(define (fibTail n1 n2 c lst)
(if (< c 0)
(reverse lst)
(fibTail (+ n1 n2) n1 (- c 1) (cons n2 lst))))
For example:
(fib 10)
=> '(0 1 1 2 3 5 8 13 21 34 55)

Printing First two numbers in scheme

I'm trying to print the first 2 numbers in a list coded in Scheme. I'm having a bit of trouble doing this. I get an error when I run the procedure. Any suggestions on how I can get this to work
(define (print-two-nums n nums)
( list-ref nums(+ (cdr nums) n)))
( print-two-nums 2'(5 5 4 4))
It looks like you were wavering between the ideas of "print two numbers" and "print n numbers." If you really want just the two first numbers of a list, you can write:
(define (print-two-nums nums)
(print (list (car nums) (cadr nums))))
But for the more general first n numbers, you can use:
(define (print-n-nums n nums)
(print (take nums n)))
To print the first n numbers, you could use this simple procedure
(define (print-n-nums L n) (cond
((or (= 0 n) (null? L)) '())
(else (cons (car L) (print-n-nums (cdr L) (- n 1))))))
(print-n-nums (list 1 2 3) 2)
;Output: (1 2)
You could further abstract the cons operation and define print-n-nums as a higher order procedure to carry out the desired operation. For example, if we wanted to add the first n numbers of a list, we could define the following procedure. Here OPERATION is a function that we pass to the list-operator function. Thus, here we want to perform the + operation. In the case above, we want to perform the cons operation. The initial parameter is just how we want to handle the edge case.
(define (list-operator L n OPERATION initial) (cond
((or (= 0 n) (null? L)) initial)
(else (OPERATION (car L) (list-operator (cdr L) (- n 1) OPERATION initial)))))
(list-operator (list 1 2 3) 2 + 0)
;Output: 3
Now, if you wanted the product of the first 2 numbers, you would just do
(list-operator (list 1 2 3) 2 * 1)

finding subsets of length N of a list in scheme

I wrote a function which finds all the subsets of a list already and it works. I'm trying to write a second function where I get all the subsets of N length, but it's not working very well.
This is my code:
(define (subset_length_n n lst)
(cond
[(empty? lst) empty]
[else (foldr (lambda (x y) (if (equal? (length y) n) (cons y x) x)) empty (powerset lst))]
))
where (powerset lst) gives a list of all the subsets.
Am I misunderstanding the purpose of foldr?
I was thinking that the program would go through each element of the list of subsets, compare the length to n, cons it onto the empty list if there the same, ignore it if it's not.
But (subset_length_n 2 (list 1 2 3)) gives me (list (list 1 2) 1 2 3) when I want (list (list 1 2) (list 1 3) (list 2 3))
Thanks in advance
When using foldr you don't have to test if the input list is empty, foldr takes care of that for you. And this seems like a job better suited for filter:
(define (subset_length_n n lst)
(filter (lambda (e) (= (length e) n))
(powerset lst)))
If you must, you can use foldr for this, but it's a rather contrived solution. You were very close to getting it right! in your code, just change the lambda's parameters, instead of (x y) write (y x). See how a nice indentation and appropriate parameter names go a long way toward writing correct solutions:
(define (subset_length_n n lst)
(foldr (lambda (e acc)
(if (= (length e) n)
(cons e acc)
acc))
empty
(powerset lst)))
Anyway, it works as expected:
(subset_length_n 4 '(1 2 3 4 5))
=> '((1 2 3 4) (1 2 3 5) (1 2 4 5) (1 3 4 5) (2 3 4 5))

how to write a scheme program consumes n and sum as parameters, and show all the numbers(from 1 to n) that could sum the sum?

How to write a scheme program consumes n and sum as parameters, and show all the numbers(from 1 to n) that could sum the sum? Like this:
(find 10 10)
((10)
(9 , 1)
(8 , 2)
(7 , 3)
(7 ,2 , 1)
(6 ,4)
(6 , 3, 1)
(5 , 4 , 1)
(5 , 3 , 2)
(4 ,3 ,2 ,1))
I found one:
(define (find n sum)
(cond ((<= sum 0) (list '()))
((<= n 0) '())
(else (append
(find (- n 1) sum)
(map (lambda (x) (cons n x))
(find (- n 1) (- sum n)))))))
But it's inefficient,and i want a better one. Thank you.
The algorithm you are looking for is known as an integer partition. I have a couple of implementations at my blog.
EDIT: Oscar properly chastized me for my incomplete answer. As penance, I offer this answer, which will hopefully clarify a few things.
I like Oscar's use of streams -- as the author of SRFI-41 I should. But expanding the powerset only to discard most of the results seems a backward way of solving the problem. And I like the simplicity of GoZoner's answer, but not its inefficiency.
Let's start with GoZoner's answer, which I reproduce below with a few small changes:
(define (fs n s)
(if (or (<= n 0) (<= s 0)) (list)
(append (if (= n s) (list (list n))
(map (lambda (xs) (cons n xs))
(fs (- n 1) (- s n))))
(fs (- n 1) s))))
This produces a list of the output sets:
> (fs 10 10)
((10) (9 1) (8 2) (7 3) (7 2 1) (6 4) (6 3 1) (5 4 1) (5 3 2) (4 3 2 1))
A simple variant of that function produces the count instead of a list of sets, which shall be the focus of the rest of this answer:
(define (f n s)
(if (or (<= s 0) (<= n 0)) 0
(+ (if (= n s) 1
(f (- n 1) (- s n)))
(f (- n 1) s))))
And here is a sample run of the function, including timings on my ancient and slow home computer:
> (f 10 10)
10
> (time (f 100 100)
(time (f 100 ...))
no collections
1254 ms elapsed cpu time
1435 ms elapsed real time
0 bytes allocated
444793
That's quite slow; although it is fine for small inputs, it would be intolerable to evaluate (f 1000 1000), as the algorithm is exponential. The problem is the same as with the naive fibonacci algorithm; the same sub-problems are re-computed again and again.
A common solution to that problem is memoization. Fortunately, we are programming in Scheme, which makes it easy to encapsulate memoization in a macro:
(define-syntax define-memoized
(syntax-rules ()
((_ (f args ...) body ...)
(define f
(let ((results (make-hash hash equal? #f 997)))
(lambda (args ...)
(let ((result (results 'lookup (list args ...))))
(or result
(let ((result (begin body ...)))
(results 'insert (list args ...) result)
result)))))))))
We use hash tables from my Standard Prelude and the universal hash function from my blog. Then it is a simple matter to write the memoized version of the function:
(define-memoized (f n s)
(if (or (<= s 0) (<= n 0)) 0
(+ (if (= n s) 1
(f (- n 1) (- s n)))
(f (- n 1) s))))
Isn't that pretty? The only change is the addition of -memoized in the definition of the function; all of the parameters and the body of the function are the same. But the performance improves greatly:
> (time (f 100 100))
(time (f 100 ...))
no collections
62 ms elapsed cpu time
104 ms elapsed real time
1028376 bytes allocated
444793
That's an order-of-magnitude improvement with virtually no effort.
But that's not all. Since we know that the problem has "optimal substructure" we can use dynamic programming. Memoization works top-down, and must suspend the current level of recursion, compute (either directly or by lookup) the lower-level solution, then resume computation in the current level of recursion. Dynamic programming, on the other hand, works bottom-up, so sub-solutions are always available when they are needed. Here's the dynamic programming version of our function:
(define (f n s)
(let ((fs (make-matrix (+ n 1) (+ s 1) 0)))
(do ((i 1 (+ i 1))) ((< n i))
(do ((j 1 (+ j 1))) ((< s j))
(matrix-set! fs i j
(+ (if (= i j)
1
(matrix-ref fs (- i 1) (max (- j i) 0)))
(matrix-ref fs (- i 1) j)))))
(matrix-ref fs n s)))
We used the matrix functions of my Standard Prelude. That's more work than just adding -memoized to an existing function, but the payoff is another order-of-magnitude reduction in run time:
> (time (f 100 100))
(time (f 100 ...))
no collections
4 ms elapsed cpu time
4 ms elapsed real time
41624 bytes allocated
444793
> (time (f 1000 1000))
(time (f 1000 ...))
3 collections
649 ms elapsed cpu time, including 103 ms collecting
698 ms elapsed real time, including 132 ms collecting
15982928 bytes allocated, including 10846336 bytes reclaimed
8635565795744155161506
We’ve gone from 1254ms to 4ms, which is a rather astonishing range of improvement; the final program is O(ns) in both time and space. You can run the program at http://programmingpraxis.codepad.org/Y70sHPc0, which includes all the library code from my blog.
As a special bonus, here is another version of the define-memoized macro. It uses a-lists rather than hash tables, so it's very much slower than the version given above, but when the underlying computation is time-consuming, and you just want a simple way to improve it, this may be just what you need:
(define-syntax define-memoized
(syntax-rules ()
((define-memoized (f arg ...) body ...)
(define f
(let ((cache (list)))
(lambda (arg ...)
(cond ((assoc `(,arg ...) cache) => cdr)
(else (let ((val (begin body ...)))
(set! cache (cons (cons `(,arg ...) val) cache))
val)))))))))
This is a good use of quasi-quotation and the => operator in a cond clause for those who are just learning Scheme. I can't remember when I wrote that function -- I've had it laying around for years -- but it has saved me many times when I just needed a quick-and-dirty memoization and didn't care to worry about hash tables and universal hash functions.
This answer will appear tomorrow at my blog. Please drop in and have a look around.
This is similar to, but not exactly like, the integer partition problem or the subset sum problem. It's not the integer partition problem, because an integer partition allows for repeated numbers (here we're only allowing for a single occurrence of each number in the range).
And although it's more similar to the subset sum problem (which can be solved more-or-less efficiently by means of dynamic programming), the solution would need to be adapted to generate all possible subsets of numbers that add to the given number, not just one subset as in the original formulation of that problem. It's possible to implement a dynamic programming solution using Scheme, but it'll be a bit cumbersome, unless a matrix library or something similar is used for implementing a mutable table.
Here's another possible solution, this time generating the power set of the range [1, n] and checking each subset in turn to see if the sum adds to the expected value. It's still a brute-force approach, though:
; helper procedure for generating a list of numbers in the range [start, end]
(define (range start end)
(let loop ((acc '())
(i end))
(if (< i start)
acc
(loop (cons i acc) (sub1 i)))))
; helper procedure for generating the power set of a given list
(define (powerset set)
(if (null? set)
'(())
(let ((rest (powerset (cdr set))))
(append (map (lambda (element) (cons (car set) element))
rest)
rest))))
; the solution is simple using the above procedures
(define (find n sum)
(filter (lambda (s) (= sum (apply + s)))
(powerset (range 1 n))))
; test it, it works!
(find 10 10)
=> '((1 2 3 4) (1 2 7) (1 3 6) (1 4 5) (1 9) (2 3 5) (2 8) (3 7) (4 6) (10))
UPDATE
The previous solution will produce correct results, but it's inefficient in memory usage because it generates the whole list of the power set, even though we're interested only in some of the subsets. In Racket Scheme we can do a lot better and generate only the values as needed if we use lazy sequences, like this (but be aware - the first solution is still faster!):
; it's the same power set algorithm, but using lazy streams
(define (powerset set)
(if (stream-empty? set)
(stream '())
(let ((rest (powerset (stream-rest set))))
(stream-append
(stream-map (lambda (e) (cons (stream-first set) e))
rest)
rest))))
; same algorithm as before, but using lazy streams
(define (find n sum)
(stream-filter (lambda (s) (= sum (apply + s)))
(powerset (in-range 1 (add1 n)))))
; convert the resulting stream into a list, for displaying purposes
(stream->list (find 10 10))
=> '((1 2 3 4) (1 2 7) (1 3 6) (1 4 5) (1 9) (2 3 5) (2 8) (3 7) (4 6) (10))
Your solution is generally correct except you don't handle the (= n s) case. Here is a solution:
(define (find n s)
(cond ((or (<= s 0) (<= n 0)) '())
(else (append (if (= n s)
(list (list n))
(map (lambda (rest) (cons n rest))
(find (- n 1) (- s n))))
(find (- n 1) s)))))
> (find 10 10)
((10) (9 1) (8 2) (7 3) (7 2 1) (6 4) (6 3 1) (5 4 1) (5 3 2) (4 3 2 1))
I wouldn't claim this as particularly efficient - it is not tail recursive nor does it memoize results. Here is a performance result:
> (time (length (find 100 100)))
running stats for (length (find 100 100)):
10 collections
766 ms elapsed cpu time, including 263 ms collecting
770 ms elapsed real time, including 263 ms collecting
345788912 bytes allocated
444793
>

Resources