This question already has an answer here:
Nested Loops Using Loop Macro in Common Lisp
(1 answer)
Closed 2 years ago.
I want to create a list of pairs (a . b) with 1 < a < b <= n up to n, e.g. n = 5:
((2 . 3) (2 . 4) (3 . 4) (2 . 5) (3 . 5) (4 . 5))
(The order of the pairs is not critical.)
I came up with the code
(defun create-pairs (upper-bound)
(loop for i from 3 to upper-bound
for j from 2 to (1- upper-bound)
collecting (cons j i)))
but that doesn't do what I wanted
* (create-pairs 5)
((2 . 3) (3 . 4) (4 . 5))
since the loops are incrementing at the same time.
Therefore I tried this
(defun create-pairs (upper-bound)
(loop for i from 3 to upper-bound do
(loop for j from 2 to (1- upper-bound)
collecting (cons j i))))
with the result:
* (create-pairs 5)
NIL
I don't remember where but I read that it's not possible to use collecting in constructs like my second try.
So how do I get the result I want to have? Isn't it possible to solve this with loop for?
You are almost there - you just need to accumulate the results of the inner loop:
(defun create-pairs (upper-bound)
(loop for i from 3 to upper-bound nconc
(loop for j from 2 below i
collect (cons j i))))
(create-pairs 5)
==> ((2 . 3) (2 . 4) (3 . 4) (2 . 5) (3 . 5) (4 . 5))
Related
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
I have a function that return two splited list like below :
((1 . 2) (3 . 4) (5 . 7))
((8 . 9) (10 . 23) (30 . 20))
Is there any resource in common lisp to do like python
a,b = 1,2
a = 1
b = 2
There are two options. First, you can return multiple values with VALUES. You can then use MULTIPLE-VALUE-BIND to bind the return values to different variables.
(defun foo ()
(values '((1 . 2) (3 . 4) (5 . 7))
'((8 . 9) (10 . 23) (30 . 20))))
(multiple-value-bind (a b) (foo)
(format t "~&A: ~s~%B: ~s~%" a b))
; A: ((1 . 2) (3 . 4) (5 . 7))
; B: ((8 . 9) (10 . 23) (30 . 20))
This is a little different from Python, because you can call the function as if it only returned one value, and the other values will be silently discarded. Multiple return values are usually used when the first value makes sense on its own, and the others are just supplementary information (see for example FLOOR).
In this case it seems like the two values are related to each other (so that it never makes sense to use only the first value). So in this case it's probably better to return a list, or a cons-cell, instead. You can use DESTRUCTURING-BIND to assign the elements to variables.
(defun bar ()
(list '((1 . 2) (3 . 4) (5 . 7))
'((8 . 9) (10 . 23) (30 . 20))))
(destructuring-bind (a b) (bar)
(format t "~&A: ~s~%B: ~s~%" a b))
; A: ((1 . 2) (3 . 4) (5 . 7))
; B: ((8 . 9) (10 . 23) (30 . 20))
If you already have two variables a and b, you can assign the values:
CL-USER 6 > (let ((a 10)
(b 3))
(multiple-value-setq (a b) (truncate a b))
(list a b))
(3 1)
or alternatively using SETF:
CL-USER 7 > (let ((a 10)
(b 3))
(setf (values a b) (truncate a b))
(list a b))
(3 1)
#lang racket
I need to create a pair from an element and a list
however when I do (cons 2 (list 1 2 3)) I get (2 (1 2 3)), I want to get (2 . (1 2 3))
how do I get the dot in ?
Since (cons a b) is the same as (a . b) we get that (2 . (1 2 3)) is the same as (cons 2 (list 1 2 3) which is the same as (list 2 1 2 3). To confirm:
> (cons 2 (list 1 2 3))
'(2 1 2 3)
> '(2 . (1 2 3))
'(2 1 2 3)
Note that the printer prints (2 1 2 3) and not (2 . (1 2 3)). The printer attempts to use the dot only when absolutely needed.
There is a difference between the syntax that explains the structure, how it's stored and how display would represent it.
For a list of two elements there are two ways you can represent it (1) and (1 . ()). When this list is displayed it will always prefer the one with the least parentheses. Thus '(2 . (1 2 3)) will always be printed as (2 1 2 3) by display. If you don't want that you can make yourself a cons-write like:
;; displays cons always as dotted
(define (cons-write x)
(if (pair? x)
(begin
(display "(")
(cons-write (car x))
(display " . ") ; spaces are important
(cons-write (cdr x))
(display ")"))
(write x)))
(cons-write '(1 2 3 4)) ; prints (1 . (2 . (3 . (4 . ()))))
A function that receives a list with sublist's M*N and returns the sum of all elements of the sublist's
example: (solution '( (1 2 3) (4 5 6) ) )
return: (5 7 9)
Sry for the bad english
thks =)
A Common Lisp version is almost the same as in Scheme:
(defun solution (list)
(apply #'mapcar #'+ list))
(solution '((1 2 3) (9 10 11) (3 4 5)))
; ==> (13 16 19)
It depends on what Lisp interpreter you're using. In Scheme, this will work:
(define (solution lsts)
(apply map + lsts))
For example:
(solution '((1 2 3) (4 5 6)))
=> '(5 7 9)
I'm having a bit of trouble with Lisp. What i'm attempting to do, is keep track of the amount of times a number appears in x number of lists. However, running this over and over again, lisp isn't recreating the variable, but using the ending value from the last time I called the function. So I'm wondering how can I get past the 'binding' powers of let?
So, I've got some list like this
(((8 7) (3)) ((8 3) (2)) ((7 3) (6)) ((7 2) (8)) ((6 7) (4 1))
((6 6) (4 1)) ((6 2) (2)) ((5 6) (3)) ((5 3) (8 3)) ((4 6) (4))
((4 4) (6)) ((4 1) (7)) ((3 7) (5 3)) ((3 4) (1)) ((3 3) (3)) ((3 1) (9))
((2 7) (7)) ((2 5) (2)) ((2 2) (5 2)) ((1 7) (1)) ((1 6) (6 1))
((1 1) (2 1)) ((1 0) (3)) ((0 7) (8 1)) ((0 5) (6)) ((0 3) (9 6))
((0 1) (1)))
Then I'm calling some function like this, (declaring var here doesn't seem to do anything, past the initial function call)... I guess some kind of binding from let.
(defun counter (possibleValues)
(let ((var '(0 0 0 0 0 0 0 0 0 0)))
(loop for i from 0 to (list-length possibleValues) do
(loop for j in (cdr (nth i possibleValues)) do
(loop for k in j do
(incf (nth k var)))))
var))
So I can run my list through the function and get something like
(0 8 5 6 3 2 5 2 3 2)
Each position referring to the number found in the list. So the value 8 would refer to how many times 1 was found in all the lists (i'm considering the second list only). Now the problem.... run it twice and...
(0 16 10 12 6 4 10 4 6 4)
I was using an associative list earlier, but in trying to figure this out and keep things simple, i'm now using a list. I guess another question I have is, how can I create associative list elements on the fly? I don't like declaring 'var' like that, but I'm just trying to get around 'let' for the moment. I haven't had much luck with 'setq' or 'setf' either....
Thanks in advance for your help!
Change the initialization form for VAR to be an expression that creates new lists, such as (make-list 10 :initial-element 0) or even (list 0 0 0 0 0 0 0 0 0 0).
Basically, do not ever use quoted objects if you have intentions on modifying them, as the consequences are undefined if you do. In fact, evaluating that function definition gives a warning about that:
; in: LAMBDA NIL
; (INCF (NTH K VAR))
; --> LET*
; ==>
; (SB-KERNEL:%SETNTH #:TMP5 #:TMP4 #:NEW3)
;
; caught WARNING:
; Destructive function SB-KERNEL:%SETNTH called on constant data.
; See also:
; The ANSI Standard, Special Operator QUOTE
; The ANSI Standard, Section 3.2.2.3
;
; compilation unit finished
; caught 1 WARNING condition