qsort optimized for brevity

lisp

    Next

  • 1. lexical closure simulation
    Hi, I use a version of lisp that does not support lexical closure. For example, I want to do the following: (defun makeAdder (x) (function (lambda (y) (+ x y)))) (defun test() (setq plus3 (makeAdder 3)) (funcall plus3 5) ) And my lisp interpreter says error: x is undefined. I am not an expert at lisp but I think it is possible to simulate lexical closure with list/structure/macros or something. Does anybody know how to do it? Any suggestions are very appreciated. Thanks
  • 2. intransigent objects of a certain recursive type
    > This paragraph completely throws me. I look at "a set is a > non-repeating list of objects" and I think "but order > doesn't matter, how is will that be handled" and "But what > does 'non-repeating' mean here?" seems to flag that the > issue is about to be addressed. Sorry; perhaps I should fill in that space. Once rec is defined the following definition of a set will typecheck. (define set? {(rec A) --> boolean} [] -> true [[X | Y] | Z] -> (and (set? [X | Y]) (and (not (member? [X | Y] Z)) (set? Z))) [X | Y] -> (and (not (member? X Y)) (set? Y))) (6+) (set? [[1 2 3] [3 2 1]]) false : boolean (7+) (set? [[1 2 3] [3 2 1 4] 5]) true : boolean (8+) (set? [[1 2 3] [3 2 1 4 4] ]) false : boolean > > However the text talks about invoking the test for set > equality on elements of the compared sets as well as the > sets themselves, as though {{1,2},3} = {1,{2,3}}. Well that > is sounding a bit strange, it would for example break von > Neuman ordinals which have Not quite certain here of where the problem is. (10+) (equalset? [[1 2] 3] [1 [2 3]]) false : boolean Mark
  • 3. More questions about exported symbols and general style.
    Well, two questions about exporting symbols, really. Say I want to set up bindings to captured variables (like IT in anaphoric macros) in packages that I'll be using. Do I want to just export IT and friends, or should I walk through the code and replace them with gensyms or something? Also, I've found I've gotten in the habit of naming captured variables like IT names that begin with dollar signs, i.e., $IT, so they stand out a bit. Bad, good or indifferent idea? Cheers, Pillsy
  • 4. Viewing the code of a function
    Hi. I'm a beginner Common Lisp user. I'm using emacs with slime. I'm just wondering if there is a command to view the code of a function that I wrote. Because sometimes I write a function on the REPL and have to modify it later, but it's a hassle to scroll up and find the function that I wrote. Thank you.

qsort optimized for brevity

Postby justinhj » Fri, 23 Dec 2005 02:29:49 GMT

I was talking to a programmer about lisp and he mentioned someone
writing qsort in haskell and python in 5 or 6 lines of code. Well I
found this evidence

 http://www.**--****.com/ 

I thought if any of you are looking for something to do for kicks how
about coming up with a brief version in lisp?

As a starter heres a basic implentation with a couple of optimizations
but no attempt at bevity... 11 lines of main code with 11 lines of
assistance

;;; quick sort on a list

; given a list return three lists
; a list of items less than pivot, a list of items the same and a list
of items
; greater than it...

(defun partition(lst pivot)
  (let ((less nil) (same nil) (grtr nil))
    (loop for item in lst do
          (if (eql item pivot)
              (setf same (cons item same))
            (if (< item pivot)
                (setf less (cons item less))
              (setf grtr (cons item grtr)))))
    (values less same grtr)))

; fast way to answer this question compared to (> (length lst) 1)
; since length must walk the whole list just to find the length

(defun more-than-one-element(lst)
  (not (null (car (cdr lst)))))

(defun qsort(lst)
  (labels ((qsorter (lst pivot)
                    (if (more-than-one-element lst)
                        (multiple-value-bind (less-lst same-lst
greater-lst)
                            (partition lst pivot)
                          (append
                           (qsorter less-lst (car lst))
                           same-lst
                           (qsorter greater-lst (car lst))))
                      lst)))
    (qsorter lst (car lst))))

; helper: generate random number list to sort of length n

(defun get-random-list(n)
  (loop for x from 1 to n collect
        (random 10000)))

; (time (progn (qsort (get-random-list 100000)) nil))


Re: qsort optimized for brevity

Postby justinhj » Fri, 23 Dec 2005 03:44:10 GMT

I guess this partition is shorter, but less efficient.

(defun partition(lst pivot)
  (values (remove-if #'(lambda(n) (>= n pivot)) lst)
           (remove-if #'(lambda(n) (not (eq n pivot))) lst)
           (remove-if #'(lambda(n) (<= n pivot)) lst)))

Is there any built in function than can split a list into different
components based on a function?


Re: qsort optimized for brevity

Postby Frank Buss » Fri, 23 Dec 2005 03:46:39 GMT




your version looks a bit like the C version, but you could write it like
the Haskell version at  http://www.**--****.com/ 

(defun partition (list pivot)
  (loop for item in list
        with less = '() and greater-or-equal = '()
        finally (return (values (nreverse less)
                                (nreverse greater-or-equal)))
        do (if (< item pivot)
               (push item less)
             (push item greater-or-equal))))

(defun qsort (list)
  (when list
    (let ((pivot (first list)))
      (multiple-value-bind (less greater-or-equal)
          (partition (rest list) pivot)
        (append
         (qsort less)
         (list pivot)
         (qsort greater-or-equal))))))

Small tasks are not very short in Lisp, but people, who knows Lisp better
than I, think that the larger the task to solve, the smaller is the Lisp
program, compared to other languages. The reason is because in Lisp the
problem dictates how the language looks like, and you don't have to think
how you have to formulate it in a given restricted language to solve your
problem, like in C. E.g. if you have lots of list comprehensions, you can
implement it with your own embedded language in Lisp (see
 http://www.**--****.com/ ~svenolof/Collect/ ) and then qsort in Lisp can look
as small as the Haskell version.

-- 
Frank Bu?  XXXX@XXXXX.COM 
 http://www.**--****.com/ ,  http://www.**--****.com/ 

Re: qsort optimized for brevity

Postby Greg Buchholz » Fri, 23 Dec 2005 03:48:51 GMT



; Hope this isn't too far off-topic. Here's a transliteration
; of the Haskell version to Scheme.   Has the same problems.
; Compare to...
;   qsort [] = []
;   qsort (x:xs) = qsort less ++ [x] ++ qsort more
;     where less = filter (<x) xs
;           more = filter (>=x) xs

(require (lib "1.ss" "srfi")) ;DrScheme

(define (qsort xss)
  (if (null? xss)
    '()
    (let* ((x  (car xss))
           (xs (cdr xss))
           (lt (lambda (m) (lambda (n) (<  n m))))
           (gt (lambda (m) (lambda (n) (>= n m))))
           (less (filter (lt x) xs))
           (more (filter (gt x) xs)))
        (append (qsort less) (append (list x) (qsort more))))))

(display (qsort (list 5 4 9 2 3 8 7 1 6)))


Re: qsort optimized for brevity

Postby Marco Antoniotti » Fri, 23 Dec 2005 04:01:08 GMT

Using the SETL package

(defun partition (list pivot)
   (values [x in list / (< x pivot)] [x in list / (> x pivot)]))

And without using partition at all

(defun qsort (list)
   (when list
      (append (qsort [x in list / (< x (first list))]) (list (first
list)) (qsort [x in list / (> x (first list))]))))

This beats Python (as if...)

If you do not want to use the SETL package

(defun qsort (list)
   (when list
     (append (qsort (remove-if (lambda (x) (> x (first list))) list)
             (list (first list))
             (qsort (remove-if (lambda (x) (< x (first list))) list))))

Same line count of Haskell.
But then again, why rewrite it when SORT is built in in CL?

Cheers

Re: qsort optimized for brevity

Postby Frank Buss » Fri, 23 Dec 2005 04:10:02 GMT




Nice. Of course, you mean something like this :-)

(defun qsort (list)
  (when list
    (let ((x (first list))
          (xs (rest list)))
      (append (qsort (remove-if (lambda (y) (>= y x)) xs))
              (list x)
              (qsort (remove-if (lambda (y) (< y x)) xs))))))

-- 
Frank Bu?  XXXX@XXXXX.COM 
 http://www.**--****.com/ ,  http://www.**--****.com/ 

Re: qsort optimized for brevity

Postby justinhj » Fri, 23 Dec 2005 04:20:22 GMT




It seems fair to only use standard CL


I had trouble with this. I had to change list to lst to eval it, and
add a bracket at the end.

Once I'd done that it over-flowed (flew?) the stack so I think the exit
condition is not working.

Although if it can be made to work it wins.


For kicks.


Justin


Re: qsort optimized for brevity

Postby Marco Antoniotti » Fri, 23 Dec 2005 04:26:48 GMT

Duh!  Of course. :}


Re: qsort optimized for brevity

Postby rif » Fri, 23 Dec 2005 04:34:18 GMT


CL's sort can be quite inefficient (in the constants --- it's still
O(n log n) in all implementations as far as I know).  Every comparison
is a function call, and there's no way I know of to either inline that
function call or avoid boxing and unboxing its arguments.  In
particular, consider sorting an array of double-floats, in an
implementation like CMUCL that supports unboxed arrays.  I believe
that when I finally wrote a fully optimized, fully specialized qsort,
I got 2-3 orders of magnitude speedup over the built-in.

Cheers,

rif

Re: qsort optimized for brevity

Postby Marco Antoniotti » Fri, 23 Dec 2005 04:34:51 GMT






It is buggy.  Sorry.  Here is a better version

(defun qsort (list &aux (x (first list)) (xs (rest list)))
  (when list
    (append (qsort (remove-if (lambda (y) (>= y x)) xs))
            (list x)
            (qsort (remove-if (lambda (y) (< y x)) xs)))))

This *was* tested :)


Re: qsort optimized for brevity

Postby Marco Antoniotti » Fri, 23 Dec 2005 04:38:04 GMT




Sure, but I would say that this is a case of "first you got it right,
then you got it fast".

The simple REMOVE-IF based QSORT we have been playing around with is
obviously suboptimal when it comes to efficiency. :)

Cheers

Re: qsort optimized for brevity

Postby justinhj » Fri, 23 Dec 2005 04:39:13 GMT






Winner!

Except that's now slower than mine (at least with the testing I did
with the two versions compiled, on a 100,000 element random number
list).

My partition func makes one pass through the list which is where the
speed up probably comes from, wherease this one does two remove-if's


Re: qsort optimized for brevity

Postby Jens Axel Saard » Fri, 23 Dec 2005 05:22:01 GMT





Using CUT from srfi-26 to "curry" we can translate the Haskell
directly into PLT Scheme:

   (require (lib "26.ss" "srfi"))

   (define qsort
     (match-lambda
       [()        '()]
       [(x . xs)  (append
                   (qsort (filter (cut < <> x) xs))
                   (list x)
                   (qsort (filter (cut >= <> x) xs)))]))

   (qsort (list 5 1 2 4 1 3 2 1)) ; => (1 1 1 2 2 3 4 5)

Marcos solution with the SETL package was nice - using
eager comprehensions from srfi-42 a similar solution
is possible:

   (define qsort
     (match-lambda
       [()           '()]
       [(pivot . xs) (append
                       (qsort (list-ec (: x xs) (if (< x pivot)) x))
                       (list pivot)
                       (qsort (list-ec (: x xs) (if (>= x pivot)) x)))]))

   (qsort (list 5 1 2 4 1 3 2 1)) ; => (1 1 1 2 2 3 4 5)


Justin - for another example consider how you would write an in-place 
quick-sort of an array.

-- 
Jens Axel Saard

Re: qsort optimized for brevity

Postby Geoffrey Summerhayes » Fri, 23 Dec 2005 06:08:29 GMT

If it wasn't for google's line length...

(defun qsort(list)
  (when ...
     (let ...
        (append ...))))

(defun qsort(list)
  (when list
    (let ((sorted-partitions
             (mapcar #'qsort
                     (loop for x in (cdr list)
                           if (< x (car list)) collect x into ls
                           else collect x into ge
                           finally return (list ls ge)))))
      (append (car sorted-partitions)
              (list (car list))
              (cadr sorted-partitions)))))

---
Geoff


Re: qsort optimized for brevity

Postby Bruce Hoult » Fri, 23 Dec 2005 06:20:18 GMT

In article < XXXX@XXXXX.COM >,







This is silly, but here's a Dylan version:

module: qsort

define method qsort(l == #()) #() end;
define method qsort(l :: <list>)
  local partition(by) choose(rcurry(by, l.head), l.tail).qsort end;
  concatenate(\<.partition, l.head.list, \>=.partition);
end;

format-out("%=\n", qsort(#(3, 1, 4, 1, 5, 9, 2, 6, 5, 4)));

-- 
Bruce |  41.1670S | \  spoken |          -+-
Hoult | 174.8263E | /\ here.  | ----------O----------

Similar Threads:

1.qsort optimized for brevity

Marco Antoniotti wrote:
> Using the SETL package
>
> (defun partition (list pivot)
>    (values [x in list / (< x pivot)] [x in list / (> x pivot)]))
>
> And without using partition at all
>
> (defun qsort (list)
>    (when list
>       (append (qsort [x in list / (< x (first list))]) (list (first
> list)) (qsort [x in list / (> x (first list))]))))

This is I must honestly say: very cool. I will never deride Common Lisp
for the time coming.

By the way anyone care to comment whether such tricks are doable by
means of Scheme its srfi-1 library (I added comp.lang.scheme to the
header).

Sir Francis Drake

2.Antonym for optimize, sound-bite for de-optimize?

I can look up definitions for optimize and find things like:

1. make optimal; get the most out of; use best; "optimize your resources"
2. modify to achieve maximum efficiency in storage capacity or time or
   cost; "optimize a computer program"

But there appear to be no real antonym for optimize.  In the past it
appears there was no need for a word for the opposite of optimize but
today we have many champions of de-optimimization who have no word
in common use as an antonym for optimize.  The best I could find
were:

blot, blotch, blur, 
cheapen, contaminate, corrupt, corrode, 
damage, debase, deface, denature, deteriorate, devalue, diminish,
expunge, 
harm, hurt,
impair, intermix,
maim, make impure, mangle, mar, 
pervert, phony up, pollute, 
rot, ruin,
spoil, sully, 
taint, tarnish, thin, twist, 
warp, water, water down, weaken, 
vitiate

I suppose some people will define optimize as
achieving maximum efficiency in maximizing costs 
(of products) to maximize profit.  I often hear that
maximizing for efficient use of human time, computer
time, computer memory, and human understanding are
simply counterproductive to maximizing efficiency
for profit.  From that perspective the above list
of optimization antonyms can be seen as just other
forms of optimization, just optimization in a different
dimmension of the problem space.

What is an effective sound-bite to describe the need
for de-optimization?

Best Wishes

Dogbirt Forth:

"In pursuit of our mission to" mission-statement 
"In such a way as to maximize" random-platitude
"and achieve" random-platitude
"The beautiful thing about" mission-statement
"is that it allows us to achive" random-platitude

Insert these phrases recursively along with the rest 
of the Chroning phrases to any statement that expresses 
meaning too efficiently or succinctly.  The platitudes 
to which we pay homage in the computer industry are code 
reuse, portability, interopability, expandability, compatibility,
maintainability, standardization, forward looking, security, etc.  
We just have to remember that people really refer to exactly the 
opposite thing when they use those terms. Optimize marketing?

3.tinyclos brevity?

"damien.guichardwanadoo.fr" < XXXX@XXXXX.COM > writes:
<snip>
>   (lambda (msg . arg-list)
>     (define getter (eval msg (the-environment)))
>     (if (procedure? getter)
>       (apply getter arg-list)
>       getter
>     )
>   )
> )
<snip>

Right, or another way to do it is with a "case" dispatch as per SICP
(though they use cond IIRC):

(lambda (msg . arg-list)
  (case m
    ((val) val)
    ((inc) (inc (car arg-list)))))

etc etc.

Not as OOAO-y, but you don't have to expose all slots, and you can
provide special operations for some messages (which I use, I have a
has-a relationship that I just pass on the messages to).

4.Brevity vs. Lispicity

5.Why is qsort going into infinite recursion?

Qsort drops recurring elemtns int he below definition.

> (qsort '(12 3 34 12))
(3 12 34)

But when I try to fix it by doing:
(qsort (filter (lambda (x) (>= x middle)) xs))))))

it ends in infinite recursion. why?


(define (nth pos xs)
  (if (< (length xs) pos)
      '()
      (if (> pos 0)
	  (nth (- pos 1) (cdr xs))
	  (car xs))))

(define (mid xs)
  (nth (- (/ (length xs) 2) 1) xs))

(define (qsort xs)
  (if (= (length xs) 0)
      xs
      (let ((middle (mid xs)))
	(append
	 (qsort (filter (lambda (x) (< x middle)) xs))
	 (list middle)
	 (qsort (filter (lambda (x) (> x middle)) xs))))))

6. qsort needs one more argument

7. qsort

8. qsort wiht struct and pointers - GAL



Return to lisp

 

Who is online

Users browsing this forum: No registered users and 53 guest