I am trying to write a function that creates a list of the fibonacci sequence but stops when a certain value is found in the list, then returns that list (I hope that makes sense).
So for example if I give it fib-list(55), the function should return:
(1 1 2 3 5 8 13 21 34 55)
So it's not the 55th fibonacci number I want, its the list UP TO the value 55.
The code I have for returning the list so far looks like this:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((equal? n (car fs)) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
(display (fib-list 55))
My main problem is finding if an element is in the list, because at the moment I just get an error on the line where I am trying to write the ((equal? statement.
The error says:
mcar: contract violation
expected: mpair?
given: '()
I am still very VERY new to Scheme, so my understanding of the language as a whole isn't great. So please be gentle when telling me why my code sucks/doesn't make sense.
(list) creates an empty list, and on the first iteration you get to (car fs), which tries to apply car to an empty list, and that's an error.
Your code seems a bit confused about the nature of n.
Your description says that it's the largest number you want, but you're recursing like you want the n:th Fibonacci number - terminating on (zero? n) and recursing on (- n 1).
When you're recursing you're still looking for numbers up to the same limit.
Thus, you should not decrement your limit and terminate on zero, you should leave the limit alone and terminate when you reach larger numbers.
Here's how I would write it:
The initial list is (1 1)
At each step:
Compute the next fibonacci number
If this is greater than the limit, reverse the accumulator list and return it
Otherwise, cons it to the accumulator and recurse with the "new" last two fibonacci number.
In code:
(define (fib-list n)
(let loop ((f2 1) (f1 1) (fs '(1 1)))
(let ((next (+ f1 f2)))
(if (> next n)
(reverse fs)
(loop f1 next (cons next fs))))))
Here's another way you can do it using continuation-passing style. By adding a continuation parameter to our loop, we effectively create our own return mechanism. One unique property of this implementation is the output list is built in forward order and does not need to be reversed when n reaches zero.
(define (fib-list n)
(let loop ((n n) (a 0) (b 1) (return identity))
(if (zero? n)
(return empty)
(loop (sub1 n)
b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 10)
;; '(0 1 1 2 3 5 8 13 21 34)
Reading your question a little closer, in fib-list(N) you need N to be the stopping condition for your loop, not the Nth term in the list. This is actually easier to implement as there's no need to count the number of terms generated.
(define (fib-list max)
(let loop ((a 0) (b 1) (return identity))
(if (> a max)
(return empty)
(loop b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 55)
;; '(0 1 1 2 3 5 8 13 21 34 55)
(fib-list 1000)
;; '(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987)
What's going wrong with the car function?
The car function takes the first element of a list, but if the list is empty it doesn't have a first element. The fs list starts out as empty. When you try to take the first element of an empty list you get this error message:
> (car (list))
mcar: contract violation
expected: mpair?
given: ()
If the list isn't empty, then it has a first element, and it's fine:
> (car (list 4 5 6))
4
Following what you meant in the comment
However, your comment "Check if n is in list" leads me to believe that (equal? n (car fs)) is not what you want anyway. The function for determining whether an element is in a list is called member.
#!r6rs
(import (rnrs base)
(rnrs lists))
> (if (member 4 (list 1 2 4 8))
"it's in the list"
"go fish")
"it's in the list"
> (if (member 5 (list 1 2 4 8))
"it's in the list"
"go fish")
"go fish"
So with that (equal? n (car fs)) test replaced with (member n fs), your code looks like:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((member n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(10946 6765 4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1)
This is not the answer you wanted though; you wanted (1 1 2 3 5 8 13 21 34 55).
Why is the list going past 55?
One of the problems is that the n is shadowed, in the same way that in this expression:
> (let ([n 5])
(let ([n 10])
n))
10
The n in the body refers to 10 instead of 5.
The result is going past 55 because inside the loop n is shadowed and has become a different number. I'm guessing in your comment about "check if n is in list", you meant "check if the original n is in list". To do that you have to rename one of the ns:
> (let ([orig-n 5])
(let ([n 10])
orig-n))
5
In the context of your code:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return list.
((member orig-n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(55 34 21 13 8 5 3 2 1 1)
Reversing
This is closer, but it's reversed. You have two base cases, the (zero? n) case and the (member orig-n fs) case. In one of those it's reversed and in one of them it's not. Changing them both to call reverse fixes it:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
Small numbers
This is correct on large Fibonacci numbers like 55, but it still does something weird on small numbers:
> (fib-list 2)
(1 1)
> (fib-list 3)
(1 1 2)
If you only want it to stop when it gets to orig-n, then maybe the decreasing n argument is not needed, and is actually making it stop too early. Removing it (and removing the zero check for it) makes the member check the only stopping case.
This is dangerous, because it could go into an infinite loop if you give it a non-Fibonacci number as input. However, it fixes the small-number examples:
; Create a list of the fibonacci sequence up to n.
; The `orig-n` MUST be a fibonacci number to begin with,
; otherwise this loops forever.
(define (fib-list orig-n)
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 2)
(1 1 2)
> (fib-list 3)
(1 1 2 3)
And finally, consider what happens vs. what should happen if you give it a number like 56.
> (fib-list 56)
;infinite loop
This is a design decision that you have not specified in your question (yet), but there are ways of solving it either way.
Update: orig-n or greater
I should have specified that I need to check if there is a number that is greater than OR equal to orig-n. Can I still use the member function to check for this or will I need to use something different?
You will have to use something different. Just above member in the documentation is the memp function (you could also use exists in this case). The mem is short for member, and the p is short for "predicate". It determines whether any member of the list matches a certain predicate.
> (if (memp positive? (list -4 -2 -3 5 -1))
"one of them is positive"
"go fish")
"one of them is positive"
> (if (memp positive? (list -4 -2 -3 -5 -1))
"one of them is positive"
"go fish")
"go fish"
> (define (five-or-greater? n)
(>= n 5))
> (if (memp five-or-greater? (list -4 -2 -3 6 -1))
"one of them is equal to 5 or greater"
"go fish")
"one of them is equal to 5 or greater"
> (if (memp five-or-greater? (list -4 -2 -3 4 -1))
"one of them is equal to 5 or greater"
"go fish")
"go fish"
To use it for "orig-n or greater", you would have to define a function like:
(define (orig-n-or-greater? n)
(>= n orig-n))
As a local function inside your main function, so that it can refer to orig-n. Then you can use it like (memp orig-n-or-greater? fs).
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
(define (orig-n-or-greater? n)
(>= n orig-n))
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n or greater is in list. If so, return reversed list.
((memp orig-n-or-greater? fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 3)
(1 1 2 3)
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 56)
(1 1 2 3 5 8 13 21 34 55 89)
I'm pretty new to Common Lisp. And I try to build my own operator functions.
In the first function I tried to add one to the given number.
The second function we do a recursive use of the first in the frequency of m.
When I enter totaladd ( 5 3 ) I expect an 8.
What can I do about the undefined funciton k?
(defun add1(n)
(+ n 1)
)
(write (add1 5))
(defun totaladd (k m)
(if (eq m 0)
0
(totaladd(add1(k) (- m 1)))
)
)
(write (totaladd 5 3))
There are three errors in the next line:
(totaladd(add1(k) (- m 1)))
Let's look at it:
(totaladd ; totaladd is a function with two parameters
; you pass only one argument -> first ERROR
(add1 ; add1 is a function with one parameter
; you pass two arguments -> second ERROR
(k) ; K is a variable, but you call it as a function,
; but the function K is undefined -> third ERROR
(- m 1)))
(defun add1 (n) (+ n 1))
(defun totaladd (k m)
(if (= m 0)
k
(add1 (totaladd k (- m 1)))))
There is a extra function for (= ... 0) called zerop which asks whether a number os zero or not. Very frequently used when recursing over numbers as the break condition out of the recursion.
There is also an extra function for (- ... 1) or (+ ... 1) because these are common steps when recursing with numbers: (1- ...) and (1+ ...), respectively.
(Their destructive forms are (incf ...) and (decf ...), but these are not needed for recursion.)
So, using this, your form becomes:
(defun totaladd (k m)
(if (zerop m)
k
(add1 (totaladd k (1- m)))))
I'm looking to create a function that returns a list of 'n' functions each of which increments the input by 1, 2, 3... n respectively.
I use DrRacket to try this out. A sample of expected outcome :
> (map (lambda (f) (f 20)) (func-list 5))
(21 22 23 24 25)
I'm able to write this down in a static-way :
> (define (func-list num)
> (list (lambda (x) (+ x 1)) (lambda (x) (+ x 2)) (lambda (x) (+ x 3)) (lambda (x) (+ x 4)) (lambda (x) (+ x 5)))
[Edit]
Also that a few restrictions are placed on implementation :
Only 'cons' and arithmetic operations can be used
The func-list should take as input only one parameter ('n' being the number of functions to be returned in this case)
It would be great if somebody can help me out. Thanks in advance.
Instead of explicitly writing out the list, a better approach would be to recursively construct it for an arbitrary n, as follows:
(define (func-list n)
(define (func-lst a n)
(if (> a n)
empty
(cons (lambda (x) (+ x a))
(func-lst (add1 a) n))))
(func-lst 1 n))
For example:
> (map (lambda (f) (f 20)) (func-list 0))
'()
> (map (lambda (f) (f 20)) (func-list 5))
'(21 22 23 24 25)
ive been given a task in Scheme (Dr Racket) to reverse to order of a given digit. The solution should be recursive, and this is what i got this far..
The truth is, im not quite sure if the given algorithm even works because i get:
" application: not a procedure;
expected a procedure that can be applied to arguments"
error every time i run it..
Any thoughts or help on the issue?
(define reverse-digits
(lambda (n) (if (> n 9)
(+ (* 10 (modulo n 10)) (reverse-digits (quotient n 10)))
(n))))
(reverse-digits 1234)
This is a HW assignment so I won't give you code.
Your problem is that multiplying (modulo n 10) by 10 doesn't get you to the position you need to be in. Consider (reverse-digits 123):
(reverse-digits 123)
(+ 30 (reverse-digits 12))
(+ 30 (+ 20 (reverse-digits 1)))
(+ 30 (+ 20 1))
51
What you want is to multiply it by a different power of 10 every time depending on the length of the number. You could either make a function that calculates the length of the number (possibly by repeatedly dividing the number by 10 and keeping track of how many times it did that) or passing along the length of the number (possibly by creating another function that takes the number n as an argument and calculates the length, then passes it along to your function which will then subtract 1 from length every recursive call.
What you would then get is something like this:
(reverse-digits 123)
(+ 300 (reverse-digits 12))
(+ 300 (+ 20 (reverse-digits 1)))
(+ 300 (+ 20 1))
321
The error you're getting is because in your else-case, you do (n). As n is not a procedure, you get an error. You just want n instead.
Are you bound to using specific procedures ? If not, there's an alternative to using modulo and adding numbers. It's about using list procedures such as
number->string
take
list->string
and so on.
This is my solution, it is not very efficient!
(define
invert-number-aux (λ (n res)
(if (empty? n) res
(invert-number-aux
(take n (-(length n) 1)) ;new n
(append res (list (last n))) ;new res
)
)))
(define
invert-number (λ (n)
(string->number (list->string (invert-number-aux (string->list(number->string n)) '())))
))
It will be helpful to use smaller helper functions.
Here is one way to split the task in smaller parts:
; number->digits : natural -> list-of-digits
(define (number->digits n)
...)
; digits->number : list-of-digits -> natural
(define (number->digits n)
...)
With these helpers you can write:
(define (reverse-number x)
(digits->number
(reverse
(number->digits x))))
Also - if you want to the error " application: not a procedure; expected a procedure that can be applied to arguments" replace (n) with n.
If you run your program in DrRacket, the application (n) ought to be colored red. The problem is that (42) means evaluate 42 and then call the result as if is a function. Since 42 is a number, you get the error.
Its important to understand that fixnums don't have just one representation and what the different digits are of a number might change with the base of its representation. Here is my take on it.
(define (number->digits number (base 10))
(let loop ((n number) (acc '()))
(if (zero? n)
acc
(let-values (((res rem) (quotient/remainder n base)))
(loop res (cons rem acc))))))
(define (list->number lst (base 10))
(foldl (lambda (x acc)
(+ (* acc base) x))
0
lst))
(define (reverse-digits number (base 10))
(list->number (reverse (number->digits number base))
base))
(number->string (reverse-digits #b100111 #b10) #b10) ; ==> "111001" (or 39 => 57 in base 10)
(number->string (reverse-digits #xebabefac #x10) #x10) ; ==> "cafebabe" (or 3953913772 => 3405691582 in base 10)
(number->string (reverse-digits 1234)) ; ==> 4321
This is what I did until now it tells me that it is not of type list.
(defun number_list(n)
(setf x
(if (zerop (truncate n 10))
(list n)
(append (number_list (truncate n 10)) (list (mod n 10)))))
(length x))
When I remove the (length x) I can see that the result is a list however.
Would appreciate any help.
Your solution uses a global variable x, which is generally a bad idea, especially in recursive functions. Then, you create a list in order to count the number of digits. This is not really necessary.
Using a list
If you want to work with a list, I suggest you split the problem in 2 parts:
1. convert a number to a list
Your function works well for this if you remove setf x:
(defun number_list(n)
(if (zerop (truncate n 10))
(list n)
(append (number_list (truncate n 10)) (list (mod n 10)))))
2. count the number of digits
(defun numdigits (n)
(length (number_list n))).
Alternative
But I would suggest a simple recursive definition such as:
(defun numdigits (n)
(if (< -10 n 10)
1
(1+ (numdigits (truncate n 10)))))
If you want to get the decimal digits and then count the length, assuming that numbers are 0 or greater integers.
(defun number-list (n)
(if (< n 10)
(list n)
(cons (mod n 10)
(number-list (truncate n 10)))))
CL-USER 44 > (length (number-list 123456789))
9
But it is preferable to directly count the digits. See the other answers.