I am trying to write a function that computes the squared Euclidean distance. I originally stored the data inside lists of the form:
'(1 8 0 0 0 1 0 5 0 1)
'(1 0 2 0 0 0 0 5 0 0)
And basically what I try to obtain is the sum of:
'(0 64 4 0 0 1 0 0 0 1)
Using lists this isn't hard to achieve, like with the code from bellow:
(define (f a b)
(apply + (map (λ(x y) (sqr (- x y))) a b)))
However the data that I'm working with got quite many zeros in it, so instead I tried to replace lists with hash-sets, like so:
'#hash((0 . 1) (1 . 8) (5 . 1) (7 . 5) (9 . 1))
'#hash((0 . 1) (2 . 1) (7 . 5))
Here when I try to rewrite the f function but with hash-sets I get stuck, because I don't know how to iterate over both of them directly. What I wrote so far doesn't count the elements that are in the second hash-set but not in the first one.
(define (f a b)
(for/fold ([sum 0])
([(k v) (in-hash a)])
(+ sum (sqr (- (hash-ref b k 0) v)))))
Is there a way to achieve this in a fast way (preferably using a single for)? Or perhaps is there a better way to work with sparsed lists (that contain many zeros)?
One solution would be to get a list of all indices which occur in either of the sparse vectors, and then to map over that list of indices to calculate the squared distances:
(define (sparse-sum-of-squares u v)
(let ((indices (remove-duplicates (append (hash-keys u) (hash-keys v)))))
(apply + (map (lambda (i) (let ((x (hash-ref u i 0))
(y (hash-ref v i 0)))
(sqr (- x y))))
indices))))
You should probably do some actual testing on your data to see if performance is an issue before you start complicating the data representation. After fixing the sparse vectors in the posted example so that they match, here are the results:
sparse-vector.rkt> (f '(1 8 0 0 0 1 0 5 0 1)
'(1 0 2 0 0 0 0 5 0 0))
70
sparse-vector.rkt> (sparse-sum-of-squares '#hash((0 . 1) (1 . 8) (5 . 1) (7 . 5) (9 . 1))
'#hash((0 . 1) (2 . 2) (7 . 5)))
70
The thing is, we need to handle missing values in both hashes. Iterating only over indexes with actual values, we can do something like this:
(define (squared-euclidean-distance a b)
(for/fold ([sum 0])
([idx (set-union (hash-keys a) (hash-keys b))])
(+ sum (sqr (- (hash-ref a idx 0)
(hash-ref b idx 0))))))
We simply return 0 if an index is missing. It works as expected:
(squared-euclidean-distance
'#hash((0 . 1) (1 . 8) (5 . 1) (7 . 5) (9 . 1))
'#hash((0 . 1) (2 . 2) (7 . 5)))
=> 70
How would I write a function in Dr. Racket which consumes a list of list of integers and produces a new list of list of integers with a transformation (sqr) applied to each element.
Note: There is an equal number of elements in each list.
Here are two examples to show what I am saying:
Example 1:
(list (list 1 2) (list 3 -2))
Should produce:
(list (list 1 4) (list 9 4))
Example 2:
(list (list 3 4 5) (list 2 1 3) (list 2 3 7) (list 0 -3 2))
Should produce:
(list (list 9 16 25) (list 4 1 9) (list 4 9 49) (list 0 9 4))
Here is my code so far:
(define (transform-to-sqr b)
(map sqr b))
If I type in:
(transform-to-sqr (list (list 1 2) (list 3 -2)))
I get an error message saying:
sqr: expected a number; given (list 1 2).
Why is this happening. Can someone please tell me what I am doing wrong.
Thanks for your help.
The map higher-order procedure applies a procedure over the elements of a list, but in this case the elements are lists themselves. To operate on the nested elements, we need to nest calls to map:
(define (transform-to-sqr matrix)
(map (λ (row) (map sqr row))
matrix))
It works as expected:
(transform-to-sqr '((1 2) (3 -2)))
=> '((1 4) (9 4))
(transform-to-sqr '((3 4 5) (2 1 3) (2 3 7) (0 -3 2)))
=> '((9 16 25) (4 1 9) (4 9 49) (0 9 4))
I want to define a functionality in common lisp which uses some words/symbols not known to lisp, for example having such a function/macro:
(my-func-or-macro lst key-word idx)
which returns items in the lst upto the idx if the key-word is to and from the idx to the end if the key-word is from.
So practically it should work like:
(my-func-or-macro '(1 2 3 4 5 6) from 3) => '(4 5 6)
and
(my-func-or-macro '(1 2 3 4 5 6) to 3) => '(1 2 3)
Since macros don't evaluate their arguments i think i should be using a macro which doesn't care about from and to (note i don't want to pass quoted args like 'from 'to).
Since every argument to a function is evaluated before the function is executed, you need a symbol that evaluates to itself.
Such symbols are already part of the language: all symbols in the special KEYWORD package evaluate to themselves. Symbols that are written with a leading colon, e. g. :foo are interned into that package.
Also part of the language are keyword arguments that use such keywords to identify parameters:
(defun my-func (list &key from)
(subseq list from))
(my-func '(0 1 2 3 4 5) :from 3)
=> (3 4 5)
You can give default values to such parameters:
(defun my-func (list &key (from 0) (to (length list)))
(subseq list from to))
(my-func '(0 1 2 3 4 5) :from 3)
=> (3 4 5)
(my-func '(0 1 2 3 4 5) :to 3)
=> (0 1 2)
(my-func '(0 1 2 3 4 5) :from 1 :to 4)
=> (1 2 3)
Keyword arguments can be given in any order:
(my-func '(0 1 2 3 4 5) :to 4 :from 1)
=> (1 2 3)
I'm trying to create a lisp macro that has an &optional parameter with a default value. Unfortunately the parameter is processed differently depending on whether it is read from the default value or from parameters provided to the macro. The code fragment below reproduces the issue:
(setf table1 '((1 2 3)
(4 5 6))
table2 '((10 20 30)
(40 50 60)))
(defmacro test-lambda (f &optional (tableau table1))
`(list ,f ,tableau))
? (test-lambda 0 table2) ;; This works...
(0 ((10 20 30) (40 50 60)))
? (test-lambda 0) ;; ...but this doesn't
> Error: Car of ((1 2 3) (4 5 6)) is not a function name or lambda-expression.
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process listener(1).
> Type :POP to abort, :R for a list of available restarts.
> Type :? for other options.
1 >
I don't quite understand why the macro won't work with the default value in the second case. Is there a better way to code this or at least a workaround?
Thanks,
What
You need to quote the default argument value:
(defmacro test-lambda-1 (f &optional (tableau 'table1))
`(list ,f ,tableau))
(test-lambda-1 0)
==> (0 ((1 2 3) (4 5 6)))
Why
You need to think how Common Lisp evaluates your code: when it sees (test-lambda ...), it
expands the macro
evaluates the resulting code
Let us try it:
(macroexpand '(test-lambda 0))
==> (LIST 0 ((1 2 3) (4 5 6))) ; T
(macroexpand '(test-lambda-1 0))
==> (LIST 0 TABLE1) ; T
(macroexpand '(test-lambda 0 table2))
==> (LIST 0 TABLE2) ; T
(macroexpand '(test-lambda-1 0 table2))
==> (LIST 0 TABLE2) ; T
Now you can see where the error is coming from: you did not quote the default value of the argument, so it got evaluated twice.
I am trying to return a list which contains non-negative numbers from function parameter list using clisp.
(defun recursive (L)
(setq ret (list))
(setq first (car L))
(setq rest (cdr L))
(if (null L)
0
(if (>= first 0)
(nconc ret (first))
(recursive rest))))
(setq mylist (list 1 2 3 -1 0 -3))
(write (recursive mylist))
I wrote this and expecting an output as (1 2 3 0)
What is wrong in that code?
Let filter be the function you want to implement.
Then (filter nil) should return nil.
In the general case, you compte (filter (number . tail)) recursively. Assuming that filter computes the list of positive numbers in a list, you can solve the problem for tail, and call (filter tail). In order to solve your current problem, you have to consider if number is positive or not, and add the element to the recursive result accordingly.
(defun filter (list)
(etypecase list
(null nil)
(cons (destructuring-bind (number . tail) list
(if (plusp number)
(cons number (filter tail))
(filter tail))))))
I am using ETYPECASE, PLUSP, DESTRUCTURING-BIND, but you can express the same differently. Note that you used NCONC which requires iterating over the whole list, which is not required and makes your whole aproach quadratic in time.
The above function has a flaw because the size of the call stack grows linearly with the size of your input list. Each time you call filter, a new frame is allocated on the stack, which can be easily seen with TRACE:
CL-USER> (trace filter)
(FILTER)
CL-USER> (filter '(0 1 -2 3 -4 -5 6 7 -8 9))
0: (FILTER (0 1 -2 3 -4 -5 6 7 -8 9))
1: (FILTER (1 -2 3 -4 -5 6 7 -8 9))
2: (FILTER (-2 3 -4 -5 6 7 -8 9))
3: (FILTER (3 -4 -5 6 7 -8 9))
4: (FILTER (-4 -5 6 7 -8 9))
5: (FILTER (-5 6 7 -8 9))
6: (FILTER (6 7 -8 9))
7: (FILTER (7 -8 9))
8: (FILTER (-8 9))
9: (FILTER (9))
10: (FILTER NIL)
10: FILTER returned NIL
9: FILTER returned (9)
8: FILTER returned (9)
7: FILTER returned (7 9)
6: FILTER returned (6 7 9)
5: FILTER returned (6 7 9)
4: FILTER returned (6 7 9)
3: FILTER returned (3 6 7 9)
2: FILTER returned (3 6 7 9)
1: FILTER returned (1 3 6 7 9)
0: FILTER returned (1 3 6 7 9)
This happens because you need to remember each intermediate value of number across recursive calls, in order to cons them with a recursive result. If you could instead have done all your work before descending into a recursive call, then there would be no need to retain intermediate values, and the function would be recursive terminal and could be subject to what is known as tail-call optimization.
In order to do that, you have to build the resulting list before calling the recursive call, through an accumulator:
(defun filter (list accumulator)
(etypecase list
(null accumulator)
(cons (destructuring-bind (head . tail) list
(if (plusp head)
(filter tail (cons head accumulator))
(filter tail accumulator))))))
Notice the repetition, which can be refactored as:
(filter tail (if (plusp head) (cons head accumulator) accumulator))
Here above, we added an accumulator, which holds the new list. Initially, you should pass an empty list. When you reach the end of your input list, you return the accumulator. Otherwise, you add the number to the accumulator before calling filter recursively. The difference is that you don't need to store intermediate values in the call stack. The trace macro produces this:
0: (FILTER (0 1 -2 3 -4 -5 6 7 -8 9) NIL)
1: (FILTER (1 -2 3 -4 -5 6 7 -8 9) NIL)
2: (FILTER (-2 3 -4 -5 6 7 -8 9) (1))
3: (FILTER (3 -4 -5 6 7 -8 9) (1))
4: (FILTER (-4 -5 6 7 -8 9) (3 1))
5: (FILTER (-5 6 7 -8 9) (3 1))
6: (FILTER (6 7 -8 9) (3 1))
7: (FILTER (7 -8 9) (6 3 1))
8: (FILTER (-8 9) (7 6 3 1))
9: (FILTER (9) (7 6 3 1))
10: (FILTER NIL (9 7 6 3 1))
10: FILTER returned (9 7 6 3 1)
9: FILTER returned (9 7 6 3 1)
8: FILTER returned (9 7 6 3 1)
7: FILTER returned (9 7 6 3 1)
6: FILTER returned (9 7 6 3 1)
5: FILTER returned (9 7 6 3 1)
4: FILTER returned (9 7 6 3 1)
3: FILTER returned (9 7 6 3 1)
2: FILTER returned (9 7 6 3 1)
1: FILTER returned (9 7 6 3 1)
0: FILTER returned (9 7 6 3 1)
Please note that the function is tail-recursive, but doesn't look like it was optimized away because there is an arrow-shaped trace. However, trace is not a reliable way of knowing if the function is or isn't tail-recursive, because the act of tracing changes hat is actually done. Or, maybe the debug quality is so high that tail-call optimization is not applied. This depends on your implementation. Please note that the trace clearly shows how the intermediate list is built, and how the result is passed unchanged from deep levels to higher ones. See also that the list is being built in reverse, because we keep calling cons with the accumulator (which is efficient, contrary to nconc).
Since you didn't specify if you want the elements of the list to retain the same order as the input list, I assumed that this is not required.
However, you could also call NREVERSE on the resulting list to reverse it destructively (i.e. in-place, without allocating memory). This is ok if here because you own the fresh list being built, so you can safely modify it before giving it to the caller. This is best done by wrapping the implementation detail inside a local function:
(defun filter (list)
(labels ((filter (list accumulator)
(etypecase list
(null accumulator)
(cons (destructuring-bind (head . tail) list
(filter tail (if (plusp head)
(cons head accumulator)
accumulator)))))))
(nreverse (filter list nil))))
Note that filter is lexically bound to a local function inside the global filter function. See also LABELS.
However, you can better spend your time than writing recursive functions to perform loops. Common Lisp provide iteration construction, which means you can simply do this:
(defun filter (list)
(loop for number in list
when (plusp number)
collect number))
Note that removing elements from lists is also easily done with REMOVE-IF-NOT.
First off, your code doesn't work, because of the way you are using first as a function ((first)) in the then-branch of your if.
Apart from that, every time you call recursive, you re-initialize ret to an empty list. And inside the if you only recurse if the number is not bigger than 0.
Here's a working solution using cond:
(defun filter-non-negative (l)
(cond
((null l) ;; empty list
nil)
((>= (first l) 0) ;; number >= 0
(cons (first l) (filter-non-negative (rest l))))
(t ;; all other cases
(filter-non-negative (rest l)))))
(write (filter-non-negative '(1 2 3 -1 0 -3)))
;; (1 2 3 0)
First of all, the variables ret, first and rest should be defined locally with a let. In your version they are global variables. Note that you don't need these variables at all, you can simply use the function calls directly.
In the line before last, you have (first), which will signal an error because this function expects an argument. However, what you want is not the function first but the variable first, therefore you need (list first).
When the list is null, you return a 0. Since you will reach this point at the end of every recursive call, this will add a 0 to any input argument. You should return nil instead.
Finally, instead of nconc look at the function cons.
Incidentally, note that there is a function remove-if that will do exactly the job you want, but I understand that you are trying to learn about recursive calls.
I hope this helps.
You want to keep the positive numbers. Positive numbers are greater 0.
Let's remove all numbers which are not positive:
CL-USER 24 > (remove-if-not #'plusp (list 1 2 3 -1 0 -3))
(1 2 3)
or
CL-USER 25 > (remove-if (complement #'plusp) (list 1 2 3 -1 0 -3))
(1 2 3)