Scheme - Return list of N Repetitions of said list - scheme

First off, this is a homework question so just looking for guidance and not an answer.
Write a function named (cycle ALIST N) that accepts a list of elements ALIST and an integer N. This function returns a list containing N repetitions of the elements of ALIST. If N is non-positive, this function returns the empty list.
I will be honest in that I'm not sure how to begin solving this problem. I've been thinking of writing a helper function then using cons calling this n times but just looking if I'm on the correct track here.

One of the more common ways to tackle recursive problems is to begin thinking about it at the end. In other words, under what conditions should you stop? —When are you done? If you can write this base case down, then you only need to ask, what do I do when I am one step away from stopping? This is the recursive step, and for relatively simple recursive problems you are done as the whole problem is either "continue" to do the same thing or "stop."
Knowing the base case usually tells you what kind of extra information you may need to carry around, if any.
In the case of scheme and racket, which support tail call optimization, you may end up with different kinds of recursion. For example:
(define (normal-factorial n)
(if (zero? n)
1
(* n (normal-factorial (- n 1)))))
(define (tail-factorial n)
(letrec ((tf (lambda (product index)
(if (zero? index)
product
(tf (* product index) (- index 1))))))
(tf n (- n 1))))
In the first case, we build up a product without ever multiplying until the very end, while in the second we multiply as soon as possible and carry around this temporary product the whole time.
Not all problems easily lend themselves to one kind of recursion or the other.

You have different strategies you can make. The simplest is probably not the most effiecent but the one that produces less code:
(require srfi/26) ; cut
(define (cycle lst n)
(define dup-lst (map (cut make-list n <>) lst))
(foldr append '() dup-lst))
So what this does is that the map creates a list of lists where each is n elements of each. The foldr flattens it by using append.
With more hands on you can make it more efficient. I'm thinking roll your own recursion consing the elements from end to beginning in an accumulator:
(define (cycle lst n)
(let helper ((lst (reverse lst)) (c n) (acc '()))
(cond ((null? lst) acc)
((<= c 0) (helper ...))
(else (helper ...)))))
I've left out the recursive parts. What this does is a base case on the empty list, a reset recur with a c reset to n and the cdr when c is zero and the default case keeping lst while reducing c and cons-ing the first element of lst to acc. This is a O(n) solution.

Related

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.

Racket random list-ref function

Define a function that takes a non-empty list and returns an element of the list selected at random and with equal probability. (Do not use the built-in list-ref procedure.)
I'm stuck on this. I feel like you would need to count the number of times the function has run recursively and compare it to the random number you get, but I don't know how to do that in BSL+. Any help would be really great.
Here is a solution. To get the ball rolling the first element of the list is chosen as a candidate to be returned. Then for each element of the remaining elements in the list, we randomly choose if the candidate is to be replaced.
For example: For a list with two elements '(a b) first the element 'a is chosen.
The a coin is flipped: With probability 50% 'b is returned instead.
Examine the code to see how the algorithm works for larger lists:
(define (pick-random xs)
(pick-random/helper (rest xs) (first xs) 1))
(define (pick-random/helper xs chosen k)
(cond
[(empty? xs) chosen]
[else ; with probability 1/(k+1) choose the first element of xs
(if (= (random (+ k 1)) 0)
(pick-random/helper (rest xs) (first xs) (+ k 1))
(pick-random/helper (rest xs) chosen (+ k 1)))]))
If you want to google the theory, this type of algorithm belongs to "sampling algorithms".
I take the comment about not using list-ref as a direction to think about the problem recursively.
An assumption is made that 'equal probability' does not take into account the flaws of naive software-based RNGs.
Note that we use []-notation in the function definition to say that steps, unless specified, will have a (default) value of (random (length lst)). This means it will initially have a random amount of 'steps into' the list.
#lang racket
(define (random-element lst [steps (random (length lst))])
(if (= steps 0)
(first lst)
(random-element (rest lst)
(sub1 steps))))
Since steps is internally specified (as (sub1 steps), subtract one from steps) it will always have an explicit value except when the function is applied like so:
(random-element '(42 1337 128 256))
; 256

Continuation Passing Style In Common Lisp?

In an effort to find a simple example of CPS which doesn't give me a headache , I came across this Scheme code (Hand typed, so parens may not match) :
(define fact-cps
(lambda(n k)
(cond
((zero? n) (k 1))
(else
(fact-cps (- n 1)
(lambda(v)
(k (* v n))))))))
(define fact
(lambda(n)
(fact-cps n (lambda(v)v)))) ;; (for giggles try (lambda(v)(* v 2)))
(fact 5) => 120
Great, but Scheme isn't Common Lisp, so I took a shot at it:
(defun not-factorial-cps(n k v)
(declare (notinline not-factorial-cps)) ;; needed in clisp to show the trace
(cond
((zerop n) (k v))
((not-factorial-cps (1- n) ((lambda()(setq v (k (* v n))))) v))))
;; so not that simple...
(defun factorial(n)
(not-factorial-cps n (lambda(v)v) 1))
(setf (symbol-function 'k) (lambda(v)v))
(factorial 5) => 120
As you can see, I'm having some problems, so although this works, this has to be wrong. I think all I've accomplished is a convoluted way to do accumulator passing style. So other than going back to the drawing board with this, I had some questions: Where exactly in the Scheme example is the initial value for v coming from? Is it required that lambda expressions only be used? Wouldn't a named function accomplish more since you could maintain the state of each continuation in a data structure which can be manipulated as needed? Is there in particular style/way of continuation passing style in Common Lisp with or without all the macros? Thanks.
The problem with your code is that you call the anonymous function when recurring instead of passing the continuation like in the Scheme example. The Scheme code can easily be made into Common Lisp:
(defun fact-cps (n &optional (k #'values))
(if (zerop n)
(funcall k 1)
(fact-cps (- n 1)
(lambda (v)
(funcall k (* v n))))))
(fact-cps 10) ; ==> 3628800
Since the code didn't use several terms or the implicit progn i switched to if since I think it's slightly more readable. Other than that and the use of funcall because of the LISP-2 nature of Common Lisp it's the identical code to your Scheme version.
Here's an example of something you cannot do tail recursively without either mutation or CPS:
(defun fmapcar (fun lst &optional (k #'values))
(if (not lst)
(funcall k lst)
(let ((r (funcall fun (car lst))))
(fmapcar fun
(cdr lst)
(lambda (x)
(funcall k (cons r x)))))))
(fmapcar #'fact-cps '(0 1 2 3 4 5)) ; ==> (1 1 2 6 24 120)
EDIT
Where exactly in the Scheme example is the initial value for v coming
from?
For every recursion the function makes a function that calls the previous continuation with the value from this iteration with the value from the next iteration, which comes as an argument v. In my fmapcar if you do (fmapcar #'list '(1 2 3)) it turns into
;; base case calls the stacked lambdas with NIL as argument
((lambda (x) ; third iteration
((lambda (x) ; second iteration
((lambda (x) ; first iteration
(values (cons (list 1) x)))
(cons (list 2) x)))
(cons (list 3) x))
NIL)
Now, in the first iteration the continuation is values and we wrap that in a lambda together with consing the first element with the tail that is not computed yet. The next iteration we make another lambda where we call the previous continuation with this iterations consing with the tail that is not computed yet.. At the end we call this function with the empty list and it calls all the nested functions from end to the beginning making the resulting list in the correct order even though the iterations were in oposite order from how you cons a list together.
Is it required that lambda expressions only be used? Wouldn't a named
function accomplish more since you could maintain the state of each
continuation in a data structure which can be manipulated as needed?
I use a named function (values) to start it off, however every iteration of fact-cps has it's own free variable n and k which is unique for that iteration. That is the data structure used and for it to be a named function you'd need to use flet or labels in the very same scope as the anonymous lambda functions are made. Since you are applying previous continuation in your new closure you need to build a new one every time.
Is there in particular style/way of continuation passing style in
Common Lisp with or without all the macros?
It's the same except for the dual namespace. You need to either funcall or apply. Other than that you do it as in any other language.

Not returning the answer i need

(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))(* n (car ls))(checksum-2 (cdr ls)))))
Ok, I have this code, its suppose to, if I wrote it right, the number (n) should increase by one every time it goes through the list, so n (in reality) should be like 1 2 3 4, but I want n to be multiplied by the car of the list.
Everything loads, but when the answer is returned I get 0.
Thanks!
If you format your code differently, you might have an easier time seeing what is going on:
(define (checksum-2 ls)
(if (null? ls)
0
(let ([n 0])
(+ (+ n 1))
(* n (car ls))
(checksum-2 (cdr ls)))))
Inside the let form, the expressions are evaluated in sequence but you're not using the results for any of them (except the last one). The results of the addition and multiplication are simply discarded.
What you need to do in this case is define a new helper function that uses an accumulator and performs the recursive call. I'm going to guess this is homework or a learning exercise, so I'm not going to give away the complete answer.
UPDATE: As a demonstration of the sort of thing you might need to do, here is a similar function in Scheme to sum the integers from 1 to n:
(define (sum n)
(define (sum-helper n a)
(if (<= n 0)
a
(sum-helper (- n 1) (+ a n))))
(sum-helper n 0))
You should be able to use a similar framework to implement your checksum-2 function.

How do I generate all permutations of certain size with repetitions in Scheme?

I am learning Scheme and I am trying to generate permutations with repetitions of certain size.
For example, given n=4 and set S = {a, b, c, d, e, f}, I'd like to generate all possible permutations: {a,a,a,a},{a,a,a,b},...,{a,a,a,f},{a,a,b,a},{a,a,b,b},...,{a,a,b,f},...{f,a,a,a},{f,a,a,b}...,{f,a,a,f},...{f,f,f,f}.
The trouble is that I can't understand how to pick 'a' 4 times, and remember that i had picked it 4 times, then pick 'a' 3 times, and 'b' one time, and remember all this, so I don't pick it again.
I know that these kinds of problems are best solved with recursive algorithms, but it just makes everything more complicated, like, how do I remember in the recursion, what elements have I picked.
I don't know how to approach this problem at all. I would be very glad if someone wrote out the thought process of solving this problem. I'd appreciate it very much!
Please help me.
Thanks, Boda Cydo.
It's good to start from the procedure's interface and expected results. Your procedure is going to be called (permutations size elements) and is expected to return a list of permutations of the items in ELEMENTS, each permutation being SIZE items long. Figure you're going to represent a "permutation" as a list. So if you called (permutations 1 '(a b c)) you'd expect an output of ((a) (b) (c)).
So the trick about recursive procedures, is you have to figure out what the base condition is that you can answer easily, and the recursive step which you can answer by modifying the solution of a simpler problem. For PERMUTATIONS, figure the recursive step is going to involve decreasing SIZE, so the base step is going to be when SIZE is 0, and the answer is a list of a zero-length permutation, i. e. (()).
To answer the recursive step, you have to figure out what to do to the result for size N - 1 to get a result for size N. To do this, it can help to write out some expected results for small N and see if you can discern a pattern:
ELEMENTS = (a b)
SIZE (PERMUTATIONS SIZE ELEMENTS)
0 ( () )
1 ( (a) (b) )
2 ( (a a) (a b) (b a) (b b) )
3 ( (a a a) (a a b) (a b a) (a b b) (b a a) ... )
So basically what you want to do is, given R = (permutations n elements), you can get (permutations (+ n 1) elements) by taking each permutation P in R, and then for each element E in ELEMENTS, adjoin E to P to create a new permutation, and collect a list of them. And we can do this with nested MAPs:
(define (permutations size elements)
(if (zero? size)
'(())
(flatmap (lambda (p) ; For each permutation we already have:
(map (lambda (e) ; For each element in the set:
(cons e p)) ; Add the element to the perm'n.
elements))
(permutations (- size 1) elements))))
I'm using FLATMAP for the outer mapping, because the inner MAP creates lists of new permutations, and we have to append those lists together to create the one big flat list of permutations that we want.
Of course, this is all assuming you know about and have a good handle on sequence operations like MAP. If you don't it'd be real difficult to come up with an elegant solution like I just did here.
Here is another version: I used reduce, not flatmap. I wrote it in MIT-scheme.
(define (per s)
(define (ins c before after)
(if (null? after)
(list (append before (list c)))
(append (list (append before (list c) after))
(ins c
(append before (list (car after)))
(cdr after)))))
(define (iter l)
(cond ((null? l)
'(()))
(else
(let ((rest (iter (cdr l))))
(reduce-left append
()
(map (lambda (x) (ins (car l) () x) )
rest))))))
(iter s))
(per '(1 3 2 4))
Hint: You can use parameters to a recursive call to "remember" what other recursive calls have done. ;)

Resources