I am trying to create a recursive function which picks n items from a list returning the picked values and the list without the values, but when I create my variables I get this error:
new-list: unbound identifier in: new-list
Here is my code:
(define(pick-randomr list n picked) ;;Picked always called as empty list
(if(= n 0) (values list picked)
((let* ([aux list]
[r (random (length aux))]
[value (list-ref aux r)]
[new-picked (cons value picked)]
[new-list (values (remove value aux))])
(values aux r new-list))
(pick-randomr new-list (- n 1) new-picked))))
EDIT:
The line that goes:
(values aux r new-list)
is just to not have an empty body
There are a couple of problems with your syntax:
You should not use list as a parameter name, it conflicts with a built-in procedure of the same name.
Don't surround let* with two brackets, that's a common mistake, brackets are not like curly braces in other languages, you must not use them to define a block of statements, use begin for that - but we don't need it in this particular case.
The first error you got stated that you must not define a let* with an empty body. But the expression you added there isn't right, you must write the expressions that use the variables inside the let*, otherwise the new-list variable won't be visible.
This is what you meant to write:
(define (pick-randomr lst n picked)
(if (= n 0)
(values lst picked)
(let* ([aux lst]
[r (random (length aux))]
[value (list-ref aux r)]
[new-picked (cons value picked)]
[new-list (values (remove value aux))])
(pick-randomr new-list (- n 1) new-picked))))
Let's test it:
(pick-randomr '(1 2 3 4 5) 2 '())
=> '(1 2 5)
'(3 4)
Related
I'm trying to get the hang of recursion in scheme. I put together a Fibinachi function and it keeps returning unspecified instead of a number. How do I make this function return a number and to unspecified?
(define (F n)
(if (= n 0)
0)
(if (= n 1)
1)
(if (< n 2)
(+
(F (- n 1))
(F (- n 2)))))
(display (F 5))
(newline)
The function returns
#<unspecified>
I'm using guile (GNU Guile) 2.0.13.
The issue here is that your code is:
(begin
(if a 1)
(if b 2)
(if c 3))
What is wrong with this? The value of that will be unspecified except if c is true.
Why? The value of each if is unspecified when the condition is false. The begin returns the value of the last expression.
Where did the begin come from you might ask as it didn't appear in my code? To make it easier every lambda and define contains an implicit begin which is why your code was even accepted for execution.
You should use either nested ifs or a cond form:
(if a 1
(if b 2
(if c 3)))
(cond (a 1)
(b 2)
(c 3))
I'm trying to get the lowest integer out of a vector only containing numbers. I know how to do it with lists. You compare the first two values of the list and depending on which is larger you either save your value to output it later or call the function again with the rest of the list (all elements except the first) using the cdr procedure.
But with vectors I'm completely lost. My guess would be that the way of thinking about the solution would be the same for lists and vectors. I've been reading on the racket-lang website but haven't been able to come up with a solution to the problem. The procedures I've been experimenting most with are vector-ref and vector-length as they seem to be the most useful in this problem (but this is my first time working with vectors so what do I know).
So my two questions are:
How can we get all values except the first from a vector? Is there a procedure like cdr but for vectors?
If you were working with lists you would use cons to save the values you would want to output. But is there a similar way of doing it when working with vectors?
Thanks!
The simplest solution is to use a variant of for called for/fold.
I thought there were an for/min but alas.
#lang racket
(define v (vector 11 12 13 4 15 16))
(for/fold ([m +inf.0]) ([x (in-vector v)])
(min m x))
If you like a more explicit approach:
(define (vector-min xs)
(define n (vector-length xs))
(let loop ([i 0] ; running index
[m +inf.0]) ; minimum value so far
(cond
[(= i n) ; if the end is reached
m] ; return the minimum
[else ; else
(define x (vector-ref v i)) ; get new element in vector
(loop (+ i 1) ; increment index
(min m x))]))) ; new minimum
UPDATE
(let loop ([x 1] [y 10])
(loop (+ x 1) (- y 1))
is the same as:
(let ()
(define (loop (x y)
(loop (+ x 1) (- y 1)))
(loop 1 10))
Vectors are O(1) access and indexed so it is a completely different data structure, however you have SEFI-43 which is like the SRFI-1 List library, but for vectors.
#lang racket
(require srfi/43)
(define (min-element lst)
(vector-fold min (vector-ref lst 0) lst))
(max-element #(7 8 1 2 3 4 5 12))
; ==> 1
The racket/vector module has vector-argmin for finding the minimum element of a vector (Well, the minimum after feeding the elements through a transformation function). Combine that with a function like identity from racket/function and it's trivial:
(vector-argmin identity '#(5 4 3 2 1 6))
I am trying to evaluate each atom of a list and see if it's equal to the number provided and remove if its not but I am running into a slight problem.
I wrote the following code:
(defun equal1(V L)
(cond((= (length L) 0))
(T (cond( (not(= V (car(equal1 V (cdr L))))) (cdr L) )))
)
)
(equal1 5 '(1 2 3 4 5))
I obtain the following error
Error: Cannot take CAR of T.
If I add (write "hello") for the action if true, the following error is obtained:
Error: Cannot take CAR of "hello".
I'm still quite new to LISP and was wondering what exactly is going on and how could I fix this so I could evaluate each atom properly and remove it if its not, thus the cdr L for the action.
car and cdr are accessors of objects of type cons. Since t and "hello" are not cons you get an error message.
To fix it you need to know what types your function returns and not car unless you know that it's a cons
EDIT
First off ident and clean up the code.. The nested cond are uneccesary since cond is a if-elseif-else structure by default:
(defun remove-number (number list)
(cond ((= (length list) 0)
t)
((not (= number (car (remove-number number (cdr list)))))
(cdr list))))
(t
nil)))
I want you to notice I've added the default behaviour of returning t when a consequent is not given as we know = returns either t or nil so it returns t when the length is 0 in this case.
I've added the default case where none of the two previous predicates were truthy and it defaults to returning nil.
I've named it according to the functions used. = can only be used for numeric arguments and thus this will never work on symbols, strings, etc. You need to use equal if you were after values that look the same.
Looking at this now we can see that the functions return value is not very easy to reason about. We know that t, nil and list or any part of the tail of list are possible and thus doing car might not work or in the case of (car nil) it may not produce a number.
A better approach to doing this would be:
check if the list is empty, then return nil
check if the first element has the same numeric value as number, then recurse with rest of the list (skipping the element)
default case should make cons a list with the first element and the result fo the recursion with the rest of the list.
The code would look something like this:
(defun remove-number (number list)
(cond ((endp list) '())
((= (car list) number) (remove-number ...))
(t (cons ...))))
There are a couple of things you could do to improve this function.
Firstly, let's indent it properly
(defun equal1 (V L)
(cond
((= (length L) 0))
(T (cond
((not (= V (car (equal1 V (cdr L))))) (cdr L))))))
Rather than saying (= (length l) 0), you can use (zerop (length l)). A minor sylistic point. Worse is that branch returns no value. If the list L is empty what should we return?
The issue with the function is in the T branch of the first cond.
What we want to do is
remove any list item that is the same value as V
keep any item that is not = to V
The function should return a list.
The expression
(cond
((not (= V (car (equal1 V (cdr L))))) (cdr L)))
is trying (I think) to deal with both conditions 1 and 2. However it's clearly not working.
We have to recall that items are in a list and the result of the equal function needs to be a list. In the expression above the result of the function will be a boolean and hence the result of the function call will be boolean.
The function needs to step along each element of the list and when it sees a matching value, skip it, otherwise use the cons function to build the filtered output list.
Here is a skeleton to help you out. Notice we don't need the embedded cond and just have 3 conditions to deal with - list empty, filter a value out, or continue to build the list.
(defun equal-2 (v l)
(cond
((zerop (length L)) nil)
((= v (car l)) <something goes here>) ;skip or filter the value
(t (cons (car l) <something goes here>)))) ;build the output list
Of course, this being Common Lisp, there is a built-in function that does this. You can look into remove-if...
I solved Project Euler's 8th problem using SBCL and the iterate package from quicklisp. In my code I defined a function that turns a number into a list of it's digits. Here's the source code:
(defun number-to-list (n)
(iter (for c in-string (write-to-string n)) (collect (digit-char-p c))))
The collect clause both in iter and in loop make a list out of the values. Is it possible to instead generate a vector (one dimensional array)?
Would my only option be to convert the list generated by number-to-list to a vector? Because that seems inefficient (although probably not that inefficient)
Usually there is one big problem: how large will the result vector be? It would be best to know that upfront, then we can allocate the vector once with the correct size. Otherwise we would have find ways to deal with that: use a resizable vector, allocate a list first and copy into a result vector later, allocate a larger vector with a fill pointer, ...
If you have a sequence, then one can use the Common Lisp function MAP: if the source object is a vector, here a string, its length is cheap to get.
CL-USER 1 > (map 'vector
#'digit-char-p
(write-to-string 5837457324534))
#(5 8 3 7 4 5 7 3 2 4 5 3 4)
You can use ITERATE and collect a vector:
FOO 32 > (defun number-to-vector (n)
(iter (for c in-string (write-to-string n))
(collect (digit-char-p c) result-type vector)))
NUMBER-TO-VECTOR
FOO 33 > (number-to-vector 8573475934)
#(8 5 7 3 4 7 5 9 3 4)
If you look at the macro expansion, it actually collects into a list and then calls COERCE to create the vector. So: no win in efficiency.
Note that this is another example where ITERATE is more powerful than LOOP: the standard LOOP can't directly return vectors from collect.
The proposed solutions are correct and elegant, but they first create a list, or trasform the number in string. I would like to propose a direct transformation from integers to arrays, without transforming first the number in a list or a string:
(defun digits(n)
"Transform a positive integer n in array of digits"
(let* ((logn (floor (log n 10)))
(result (make-array (1+ logn) :element-type '(integer 0 9))))
(loop for i downfrom logn to 0
do (setf (values n (aref result i)) (floor n 10)))
result))
The problem of allocating an array of the correct dimension is solved with the formula that gives the number of decimal digits of an integer n: ⌊log10 n⌋+1.
Maybe not a direct answer to your question but here are my num-to-list and list-to-num functions I frequently use.
(defun num-to-list-helper (n liste)
(cond ((< n 1) liste)
(t (num-to-list-helper (truncate (/ n 10)) (cons (rem n 10) liste))))))
(defun num-to-list (n)
(num-to-list-helper n nil))
(defun list-to-num-helper (liste n)
(if (null liste)
n
(list-to-num-helper (cdr liste)
(+ n (* (car liste) (expt 10 (1- (length liste))))))))
(defun list-to-num (liste)
(list-to-num-helper liste 0))
You could try these and see if there's an improvement over converting the number to string. Personally I don't prefer strings for numbers as I consider them as an ugly trick I was forced to do in my Java days.
You could also convert these functions to a version using vectors and see how they do.
So i was asked to do a function i LISP that calculates the average of any given numbers. The way i was asked to do this was by using the &rest parameter. so i came up with this :
(defun average (a &rest b)
(cond ((null a) nil)
((null b) a)
(t (+ (car b) (average a (cdr b))))))
Now i know this is incorrect because the (cdr b) returns a list with a list inside so when i do (car b) it never returns an atom and so it never adds (+)
And that is my first question:
How can i call the CDR of a &rest parameter and get only one list instead of a list inside a list ?
Now there is other thing :
When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there.
My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
EDIT: I know the function only does the + operation, i know i have to divide by the length of the b list + 1, but since i got this error i'd like to solve it first.
(defun average (a &rest b)
; ...
)
When you call this with (average 1 2 3 4) then inside the function the symbol a will be bound to 1 and the symbol b to the proper list (2 3 4).
So, inside average, (car b) will give you the first of the rest parameters, and (cdr b) will give you the rest of the rest parameters.
But when you then recursively call (average a (cdr b)), then you call it with only two arguments, no matter how many parameters where given to the function in the first place. In our example, it's the same as (average 1 '(3 4)).
More importantly, the second argument is now a list. Thus, in the second call to average, the symbols will be bound as follows:
a = 1
b = ((3 4))
b is a list with only a single element: Another list. This is why you'll get an error when passing (car b) as argument to +.
Now there is other thing : When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there. My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
(null b) will only be truthy when b is the empty list. But when you call (average a '()), then b will be bound to (()), that is a list containing the empty list.
Solving the issue that you only pass exactly two arguments on the following calls can be done with apply: It takes the function as well as a list of parameters to call it with: (appply #'average (cons a (cdr b)))
Now tackling your original goal of writing an average function: Computing the average consists of two tasks:
Compute the sum of all elements.
Divide that with the number of all elements.
You could write your own function to recursively add all elements to solve the first part (do it!), but there's already such a function:
(+ 1 2) ; Sum of two elements
(+ 1 2 3) ; Sum of three elements
(apply #'+ '(1 2 3)) ; same as above
(apply #'+ some-list) ; Summing up all elements from some-list
Thus your average is simply
(defun average (&rest parameters)
(if parameters ; don't divide by 0 on empty list
(/ (apply #'+ parameters) (length parameters))
0))
As a final note: You shouldn't use car and cdr when working with lists. Better use the more descriptive names first and rest.
If performance is critical to you, it's probably best to fold the parameters (using reduce which might be optimized):
(defun average (&rest parameters)
(if parameters
(let ((accum
(reduce #'(lambda (state value)
(list (+ (first state) value) ;; using setf is probably even better, performance wise.
(1+ (second state))))
parameters
:initial-value (list 0 0))))
(/ (first accum) (second accum)))
0))
(Live demo)
#' is a reader macro, specifically one of the standard dispatching macro characters, and as such an abbreviation for (function ...)
Just define average*, which calls the usual average function.
(defun average* (&rest numbers)
(average numbers))
I think that Rainer Joswig's answer is pretty good advice: it's easier to first define a version that takes a simple list argument, and then define the &rest version in terms of it. This is a nice opportunity to mention spreadable arglists, though. They're a nice technique that can make your library code more convenient to use.
In most common form, the Common Lisp function apply takes a function designator and a list of arguments. You can do, for instance,
(apply 'cons '(1 2))
;;=> (1 . 2)
If you check the docs, though, apply actually accepts a spreadable arglist designator as an &rest argument. That's a list whose last element must be a list, and that represents a list of all the elements of the list except the last followed by all the elements in that final list. E.g.,
(apply 'cons 1 '(2))
;;=> (1 . 2)
because the spreadable arglist is (1 (2)), so the actual arguments (1 2). It's easy to write a utility to unspread a spreadable arglist designator:
(defun unspread-arglist (spread-arglist)
(reduce 'cons spread-arglist :from-end t))
(unspread-arglist '(1 2 3 (4 5 6)))
;;=> (1 2 3 4 5 6)
(unspread-arglist '((1 2 3)))
;;=> (1 2 3)
Now you can write an average* function that takes one of those (which, among other things, gets you the behavior, just like with apply, that you can pass a plain list):
(defun %average (args)
"Returns the average of a list of numbers."
(do ((sum 0 (+ sum (pop args)))
(length 0 (1+ length)))
((endp args) (/ sum length))))
(defun average* (&rest spreadable-arglist)
(%average (unspread-arglist spreadable-arglist)))
(float (average* 1 2 '(5 5)))
;;=> 3.25
(float (average* '(1 2 5)))
;;=> 2.66..
Now you can write average as a function that takes a &rest argument and just passes it to average*:
(defun average (&rest args)
(average* args))
(float (average 1 2 5 5))
;;=> 3.5
(float (average 1 2 5))
;;=> 2.66..