Using a counter within a function Scheme - scheme

I want to find a way to use a counter within a function where the counter is also a variable within the recursive function. An example of this is with a program that takes a list and then "sifts" through it until it finds all the numbers within it that are multiples of i:
(define (multiples-of lst) (lambda (i) (if (> i 3))
'()
(multiplefilter (ismultipleof (+ i 1)) (lst)))))
where ismultipleof checks if the car of each list is a multiple of i + 1 (with i starting at 1) and then the multiplefilter is a separate function that scraps any values of the list that are not multiples of i. So that if I put in the list (1 2 3 4 5 6 7 8 9 10 11 12) the output would just be (6 12). The biggest issue is getting said counter to work within the function.

Well, here's a simple function that uses a counter in its execution. range just returns a list of integers from 0 up to (- n 1). It's just as easy to write something that increments a counter.
(define (range n)
(let loop ((acc '())
(list-start (- n 1)))
(if (negative? list-start)
acc
(loop (cons list-start acc) (- list-start 1)))))
This function counts down rather than up because recursion usually builds lists "backwards". Counting down just avoids the need call reverse on the acc when the recursion is finished.
Iteration is usually accomplished with recursion in Scheme instead of for loops as in some languages. In particular, recursion from the tail is something to strive for since it will not "blow the stack".

Related

Why is the empty list produced here in this iteration?

Let's take the following function to get a pair of numbers:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
Why does the above produce '() as the first element of the output? Comparing this with python, I would expect it to just give the three pairs, something like:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
I suppose maybe it has to do with when i is 1?
(map (lambda (j) (list 1 j)) '())
; ()
Is that just an identity in Scheme that a map with an empty list is always an empty list?
When i is 1, the inner map is over (range 1 0), which is () by your own definition. Since map takes a procedure and a list (or lists) of values, applies the procedure to each value in the list in turn, and returns a list containing the results, mapping any procedure over a list containing no values will return a list containing no values.
It might help to create a simple definition for map to see how this might work. Note that this definition is not fully featured; it only takes a single list argument:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
Here, when the input list is empty, there are no values to map over, so an empty list is returned. Otherwise the procedure proc is applied to the first value in the input list, and the result is consed onto the result of mapping over the rest of the list.
A couple of observations:
First, the empty list is not represented by nil in either standard Scheme or vanilla Racket, and you should not be using it. In the early days of Scheme nil was allowed as a crutch for programmers coming from other lisps, but this has not been the case for a long time. I don't think that it was ever in any of the RnRS standards, but nil may have survived in some specific implementations until maybe R4RS (1991). SICP was from that era. Today you should use '() to represent empty list literals in Scheme so that your code can run on any Scheme implementation. Racket's #lang sicp allows code directly from the book to be run, but that should not keep you from using the common notation. Note that Common Lisp does use nil as a self-evaluating symbol to represent both the empty list, and boolean false. Seeing this in Scheme just doesn't look right today.
Second, you will probably be led astray more often than to wisdom by thinking in terms of Python when trying to understand Scheme code. In this particular case, map is an iteration construct, but it is not the same thing as a for loop. A for loop is usually used for side-effects, but map is used to transform a list. Scheme has a for-each form which is meant to be used for its side-effects, and in that sense is more like a for loop. The Python version that is posted above is not at all like the Scheme version, though. Instead of returning the results in a list, the results are printed. In the Scheme code, when i is 1, the inner mapping is over (range 1 0) --> (). But, in the Python code, when i is 1, the inner loop is over range(1, 1), so the body of this for loop is not executed and nothing is printed.
Better to think carefully about the Scheme code you want to understand, falling back on basic definitions, than to cobble together a model based on Python that has possibly unconsidered corner cases.

Modified Sieve for finding Prime Numbers in Scheme

I am working on coming up with a solution for coming with a list of prime numbers using the Sieve of Eratosthenes. So the program is supposed to find prime numbers up to a specific number "n". I believe I have come up with an incomplete solution but not sure how to proceed from here.
;;;This is a helper function
(define sievehelper
(lambda (list)
;;; This is the base condition where we are comparing
;;; that the divisor is less than the square root of n""
(if (> (car list) (sqrt (car (reverse list))))
'()
;;; If the base condition has not be reached, then send it through
;;; this filter function where not-divisible by will go through
;;; the specified list and only output the list which contains
;;; the numbers that are not divisible by (car list)
(filterfunc (not-divisible-by (car list))
list)))
I have tested the other helper function fliterfunc on its own and it works fine.
;;;; This is the main function that calls the above helper function
(define sieve
(lambda (n)
;;; `makelist` is a helper function to generate the list from 2 to n
(sievehelper (makelist n))))
I have tested the makelist helper function separately and it works fine.
My question is with the helper function "sievehelper" in terms of how to iterate through the different elements in the list as the divisor.
Any help is appreciated. Thank you.
One piece of code that leads to getting stuck is (if ( > (car list) (sqrt (car(reverse list)))), which looks a lot like the loop condition you might use in other languages (and the word "iterate" hints at peeking at other languages, as well).
I would recommend that you start over, with a different strategy.
When you work with lists, you usually want to recurse on their structure alone.
Assume that you have the list of all integers, starting with 2.
As a first step, you want to keep the two, and remove all its multiples from the remainder of the list.
Now, the result of that removal will give you a list that starts with the next prime number - i.e. 3 - so you can repeat the procedure with that partial result which will remove all multiples of 3, and repeat again with that partial result, and so on until there is no more list.
(Note that this is far from as efficient as it could be, but is more a "get started with thinking recursively" level of suggestion. Read Will's answer for more.)
Applying some wishful thinking and assuming that there is a procedure remove-multiples-of which does what it sounds like, this could look like this:
(define (my-sieve-helper ls)
(if (null? ls)
'()
(cons (car ls)
(my-sieve-helper (remove-multiples-of (car ls) (cdr ls))))))
So, remove-multiples-of...
This is the same as keeping all the numbers that are not divisible by a number, so let's dream up another function:
(define (remove-multiples-of x ls) (filter (not-divisible-by x) ls))
where (not-divisible-by x) is a procedure that takes a number and returns whether that number is not divisible by x.
(define (not-divisible-by n) (lambda (x) (not (zero? (remainder x n)))))
And now we can add a suitable wrapper.
I did this:
(define (from-to m n)
(if (> m n)
'()
(cons m (from-to (+ m 1) n))))
(define (my-sieve n) (my-sieve-helper (from-to 2 n)))
Test:
> (my-sieve 100)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97)
Well, your question presents an interesting case of under-specification that can be advantageous, delaying the actual specification -- not just implementation as usual -- of subroutines used by your piece of code.
Here we have sievehelper which uses the non-implemented non-specified filterfunc and not-divisible-by. Despite their suggestive names these function can do anything, as long as they work, when used together, and make the function using them, sievehelper, also do its work as intended. Delayed specification for the win!
So let's first see what can be intended with the sievehelper as given, what does it do? Assuming the obvious meaning of the two subroutines, it seems to be intended to perform a one-step filtering of its working sequence, culling it from any multiples of its "head" element, the one in its car position.
It would signal the stopping condition by returning (). That stopping condition is a*a > z, for the input list of [a,b,c,...,z].
Otherwise, it does not perform the looping, but just the one step of it. Your sieve doesn't account for that at all, so will need to be changed to continually call this helper, performing step after step as is usual in sieving algorithms, until the square of the first element is bigger than the last element in the working sequence, when it is indeed safe to stop the culling as all the multiples in the sequence will have already been removed from it as multiples of the smaller primes ...... provided that those smaller primes were present in the initial sequence.
So this discovered requirement falls on the third non-implemented subrouting in use, makelist. You do mention that it must create the list of sequential natural numbers from 2 to n, and now we understand why we needed it to do so.
So then, in order to iterate through the different versions of the input list as each divisor is filtered out from it in turn, using your sievehelper definition as given, your sieve function must be changed as e.g.
(define sieve
(lambda (n)
(let ((init (makelist n)))
(let loop ((this init )
(next (sievehelper init)))
(if (null? next)
this
(cons (car this)
(loop next
(sievehelper next))))))))
(The above code incorporates the fix by ad-absurdum from the followup Q&A entry, to the error that this code originally contained).
This code comes from the perspective of working with a pair -- the current sequence, and its next iteration. On each step the next version of the list is found after all the multiples of its head element are removed from it by sievehelper (including the head element itself, the next found prime) -- or the empty list is instead returned to signal the end of processing when all the numbers in the list are known to already be prime, by construction.
Trying it out in Racket:
> (sieve 50)
'(2 3 5 7 11 13 17 19 23 29 31 37 41 43 47)
To run it, further definitions had to be made:
(define filterfunc filter)
(define (not-divisible-by n) ; NB! this critically depends on
(let ((m n)) ; filterfunc working over its
(lambda (x) ; argument list _in order_ NB!
(let ((ret (not (= x m))))
(if (>= x m) (set! m (+ m n)) #f)
ret))))
(define (makelist n)
(range 2 (+ 1 n))) ; in Racket
Defining the not-divisible-by as we did here, enumerating the multiples of each prime internally by iterated additions, makes it be the sieve of Eratosthenes indeed. And stopping early (at the square root of the limit), as in your original code, keeps its time complexity on the sane side, closer to optimal.

Lisp : how to use recursion to defun a function that given a nonnegative integer N, produce the list of all integers from 1 up to and including N?

write a function in lisp called number(N) that you have to use a nonnegative integer N, and produce the list of all integers from 1 up to and including N.
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
I checked some questions, but most of them use loop and range, but this question doesn't allowed me to do this, so I have to use recursion instead:
here is my code, but this code keeps giving me warning:
; caught STYLE-WARNING:
; The variable N is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 1 STYLE-WARNING condition
I think my algorithm is correct ,but because I am new to lisp, I still don't know how to write the function properly. It is grateful if anyone could gave me any help.
IF has generally a common syntax, but there are exceptions
Generally in Lisps like Common Lisp the if operator allows the following syntax:
IF test-form then-form [else-form]
This means that in Lisp usually zero or one else-form are allowed. An example is if in Common Lisp.
In Emacs Lisp multiple else-forms are allowed. Emacs Lisp has the following syntax:
IF test-form then-form else-form*
This means that in Emacs Lisp zero or more else-forms are allowed.
Thus: it's important to mention which language&dialect you are actually using.
Your code
a) Let's assume that you use Common Lisp with its IF syntax.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Your code has the problem, that there are more than one else clauses. You need to write a version which has a single else clause.
b) Let's assume that you use Emacs Lisp with its IF syntax with multiple else forms.
Your code:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
Here the (cons N nil) form is allowed, but has no effect. Its return value is not used and it has no side effect. You could delete it and it would make no difference. Again: you would need how to combine its effect with the form (numbers (- N 1)).
Syntax error: missing closing parenthesis
There is another problem in your code. The s-expressions are not complete -> a closing parenthesis is missing:
(defun numbers (N)
(if (<= N 0)
nil
(cons N nil)
(numbers (- N 1)))
As you can see a closing parenthesis is missing at the end.
Thus your code can not be read by Lisp.
There are two ways one generally can avoid this problem:
count the parentheses and set them accordingly
use the editor to count the parentheses
Most people prefer the latter.
The way to think about this is to think about what the algorithm should be:
To compute the numbers from 1 to n:
if n is less than 1 then there are no numbers, so this is the empty list;
otherwise we want a list which looks like (... n), where ... is all the numbers from 1 to n-1.
Note that we want the numbers in forward order: this is going to be critical.
Doing this is slightly difficult in Lisp because we want the number to be at the end of the list, and access to the ends of lists is hard.
Here is the start of a version which builds the list backwards (so this is not the right answer).
(defun numbers (n)
(if (< n 1)
'() ;the empty list
;; n 1 or more, so build a list which is (n . ...)
(cons n <some function involving n>)))
Well, OK, what function should we call recursively? Do we have a function which returns the list we want? Well, yes: it's numbers, with an argument which is one less than n!
(defun numbers (n)
(if (< n 1)
'()
(cons n (numbers (- n 1)))))
And this function works. But it gets the wrong answer: the list is backwards:
> (numbers 10)
(10 9 8 7 6 5 4 3 2 1)
There are two fixes to this problem: the first is to build the list forwards, using append. This version looks like this (remember append wants to append two lists: it doesn't append an element to the end of a list):
(defun numbers (n)
(if (< n 1)
'()
(append (numbers (- n 1)) (list n))))
This gets the right answer:
> (numbers 10)
(1 2 3 4 5 6 7 8 9 10)
but it's a terrible answer: append has to walk all the way down the list (lists in Lisp are chains of conses: there is no fast access to the end of a list), copying it as it goes, to append the new element. So this has absolutely terrible space & time complexity. Programs written like this are why 'Lisp is slow'.
A better approach is to build the list backwards and then reverse it.
(defun numbers (n)
(reverse (numbers-backwards n)))
(defun numbers-backwards (n)
(if (< n 1)
'()
(cons n (numbers-backwards (- n 1)))))
The problem with this, from the homework perspective, might be that using reverse is not allowed. That's OK, we can write it, recursively. The implementation is slightly fiddly, but this is going to help us below.
(defun reverse-list (l)
;; in real life reverse-list-accumulator would be a local function
(reverse-list-accumulator l '()))
(defun reverse-list-accumulator (l accum)
(if (null l)
accum
(reverse-list-accumulator (rest l) (cons (first l) accum))))
The way this works is that reverse-list calls this auxiliary function with an extra argument. The auxiliary function then checks the list, and if it's not empty it calls itself with the tail of the list and the head of the list consed onto the auxiliary argument. If it is empty, it returns the auxiliary argument. It's a little subtle but you can see that this in fact reverses the list.
So now we can write our function using only recursive functions we wrote:
(defun numbers (n)
(reverse-list (numbers-backwards n)))
But now there should be a moment of inspiration: why are we doing this whole
build-it-backwards-and-reverse-it thing? Why don't we just make numbers do the accumulator trick itself! Well, we can do that:
(defun numbers (n)
(numbers-accumulator n '()))
(defun numbers-accumulator (n accum)
(if (< n 1)
accum
(numbers-accumulator (- n 1) (cons n accum))))
And now we don't need to reverse the list, and for added value our
function is 'tail recursive' and will generally be compiled much more
efficiently.
A real-life version of numbers might look more like this, using a local function:
(defun numbers (n)
(labels ((numbers-accumulator (m accum)
(if (< m 1)
accum
(numbers-accumulator (- m 1) (cons m accum)))))
(numbers-accumulator n '())))
Here is a comparison between the version of numbers using append and the above function, on an argument small enough that the append version does not overflow the stack.
> (time (progn (numbers/append 2000) (values)))
Timing the evaluation of (progn (numbers/append 2000) (values))
User time = 0.024
System time = 0.001
Elapsed time = 0.017
Allocation = 32176304 bytes
97 Page faults
> (time (progn (numbers 2000) (values)))
Timing the evaluation of (progn (numbers 2000) (values))
User time = 0.000
System time = 0.000
Elapsed time = 0.001
Allocation = 32000 bytes
0 Page faults
You can see how terrible the append version is, and how good the other one is: this is a 64-bit Lisp, and conses are two words or 16 bytes: it has allocated precisely 2000 cons cells which is the minimum it could do.

Alternating Sum Using Foldr/Foldl (Racket)

Back again with another Racket question. New to higher order functions in general, so give me some leeway.
Currently trying to find the alternating sum using the foldr/foldl functions and not recursion.
e.g. (altsum '(1 3 5 7)) should equal 1 - 3 + 5 - 7, which totals to -4.
I've thought about a few possible ways to tackle this problem:
Get the numbers to add in one list and the numbers to subtract in another list and fold them together.
Somehow use the list length to determine whether to subtract or add.
Maybe generate some sort of '(1 -1 1 -1) mask, multiply respectively, then fold add everything.
However, I have no clue where to start with foldl/foldr when every operation is not the same for every item in the list, so I'm having trouble implementing any of my ideas. Additionally, whenever I try to add more than 2 variables in my foldl's anonymous class, I have no idea what variables afterward refer to what variables in the anonymous class either.
Any help or pointers would be greatly appreciated.
We can leverage two higher-order procedures here: foldr for processing the list and build-list for generating a list of alternating operations to perform. Notice that foldr can accept more than one input list, in this case we take a list of numbers and a list of operations and iterate over them element-wise, accumulating the result:
(define (altsum lst)
(foldr (lambda (ele op acc) (op acc ele))
0
lst
(build-list (length lst)
(lambda (i) (if (even? i) + -)))))
It works as expected:
(altsum '(1 3 5 7))
=> -4
Your idea is OK. You can use range to make a list of number 0 to length-1 and use the oddness of each to determine + or -:
(define (alt-sum lst)
(foldl (lambda (index e acc)
(define op (if (even? index) + -))
(op acc e))
0
(range (length lst))
lst))
As an alternative one can use SRFI-1 List Library that has fold that allows different length lists as well as infinite lists and together with circular-list you can have it alterate between + and - for the duration of lst.
(require srfi/1) ; For R6RS you import (srfi :1)
(define (alt-sum lst)
(fold (lambda (op n result)
(op result n))
0
(circular-list + -)
lst))
(alt-sum '(1 3 5 7))
; ==> -4

How does the named let in the form of a loop work?

In an answer which explains how to convert a number to a list the number->list procedure is defined as follows:
(define (number->list n)
(let loop ((n n)
(acc '()))
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc)))))
Here a "named let" is used. I don't understand how this named let works.
I see that a loop is defined where the variable n is equal to n, and the variable acc equal to the empty list. Then if n is smaller than 10 the n is consed to the acc. Otherwise, "the loop" is applied with n equal to n/10 and acc equal to the cons of the remainder of n/10 and the previous accumulated stuff, and then calls itself.
I don't understand why loop is called loop (what is looping?), how it can automatically execute and call itself, and how it will actually add each number multiplied by its appropriate multiplier to form a number in base 10.
I hope someone can shine his or her light on the procedure and the above questions so I can better understand it. Thanks.
The basic idea behind a named let is that it allows you to create an internal function, that can call itself, and invoke it automatically. So your code is equivalent to:
(define (number->list n)
(define (loop n acc)
(if (< n 10)
(cons n acc)
(loop (quotient n 10)
(cons (remainder n 10) acc))))
(loop n '()))
Hopefully, that is easier for you to read and understand.
You might, then, ask why people tend to use a named let rather than defining an internal function and invoking it. It's the same rationale people have for using (unnamed) let: it turns a two-step process (define a function and invoke it) into one single, convenient form.
It's called a loop because the function calls itself in tail position. This is known as tail recursion. With tail recursion, the recursive call returns directly to your caller, so there's no need to keep the current call frame around. You can do tail recursion as many times as you like without causing a stack overflow. In that way, it works exactly like a loop.
If you'd like more information about named let and how it works, I wrote a blog post about it. (You don't need to read it to understand this answer, though. It's just there if you're curious.)
A normal let usage can be considered an anonymous procedure call:
(let ((a 10) (b 20))
(+ a b))
;; is the same as
((lambda (a b)
(+ a b))
10
20)
A named let just binds that procedure to a name in the scope of the procedure so that it is equal to a single procedure letrec:
(let my-chosen-name ((n 10) (acc '()))
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc)))) ; ==> (1 2 3 4 5 6 7 8 9 10)
;; Is the same as:
((letrec ((my-chosen-name
(lambda (n acc)
(if (zero? n)
acc
(my-chosen-name (- n 1) (cons n acc))))))
my-chosen-name)
10
'()) ; ==> (1 2 3 4 5 6 7 8 9 10)
Notice that the body of the letrec just evaluates to the named procedure so that the name isn't in the environment of the first call. Thus you could do this:
(let ((loop 10))
(let loop ((n loop))
(if (zero? n)
'()
(cons n (loop (- n 1))))) ; ==> (10 9 8 7 6 5 4 3 2 1)
the procedure loop is only in the environment of the body of the inner let and does not shadow the variable loop of the outer let.
In your example, the name loop is just a name. In Scheme every loop is ultimately done with recursion, but usually the name is used when it's tail recursion and thus an iterative process.

Resources