I am trying to create subsequences of some word with the following code. When I added by k, the code stopped responding, though if I replace k with a particular number, it works. What is happening?
(let ((c nil)) (loop for k from 0 to (length "abc")
finally (return c) do (loop for j from 0 to (length "abc") by k
do (loop for i from j to (length "abc") do (push (subseq "abc" j i) c)))))
Debugging
if I replace k with a particular number, it works
What happens if you replace k with 0?
It would be much more helpful if you formatted this code with typical conventions, and probably if you isolated the particular part of the code that's problematic. That is, (remove-duplicates …) isn't the problem here, you could have removed it. With some more conventional formatting, and some comments, your code is:
(remove-duplicates
(let ((c nil))
(loop for k from 0 to (length "abc") ; k starts at 0
finally (return c)
do (loop for j from 0 to (length "abc") by k ; looping for j from 0 to something by k
do (loop for i from j to (length "abc")
do (push (subseq "abc" j i) c)))))
:test 'equal)
What's going to happen if you try to loop for j from 0 to anything by k? You're pretty much saying, "start with j at 0, then increment it by 0 for the next iteration…" so j never gets anywhere. This really could have been caught with a print or format. I know that's not the same as using a debugger, but sometimes the simplest ways are the quickest:
[8]> (remove-duplicates
(let ((c nil))
(loop for k from 0 to (length "abc")
finally (return c)
do (loop for j from 0 to (length "abc") by k
do
(format t "~&k: ~a, j: ~a" k j )
(loop for i from j to (length "abc")
do (push (subseq "abc" j i) c)))))
:test 'equal)
k: 0, j: 0
k: 0, j: 0
k: 0, j: 0
…
Collecting subsequences
If you're trying to collect the subsequences of a given sequence, you might do it like this. This works on both strings (vectors) and lists (although it's less efficient for lists).
(defun subsequences (sequence)
(loop
with length = (length sequence)
for i from 0 to length
nconcing (loop
for j from (1+ i) to length
collecting (subseq sequence i j))))
(subsequences "abc")
;=> ("a" "ab" "abc" "b" "c")
(subsequences '(1 2 3))
;=> ((1) (1 2) (1 2 3) (2) (2 3) (3))
Appendex: A hard-to-understand error from SBCL
Interestingly, you'll get a runtime error with SBCL, although the error message doesn't make it particularly clear why. Perhaps it's related to the infinite looping.
* (remove-duplicates
(let ((c nil))
(loop for k from 0 to (length "abc")
finally (return c)
do (loop for j from 0 to (length "abc") by k
do
(loop for i from j to (length "abc")
do (push (subseq "abc" j i) c)))))
:test 'equal)
debugger invoked on a TYPE-ERROR in thread #<THREAD "initial thread" RUNNING
{1002978E71}>:
The value 0
is not of type
(OR (SINGLE-FLOAT (0.0)) (DOUBLE-FLOAT (0.0d0)) (RATIONAL (0))).
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
What do you think BY 0 should do in a loop?
(loop for i from 0 upto 10 by 0 do (princ '*))
If you are not advancing the variable, you'll get an endless loop.
Related
I want to change the code below to Lisp code, but I keep getting errors in grammar. How do I fix the if statement?
int promising(int i)
{
int k = 1;
while (k < i)
{
if (col[i] == col[k] || abs(col[i] - col[k]) == abs(i - k))
return 0;
k++;
}
return 1;
}
Below is the one I changed to the Lisp code.
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
It is difficult for me to flexibly change the complicated condition of the if statement to the lisp code.
You are doing "C-in-Lisp". Trying to directly translate C (or for that matter, C++/Java/C#/Python ...) programs into Lisp will often lead to poor code, and you should be better off trying to understand how those problems are sovled in Lisp.
That being said:
You should not use (setq col <whatever>) at the toplevel. Global variables are introduced using defvar or defparameter and their name is of the form *variable-name* to distinguish them from other variables. This is because they have different scoping rules, and behave differently (i.e. they are not equivalent to other languages' global variables). In particular, using setq with a variable that has not been declared with defvar or defparameter is undefined behaviour, and most implementations will allow it, but they will then create this global variable. You generally don't want that. To sum up: either use (defvar *col* (list 0 0 ...)) if you need this really is a global variable, or simply use (let ((col (list 0 ...))) <more-code>) where you need it.
loop is a complicated construct. This is, in itself, another mini-language that you have to learn on top of Lisp. In particular, if all you ever want to do is "loop with some variable between some bounds and increment it by some value at each step", use
(loop for k from 1 do ...) ;; this introduces a local variable k, incremented by 1 at each step, with no upper bound
(loop for k from 1 to 10 do ...) ;; same, but only loop until k reaches 10
(loop for k from 1 to 10 by 3 do ...) same, but increments k by 3 at each step
Other constructs are available. Read this section of Practical Common Lisp for a good introduction, and the relevant CLHS section for a technical description and documentation.
Please follow conventions for whitespace this makes it much easier to read. For example, never place a parenthesis alone on its line (e.g. your very last parenthesis), and ( abs((setq b (- i k )))) should really be written (abs ((setq b (- i k)))) (ignoring the fact that this is incorrect, see below ...). As far as style is concerned, you also need to fix the indentation, and don't write DEFUN is uppercase, it is unnecessary and looks weird.
You cannot place extra parenthensis just to group things together, parenthesis have semantic meaning. In particular, in most cases, calling a function or using pretty much any special operator is done by (<operator-name> <first-arg> <second-arg> ... ). You almost never have 2 consecutive opening parenthesis.
Why are you using (setq a ...) and (setq b ...) in your loop ? Neither a nor b is ever declared or used anywhere else.
If you want to access specific elements of a list, don't use a list, use a vector. In particular, several calls to the nth function is often the sign that you really should have been using a vector.
A correct version of your code, using a few loop facilities, and still assuming that col is a list (which is should not be) although there would be other loop constructs making this even clearer ...
(defun promising (i)
(loop for k from 1 below i
for col-k = (nth k col)
do (when (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k))))
(return-from promising 0)))
1)
Note that this code is incredibly inefficient and this is why I suggested not to translate directly from C to Lisp. In particular, although you traverse a list (you access the k-th element at the k-th step), your code calls nth at each step instead of traversing the list ! You also compute (nth i col) at each step, which is already useless in C (it is constant so doesn't need to be recomputed at every step), but is catastrophic here. This should really be:
(defun promising (i)
(let ((col-i (nth i col)))
(loop for k from 1 below i
for col-k in (cdr col) ;; you start from the index 1, not 0
do (when (or (= col-i col-k)
(= (abs (- col-i col-k))
(abs (- i k))))
(return-from promising 0))))
1)
There are several mistakes in the code.
Incorrect function calls
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; Incorrect
)
And also here:
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))
;; ^^
;; Incorrect
( abs((setq b (- i k ))))))
;; ^^
;; Incorrect
(return-from promising 0)))
do (setq k (1+ k)))
(return-from promising 1))
)
The loop macro have 2 do keywords
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
;; ^^
;; First do
(= ( abs((setq a (- (nth i col) (nth k col)))))
( abs((setq b (- i k ))))))
(return-from promising 0)))
do (setq k (1+ k)))
;; ^^
;; Second do
(return-from promising 1))
)
return-from is used several times
return-from is usually not present in Common Lisp code, this is pretty much like C goto, something developers try to avoid.
Incoherent setq defining a and b (probably old code)
(setq col (list 0 0 0 0))
(DEFUN promising (i)
(let ((k 1)) ; k =1
(loop while (< k i)
do((if (or ( = (nth i col) (nth k col))
(= ( abs((setq a (- (nth i col) (nth k col)))))\
;; ^^^^^^
;; ??
( abs((setq b (- i k ))))))
;; ^^^^^^
;; ??
Weird incrementation scheme
(setq k (1+ k))
While being correct, Common Lisp programmers will simply use the increment function:
(incf k)
Final code
The code you might looking for should be close to that one:
(defun promising (i)
(let ((k 1))
(loop while (< k i) do
(if (or (= (nth i col) (nth k col))
(= (abs (- (nth i col) (nth k col)))
(abs (- i k ))))
(return-from promising 0))
(incf k))
;; return value
k))
Please note that the code is not equivalent to the C version, because the data structure is completely different. In the C version, the access to the data will be very fast O(1). The Common Lisp version will be slow if you have a large number of elements O(n). You can be fast with Common Lisp if you replace your list by an array/vector.
I have started to learn Common Lisp a few days ago reading the book from Peter Seibel. I have downloaded the lispbox-0.7 for Windows and tried out some of the concepts in the SLIME REPL.
Now I'm at chapter 7. Macros and Standard Control Structures / Loops and I found this intressting do expression for the 11th Fibonacci number
(do ((n 0 (1+ n))
(cur 0 next)
(next 1 (+ cur next)))
((= 10 n) cur))
I defined following function
(defun fib (n) (do ((i 1 (1+ i)) (cur 0 next) (next 1 (+ cur next))) ((= n i) cur)))
The function does what I expected and returns the nth Fibonacci number. Now for curiosity i tried summing the first 10 fibonacci numbers using a dotimes loop
(let ((sum 0)) (dotimes (k 10) (setf sum (+ sum (fib k)))) sum)
But this expression runs indefinitly and i don't understand why. Maybe here is another concept I don't know. I tried a simpler example like
(dotimes (k 10) (fib k))
which should return NIL. But this also runs indefinitly. Can someone explain to me what I am missing?
Thx
Ok, nevermind, was not carefull enougth. the code tries to evaluate fib 0, but the test condition in do cannot be fulfilled. Thats why it runs indefinitly
fixing it by (fib (+ k 1))
It is just really hard to understand from a standard description, so:
For instance, I'm trying to set a k-th position of some list (ls) to a specific value. Even have a function of my own, that gives acces to k-th elt.
(defun kth-elt (lst k)
(cond ((> 0 k) nil)
((equal 0 k) (car lst))
((< 0 k) (kth-elt (cdr lst) (- k 1))))).
Also made a function, that updates that value.
(defun kth-upd (lst k new)
(cond ((> 0 k) nil)
((equal 0 k) (setf (car lst) new))
((< 0 k) (kth-upd (cdr lst) (- k 1) new))))
Now i can actually use that, but i wanna understand the difference between it and DEFSETF. Also I still do not understand. how to "teach" defsetf to use these. Thx for help.
Based on your definitions, it is simply:
(defsetf kth-elt kth-upd)
Instead of using kth-upd, you can now use kth-elt and (setf kth-elt).
For example:
(let ((list (copy-list '(a b c d e f))))
(setf (kth-elt list 3) nil)
list)
=> (A B C NIL E F)
But the real benefits of using SETF consistently is that you can combine this setter with other ones. Just consider incrementing a value:
(let ((list (make-list 10 :initial-element 0)))
(incf (kth-elt list 3))
(incf (kth-elt list 5) 20)
list)
=> (0 0 0 1 0 20 0 0 0 0)
See also this answer from Rainer Joswig for more background on places and SETF.
Setf expander
Note that you are doing the list traversal twice: you first get the current value, then computes the new one; only then, you store the new value, starting from the beginning of the list:
0: (KTH-ELT (0 0 0 0 0 0 0 0 0 0) 3)
1: (KTH-ELT (0 0 0 0 0 0 0 0 0) 2)
2: (KTH-ELT (0 0 0 0 0 0 0 0) 1)
3: (KTH-ELT (0 0 0 0 0 0 0) 0)
3: KTH-ELT returned 0
2: KTH-ELT returned 0
1: KTH-ELT returned 0
0: KTH-ELT returned 0
0: (KTH-UPD (0 0 0 0 0 0 0 0 0 0) 3 1)
1: (KTH-UPD (0 0 0 0 0 0 0 0 0) 2 1)
2: (KTH-UPD (0 0 0 0 0 0 0 0) 1 1)
3: (KTH-UPD (0 0 0 0 0 0 0) 0 1)
3: KTH-UPD returned 1
2: KTH-UPD returned 1
1: KTH-UPD returned 1
0: KTH-UPD returned 1
This can also be seen by macroexpansion:
(incf (kth-elt list 3))
... is macroexpanded as:
(LET* ((#:LIST796 LIST) (#:NEW1 (+ 1 (KTH-ELT #:LIST796 3))))
(KTH-UPD #:LIST796 3 #:NEW1))
Another possible approach might be to use DEFINE-SETF-EXPANDER:
(define-setf-expander kth (list index)
(alexandria:with-gensyms (store cell)
(values `(,cell)
`((nthcdr ,index ,list))
`(,store)
`(setf (car ,cell) ,store)
`(car ,cell))))
The function returns 5 different code parts that can be assembled to access and modify a place. cell and store are local variables introduced using GENSYM.
The variable cell (i.e. the variable named after the fresh symbol bound to cell) will be bound to (nthcdr index list). store contains the value to set in the place. Here, it will be put at the appropriate place by using (setf (car cell) store). Also, the existing value in the place is (car cell). As you can see, we need to manipulate, under the hood, the cons cell we mutate (of course, an error is raised with empty lists).
The macroexpansion for (incf (kth list 3)) is:
(LET* ((#:CELL798 (NTHCDR 3 LIST)) (#:STORE797 (+ 1 (CAR #:CELL798))))
(SETF (CAR #:CELL798) #:STORE797))
The setter function knows how to access the place that holds the value we want to change, and can change it directly, which is more efficent than just a pair of reader/writer functions.
Remark about mutability
SETF is designed around mutable data. If you write an accessor for a key/value store on the network, so that (remote host key) will connect and retrieve a value, and (setf (remote host key) value) sends the new value back, then it is not guaranteed that the remote value is always updated when (remote host key) is used as an intermediate place.
For example, if the value is a list, (push val (remote host key)) will push on the local list created on your host, there is no obligation for setf to actually ensure the result is sent back to the network when it is part of a larger expression. That allows SETF to be efficient by mutating places, at the small cost of requiring you to be more explicit. In the preceding example, you have to write (setf (remote host key) new-list) directly (not as a nested place) to effectively send the new data back.
As an addendum to coredump's answer, it's worth noting that the following works, and is, in my opinion, much better than using defsetf:
(defun kth-elt (lst k)
(cond ((> 0 k) nil)
((= 0 k) (car lst))
((< 0 k) (kth-elt (cdr lst) (- k 1)))))
(defun (setf kth-elt) (new lst k)
(cond ((> 0 k) nil)
((= 0 k) (setf (car lst) new))
((< 0 k) (setf (kth-elt (cdr lst) (- k 1)) new))))
There are cases when you need defsetf but they are not that common.
(kth-elt itself is just a special-case of elt of course: in real life you don't need to write any of this.)
I have a list of lists and want to test if all elements are different from each other, i.e. equal should return nil for all combinations of list elements.
E.g.
(defparameter feld '((1 0 0 5 5 0)
(0 0 0 0 0 0)
(1 1 5 5 0 0)
(0 1 0 1 5 5)
(5 5 1 0 1 0)
(1 0 1 0 5 5)))
I thought of using reduce but as far as I understand it only tests the equality of neighbors, as would do a loop construct like:
(loop for i below (length feld)
for j from 1
if (equal (nth i feld) (nth j feld)) return t)
Is there a simple way using a standard construct which I do not see at the moment or do I have to create a recursive function?
The whole data structure represents a "board game" where every list is a line on the board and each element in the inside-lists is a value of this very field. The three numerical values (0, 1 and 5) are something like empty, Symbol A and Symbol B. A valid board cannot have two identical lines. This is why I want to identify those.
Basically, it is like remove-duplicates without removing. In the meantime I was thinking about something like this:
(defun duplicates-p (lst)
(cond ((null lst) '())
((member (car lst) (cdr lst)) t)
(t (duplicates-p (rest lst)))))
Something like this:
(defun unique (lsts &aux (h (make-hash-table :test 'equal)))
(loop :for lst :in lsts
:never (gethash lst h)
:do (setf (gethash lst h) t)))
I'm attempting to create a function that creates copies of whatever list the user puts in by the desired number of copies.
User: (copy '(A) '(7))
Output: (A A A A A A A)
(defun copy (x y)
(cond ((-1 counter)
nil)
(T
(list (cons (car x) (cdr x)))
copy
(cdr x)))
I'm attempting to set up a counter and just create a new list into the current list by decrementing the counter. So far the counter is pseudo-code.
This is the counter I'm trying to figure out.
(defun count (y)
(let ((a y))
(- a 1)))
The error I get is that whatever I put into y isn't a number.
While I can understand why the first parameter is a list, the second must be a number. A very simple implementation might look like:
(defun copy (lst count)
(when (> count 0)
(append (copy-list lst) (copy lst (1- count)))))
Testing:
CL-USER> (copy '(A) 7)
(A A A A A A A)
CL-USER> (copy '(A B C) 7)
(A B C A B C A B C A B C A B C A B C A B C)
The usual caveats concerning the use of append and object copying apply.
I'd suggest passing your list as a &rest argument instead and use loop:
(defun repeat (n &rest items)
(loop repeat n append items))
Test
CL-USER> (repeat 10 0 1 2)
(0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2)