Hello:
I get the following solution for Ansi common lisp chapter 3 excercise 3
------------------------------------------------------------------
;;3.- Returns sorted ocurrences
(defun ocurrences (list)
(let ((listx '()) (unicos '()))
(setf unicos (uniques list))
(setf listx (mapcar #'(lambda (x) (counts x 0 list))
unicos))
; (setf listx(cons listx ())) ; try to correct te weird result
without sucess
(sort listx #'> :key #'cdr)
; (setf listx (reverse listx)) ; if i use #'< in line before i need
to reverse but still wrong result
listx))
(defun uniques (list)
(if (atom list)
nil
(let ((uniq '()))
(dolist (elt list)
(pushnew elt uniq))
(setf uniq(reverse uniq))
uniq)))
(defun counts (elt n lst)
(if (null lst)
(cons elt n)
(let ((next (car lst)))
(if (eql next elt)
(counts elt (+ n 1) (cdr lst))
(counts elt n (cdr lst))))))
------------------------------------------------------------------
But if i try:
(ocurrences '(x j x j a j b b b b z g g g g g g a t t y) )
I get:
((X . 2) (A . 2) (T . 2) (Z . 1) (Y . 1))
I'am lossing some elements
If i comment out the sort line i get:
CL-USER> (ocurrences '(x j x j a j b b b b z g g g g g g a t t y) )
((X . 2) (J . 3) (A . 2) (B . 4) (Z . 1) (G . 6) (T . 2) (Y . 1))
This is all the elements
Seems to me that sort is cutting off some elements, but i don't know
why.
Any clues apreciated.
BTW ;) any suggestions to improve this noob attemp of code?
Thanks in advance
From: Bill Atkins
Subject: Re: Ansi common lisp chapter 3 excercise 3 question
Date:
Message-ID: <871wvimvdp.fsf@rpi.edu>
"Erick Lopez Carreon" <·····@fsl.org.mx> writes:
> Hello:
>
> I get the following solution for Ansi common lisp chapter 3 excercise 3
>
>
> ------------------------------------------------------------------
> ;;3.- Returns sorted ocurrences
>
> (defun ocurrences (list)
> (let ((listx '()) (unicos '()))
> (setf unicos (uniques list))
> (setf listx (mapcar #'(lambda (x) (counts x 0 list))
> unicos))
> ; (setf listx(cons listx ())) ; try to correct te weird result
> without sucess
> (sort listx #'> :key #'cdr)
> ; (setf listx (reverse listx)) ; if i use #'< in line before i need
> to reverse but still wrong result
> listx))
>
>
> (defun uniques (list)
> (if (atom list)
> nil
> (let ((uniq '()))
> (dolist (elt list)
> (pushnew elt uniq))
> (setf uniq(reverse uniq))
> uniq)))
>
>
> (defun counts (elt n lst)
> (if (null lst)
> (cons elt n)
> (let ((next (car lst)))
> (if (eql next elt)
> (counts elt (+ n 1) (cdr lst))
> (counts elt n (cdr lst))))))
>
> ------------------------------------------------------------------
>
> But if i try:
>
> (ocurrences '(x j x j a j b b b b z g g g g g g a t t y) )
> I get:
> ((X . 2) (A . 2) (T . 2) (Z . 1) (Y . 1))
>
> I'am lossing some elements
>
> If i comment out the sort line i get:
>
> CL-USER> (ocurrences '(x j x j a j b b b b z g g g g g g a t t y) )
> ((X . 2) (J . 3) (A . 2) (B . 4) (Z . 1) (G . 6) (T . 2) (Y . 1))
>
> This is all the elements
>
> Seems to me that sort is cutting off some elements, but i don't know
> why.
>
> Any clues apreciated.
>
> BTW ;) any suggestions to improve this noob attemp of code?
>
> Thanks in advance
>
You need to somehow save the return value of SORT. SORT is a
destructive function, so (for efficiency reasons) it will rearrange
its argument as it sees fit. After the sort, your original variable,
LISTX, could point somewhere in the middle of the sorted result.
The fix is simple. Instead of (sort listx #'> :key #'cdr), use (setf
listx (sort listx #'> :key #'cdr)). SORT will return the sorted
version of your list, but it is not specified to leave the object you
pass it in a sorted state.
Also, your version goes through the list twice. This is not
necessary:
(defun occurrences (list)
(let (result)
(dolist (x list)
(if (assoc x result)
(incf (cdr (assoc x result)))
(push (cons x 1) result)))
(sort result #'> :key #'cdr)))
is all you need. Also, I think UNIQUES is doing what the standard
function REMOVE-DUPLICATES does, except that REMOVE-DUPLICATES uses a
more efficient algorithm. As a general bit of advice, avoid using
SETF's in a row, as if you were programming C.
Happy lisping.
--
This is a song that took me ten years to live and two years to write.
- Bob Dylan