Quicksort in LISP - lisp

I am trying to do a quicksort using LISP but I am having trouble with my functions output.
(defun qsort (L)
(cond
((null L) nil)
(t(append
(qsort (list< (car L) (cdr L)))
(cons (car L) nil)
(qsort (list>= (car L) (cdr L)))))))
(defun list< (a b)
(cond
(( or(null a)(null b) nil))
(( < a (car b)) (list< a (cdr b)))
(t(cons (car b) (list< a (cdr b))))))
(defun list>= (a b)
(cond
(( or( null a)(null b) nil))
(( >= a (car b)) (list> a (cdr b)))
(t(cons (car b) (list> a (cdr b))))))
My problem being when list< and list>= finish the list always ends with a .T. For instance:
> (list< '4 '(1 5 3 8 2))
Entering: LIST<, Argument list: (4 (1 5 3 8 2))
Entering: LIST<, Argument list: (4 (5 3 8 2))
Entering: LIST<, Argument list: (4 (3 8 2))
Entering: LIST<, Argument list: (4 (8 2))
Entering: LIST<, Argument list: (4 (2))
Entering: LIST<, Argument list: (4 NIL)
Exiting: LIST<, Value: T
Exiting: LIST<, Value: (2 . T)
Exiting: LIST<, Value: (2 . T)
Exiting: LIST<, Value: (3 2 . T)
Exiting: LIST<, Value: (3 2 . T)
Exiting: LIST<, Value: (1 3 2 . T)
(1 3 2 . T)
Why is (4 NIL) evaluating as T?

Your problem with list<, and also with list>=, lies on ((or ( null a)(null b) nil)), it should be (( or( null a)(null b)) nil). Note nil was moved outside of the condition to be the returned value.
Furthermore, on the definition of list>= you are calling list>, but I'm positive you meant list>= instead.
I would also suggest some indentation to address the legibility of lisp, like follows
(defun qsort (L)
(cond
((null L) nil)
(t
(append
(qsort (list< (car L) (cdr L)))
(cons (car L) nil)
(qsort (list>= (car L) (cdr L)))))))
(defun list< (a b)
(cond
((or (null a) (null b)) nil)
((< a (car b)) (list< a (cdr b)))
(t (cons (car b) (list< a (cdr b))))))
(defun list>= (a b)
(cond
((or (null a) (null b)) nil)
((>= a (car b)) (list>= a (cdr b)))
(t (cons (car b) (list>= a (cdr b))))))
Some testing follows:
(list< '4 '(1 5 3 8 2))
=> (1 3 2)
(list>= '4 '(1 5 3 8 2))
=> (5 8)
(qsort '(1 5 3 8 2))
=> (1 2 3 5 8)

Lisp has different kinds of collections. I think sort a list using quick-sort is not a good choice. In the implementation of STL in C++, the sorting method of list is merge-sort. I have tried to implement a 3-way quick-sort using the collections of array.
(defun quick-sort (arr start end)
"Quick sort body"
(if (< start end)
(let ((n-pair (partition arr start end)))
(quick-sort arr start (car n-pair))
(quick-sort arr (cdr n-pair) end))
))
(defun partition (arr start end)
"Partition according to pivot."
(let ((pivot (aref arr start)) (cur start))
(loop while (<= start end) do
(cond
((< pivot (aref arr start)) ; pivot < arr[start], swap with arr[end]
(swap arr start end) (decf end))
((> pivot (aref arr start)) ; pivot > arr[start], swap with arr[start]
(swap arr cur start) (incf cur) (incf start))
(t ; otherwise
(incf start))))
(cons (decf cur) start)))
(defun swap (arr i j)
"Swap element of arr"
(let ((tmp (aref arr i)))
(setf (aref arr i) (aref arr j))
(setf (aref arr j) tmp)))

(defun quick (list)
(when (< = (length list) 1) (return-from quick list))
(let ((pivot (car list)) (rest (cdr list)) (less nil) (greater nil))
(loop for i in rest do
(if (< i pivot) (push i less) (push i greater)))
(append (quick less) (list pivot) (quick greater))))

I'd recommend to change the code of liya babu/Will Ness like this:
(defun quick (list)
(if (null list) nil
(let ((pivot (first list)) (less nil) (greater nil))
(dolist (i (rest list))
(if (< i pivot) (push i less) (push i greater)))
(append (quick less) (list pivot) (quick greater)))))
Although just slightly edited I find it both more lispy and more succinct.

There are some errors in the program. The corrected program is:
(defun qsort (L)
(cond
((null L) nil)
(t (append
(qsort (list< (car L) (cdr L)))
(cons (car L) nil)
(qsort (list>= (car L) (cdr L)))))))
(defun list< (a b)
(cond
(( or (null a) (null b)) nil)
(( < a (car b)) (list< a (cdr b)))
(t (cons (car b) (list< a (cdr b))))))
(defun list>= (a b)
(cond
(( or ( null a)(null b)) nil)
(( >= a (car b)) (list>= a (cdr b)))
(t (cons (car b) (list>= a (cdr b))))))

This should also work:
(defun qsort (l)
(cond
((null l) nil)
(t (append
(qsort (car(list<> (car l)(cdr l))))
(cons (car l) nil)
(qsort (cadr(list<> (car l)(cdr l))))))))
(defun list<> (a b &optional rl rr)
(cond
((null b) (list rl rr))
((<=(car b)a) (list<> a (cdr b) (cons (car b) rl) rr))
(t (list<> a (cdr b)rl (cons (car b) rr)))))
(setq l (loop for j from 1 to 20 append (list(random 100))))
(qsort l)
;=> (86 99 9 31 66 58 57 43 48 21 51 0 32 69 39 47 59 76 69 23)
;=> (0 9 21 23 31 32 39 43 47 48 51 57 58 59 66 69 69 76 86 99)

Related

Issue with extra nils in quicksort result

I'm new to lisp, and am writing code for quicksort. I am almost done, although the output is giving me some trouble. This is currently what I have:
(defun fil(P L)
(if (null L) nil
(if (funcall P (first L)) (cons (first L) (fil P (rest L)))
(fil P (rest L)))))
(defun qs(L)
(if (null L) nil
(let ((x (first L))
(gt (fil (lambda (x) (<= (first L) x))(rest L) ))
(lt (fil (lambda (x) (> (first L) x))(rest L))))
(cons (cons (qs lt) (first L)) (qs gt)))))
(write (qs '(4 2 3 1 7 3 5 3 6)))
This works, but the output looks like this:
((((((NIL . 1)) . 2) (NIL . 3) (NIL . 3) (NIL . 3)) . 4)
(((NIL . 5) (NIL . 6)) . 7))
I am not sure where the extra nils and periods and parentheses are coming from or how to fix it. Any advice is appreciated.
Look at
(cons '(a b c d) 'e)
Above code does not append E to the list.
CL-USER 4 > (cons '(a b c d) 'e)
((A B C D) . E)
It creates a new cons cell (a two element container) with the first arg and the second arg with its elements.
What you need, is to APPEND lists into a result list.
Adding to what #RainerJoswig said:
(defun %filter (pred l)
(cond ((null l) nil)
((funcall pred (car l)) (cons (car l) (%filter pred (cdr l))))
(t (%filter pred (cdr l)))))
(defun quicksort (l)
(cond ((null l) nil)
(t (let ((greater-than (%filter (lambda (x) (<= (car l) x)) (cdr l)))
(less-than (%filter (lambda (x) (> (car l) x)) (cdr l))))
(append (quicksort less-than) (list (car l)) (quicksort greater-than))))))
(quicksort '(4 2 3 1 7 3 5 3 6))
;; (1 2 3 3 3 4 5 6 7)
Alternatively also:
(defun %filter (pred l)
(mapcan (lambda (x) (if (funcall pred x) (list x) nil)) l))
(defun quicksort (l)
(cond ((null l) nil)
(t (append (quicksort (%filter (lambda (x) (< x (car l))) (cdr l)))
(list (car l))
(quicksort (%filter (lambda (x) (<= (car l) x)) (cdr l)))))))

simplifying a simple boolean expression using lisp

i have a simple boolean expression presented as a lisp list like this :
'(OR 0 (AND A1 A2))
the previous list is the presentation of ((A1 AND A2)OR 0).
anyway , i am writing a function to simplify this expression ..
for example :
calling the function "reduce" like this :
(reduce '(OR 0 (AND A1 A2)))
would yield
(AND A1 A2)
i firstly tried to create base rules , so i defined
the following identities:
(AND 1 S) == S,
(OR 0 S ) == S,
(AND 0 S) == 0,
( OR 1 S) == 1,
(NOT O) == 1,
(NOT 1) == 0.*
i was thinking of defining 6 functions , one for each rule , and then
call them one by one in a wrapper , i am new to lisp so i don't have a clue to implement that , i made it in java once , but i dont know how to handle such problem using the syntax of lisp so please help me ..
Given the complexity of your solution, here's my implementation that's a lot shorter and more readable:
(defun reduc (exp)
(if (atom exp)
exp
(flet ((helper (op args n) ; and and or is nearly the same code so we factor it out
(let ((newargs (remove n args)) (cn (- 1 n)))
(cond
((null newargs) n)
((some (lambda (e) (eql cn e)) newargs) cn)
((null (cdr newargs)) (car newargs))
((cons op newargs))))))
(let ((op (car exp)) (args (mapcar #'reduc (cdr exp))))
(ecase op
((not) (if (= 1 (length args))
(let ((arg1 (car args)))
(if (and (numberp arg1) (<= 0 arg1 1)) (- 1 arg1) exp))
(error "'not' must have exactly one parameter")))
((and) (helper op args 1))
((or) (helper op args 0)))))))
Testing:
? (reduc '(OR 0 (AND A1 A2)))
(AND A1 A2)
? (reduc '(OR 0 (AND A1 1 A2)))
(AND A1 A2)
? (reduc '(or ERROR (not 0)))
1
? (reduc '(AND ERROR (not 0)))
ERROR
? (reduc '(OR 0 (AND A1 0)))
0
? (reduc '(OR 0 (AND A1 1)))
A1
i finally came up with this solution .
(defun simplify (EXPR)
(simplify-expr NIL EXPR))
(defun simplify-expr (EXPR1 EXPR2)
(cond
((or (atom EXPR2) (equal EXPR1 EXPR2)) EXPR2)
(T (simplify-expr EXPR2 (simplify-boolean-expr EXPR2)))))
(defun simplify-boolean-expr (EXPR)
(cond
((and (equal (first EXPR) `and) (>= (length EXPR) 3))
(simplify-and-expr (rest EXPR)))
((and (equal (first EXPR) `or) (>= (length EXPR) 3))
(simplify-or-expr (rest EXPR)))
((and (equal (first EXPR) `not) (= (length EXPR) 2))
(simplify-not-expr (rest EXPR)))
(T
(error "~S is not a valid circuit descriptor expression or has an unknown operator." EXPR))))
(defun simplify-and-expr (EXPR)
(let ((SIMPLIFIED_EXPR (remove `T (remove-duplicates EXPR))))
(cond
((null SIMPLIFIED_EXPR) `T)
((member `NIL SIMPLIFIED_EXPR) `NIL)
((null (second SIMPLIFIED_EXPR)) (first SIMPLIFIED_EXPR))
(T (cons `and (simplify-operand SIMPLIFIED_EXPR))))))
(defun simplify-or-expr (EXPR)
(let ((SIMPLIFIED_EXPR (remove `NIL (remove-duplicates EXPR))))
(cond
((null SIMPLIFIED_EXPR) `NIL)
((member `T SIMPLIFIED_EXPR) `T)
((null (second SIMPLIFIED_EXPR)) (first SIMPLIFIED_EXPR))
(T (cons `or (simplify-operand SIMPLIFIED_EXPR))))))
(defun simplify-not-expr (EXPR)
(cond
((equal (first EXPR) `NIL) `T)
((equal (first EXPR) `T) `NIL)
((and (listp (first EXPR)) (equal (first (first EXPR)) `not))
(first (rest (first EXPR))))
(T (cons `not (simplify-operand EXPR)))))
(defun simplify-operand (OPERAND_LIST)
(cond
((null OPERAND_LIST) NIL)
((atom (first OPERAND_LIST))
(cons (first OPERAND_LIST) (simplify-operand (rest OPERAND_LIST))))
(T
(cons (simplify-expr NIL (first OPERAND_LIST)) (simplify-operand (rest OPERAND_LIST))))))
it takes (nil , T) for (0 , 1) and reduces any boolean expression , i tried it and it works fine .

CLisp error: "(x) is not number"

This is my function that's supposed to implement infix evaluation for * and + operations.
(defun calculate(l)
(cond
((eql (cadr l) '+) (+ (car l) (cddr l)))
((eql (cadr l) '*) (- (car l) (cddr l)))
)
)
When I run this with the list '(3 + 4) it gives me an error saying "(4) is not a number". Any ideas what the problem might be?
Symbols can be called as functions. Thus your code is just this:
(defun calculate (l)
(funcall (second l) (first l) (third l)))
or
(defun calculate (l)
(destructuring-bind (arg1 op arg2)
l
(funcall op arg1 arg2)))
Example:
CL-USER 77 > (calculate '(20 + 30))
50
The part with (cddr l) should be (caddr l). You have to access the first element of the list, not the list. The code should be then:
(defun calculate(l)
(cond
((eql (cadr l) '+) (+ (car l) (caddr l)))
((eql (cadr l) '*) (- (car l) (caddr l)))
)
)

Reverse a list with dolist in LISP

I try to reverse a list, i can't use the function "nreverse"
I try :
(defun dolist-reverse (l)
(let ((new-list (make-list (length l))))
(dolist (x l new-list)
(setf new-list (cons x new-list)))))
But the result is :
CL-USER> (dolist-reverse '(1 2 3))
(3 2 1 NIL NIL NIL)
How can i do ? (i need to use dolist)
EDIT :
Finally fix my problem :
(defun dolist-reverse (l)
(let ((new-list))
(dolist (x l new-list)
(setf new-list (cons x new-list)))))
CL-USER 11 > (defun dolist-reverse (list &aux (reverse-list nil))
(dolist (element list reverse-list)
(push element reverse-list)))
DOLIST-REVERSE
CL-USER 12 > (dolist-reverse '(1 2 3))
(3 2 1)
This one makes same thing, without changing argument to the procedure;
(defun my-reverse (l)
(if (null l) nil
(append
(my-reverse (cdr l))
(list (car l)))))

Setting up a equal function in common lisp using only "eq"

I've given the assingment to write a function in common lisp to compare two lists to see if they are equal and I have been bared from using the "equal" predicate I can only use "eq" and I seem to come to a wall. I get this error with my code EVAL: variable SETF has no value
The following restarts are available:
and he code:
(defun check(L1 L2)
(cond
((eq L nil) nil)
(setq x (first L1))
(setq y (first L2))
(setf L1 (rest L1))
(setf L2 (rest L2))
(if (eq x y) (check L1 L2))))
(defun b(L1 L2)
(cond
((eq L1 nil) nil)
(setf x (first L1))
(setf y (first L2))
(setf L1 (rest L1))
(setf L2 (rest L2))
(if (and (list x) (list y)
(check(x y))
(if (eq x y) (b(L1 L2))))))
I guess this is what you are looking for:
(defun compare-lists (list1 list2)
(if (and (not (null list1))
(not (null list2)))
(let ((a (car list1)) (b (car list2)))
(cond ((and (listp a) (listp b))
(and (compare-lists a b)
(compare-lists (cdr list1) (cdr list2))))
(t
(and (eq a b)
(compare-lists (cdr list1) (cdr list2))))))
(= (length list1) (length list2))))
Tests:
? (compare-lists '(1 2 3) '(1 2 3))
T
? (compare-lists '(1 2 3) '(1 2 3 4))
NIL
? (compare-lists '(1 2 3) '(1 2 (3)))
NIL
? (compare-lists '(1 2 (3)) '(1 2 (3)))
T
? (compare-lists '(1 2 (a b c r)) '(1 2 (a b c (r))))
NIL
? (compare-lists '(1 2 (a b c (r))) '(1 2 (a b c (r))))
T