From: Erick Lopez Carreon
Subject: Ansi common lisp chapter 3 excercise 3 question
Date: 
Message-ID: <1146179814.833508.48030@g10g2000cwb.googlegroups.com>
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
From: Erick Lopez Carreon
Subject: Re: Ansi common lisp chapter 3 excercise 3 question
Date: 
Message-ID: <1146254399.847533.310150@i40g2000cwc.googlegroups.com>
Thank you Bill

Your solution compared with mine is a motivating example of what I want
to learn, thank you very much.


I return to study.