<html>
<head>
<style><!--
.hmmessage P
{
margin:0px;
padding:0px
}
body.hmmessage
{
font-size: 10pt;
font-family:Verdana
}
--></style>
</head>
<body class='hmmessage'>
<div><br></div><span class="Apple-style-span" style="font-family: sans-serif; line-height: 19px; ">"the bubble sort seems to have nothing to recommend it, except a catchy name and the fact that it leads to some interesting theoretical problems",</span><br><br>Thinking about it, isn't that enough to recommend it.&nbsp;<div><br></div><div>What would Knuth say about using pictures and animations to teach programming.<br><br>&gt; CC: wookiz@hotmail.com; plt-scheme@list.cs.brown.edu<br>&gt; From: matthias@ccs.neu.edu<br>&gt; To: robby@eecs.northwestern.edu<br>&gt; Subject: Re: [plt-scheme] Do no evil<br>&gt; Date: Mon, 8 Mar 2010 10:47:16 -0500<br>&gt; <br>&gt; <br>&gt; Knuth wrote this up in the 1960s. Anyone who teaches bubble sort<br>&gt; in the 20xy is teaching 1970s computer science. But I think I am<br>&gt; now in some kind of loop with wooks.<br>&gt; <br>&gt; <br>&gt; <br>&gt; <br>&gt; On Mar 8, 2010, at 10:44 AM, Robby Findler wrote:<br>&gt; <br>&gt; &gt; Continuing my contrarianocity: When I was taught the bubble sort, I<br>&gt; &gt; wish that my teacher had taken the time to explain bubble sort's place<br>&gt; &gt; in the pantheon of sorting algorithms (there is essentially no metric<br>&gt; &gt; under which it better than some other sort, with the possible<br>&gt; &gt; exception of ease of implementation in Fortran 70).<br>&gt; &gt;<br>&gt; &gt; Robby<br>&gt; &gt;<br>&gt; &gt; On Mon, Mar 8, 2010 at 9:39 AM, Matthias Felleisen &lt;matthias@ccs.neu.edu <br>&gt; &gt; &gt; wrote:<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; I have taken Veer's understanding to derive a relatively short<br>&gt; &gt;&gt; form of bubble sort in the plain Scheme language:<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (define (bsort v)<br>&gt; &gt;&gt;  (define (sweep v i clean?)<br>&gt; &gt;&gt;    (cond<br>&gt; &gt;&gt;      [(= i (- n 1)) (if clean? v (sweep v 0 true))]<br>&gt; &gt;&gt;      [else (if (&lt;= (vector-ref v i) (vector-ref v (+ i 1)))<br>&gt; &gt;&gt;                (sweep v (+ i 1) clean?)<br>&gt; &gt;&gt;                (sweep (swap v i) (+ i 1) false))]))<br>&gt; &gt;&gt;  (define n (vector-length v))<br>&gt; &gt;&gt;  ;; IN<br>&gt; &gt;&gt;  (sweep v 0 true))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;; swap: factored out as suggested by Noel,<br>&gt; &gt;&gt; ;; do it with build-vector and weep! bubble<br>&gt; &gt;&gt; ;; demos how bad FP's performance can be :-)<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; But I have done so in ASL just to demonstrate that it is feasible.<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; You start with the generative recursion idea of bubbling through<br>&gt; &gt;&gt; the array until there are no more out of place items left. Then<br>&gt; &gt;&gt; you're done. Then you 'edit' the program with two observation.<br>&gt; &gt;&gt; If you were in #lang scheme, you'd come up with the above<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; The derivation is appended below. -- Matthias<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;; [Vec Number] -&gt; [Vec Number]<br>&gt; &gt;&gt; ;; create a sorted version of v<br>&gt; &gt;&gt; ;; effect: modify v<br>&gt; &gt;&gt; (define (bsort.v0 v)<br>&gt; &gt;&gt;  (local (;; Result = (list [Vec Number] Boolean)<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;          ;; [Vec Number] -&gt; [Vec Number]<br>&gt; &gt;&gt;          ;; (effect) create a sorted version of v<br>&gt; &gt;&gt;          ;; generative recursion: swap-all until nothing to swap  <br>&gt; &gt;&gt; anymore<br>&gt; &gt;&gt;          ;; termination: there are only a finite number of swaps<br>&gt; &gt;&gt;          (define (generative-driver v)<br>&gt; &gt;&gt;            (local ((define v+flag (sweep v))<br>&gt; &gt;&gt;                    (define newv   (first v+flag))<br>&gt; &gt;&gt;                    (define clean? (second v+flag)))<br>&gt; &gt;&gt;              (if clean? v (generative-driver v))))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt;          ;; [Vec Number] -&gt; Result<br>&gt; &gt;&gt;          ;; (effect) swap all out of place neighbors throughout  <br>&gt; &gt;&gt; vector<br>&gt; &gt;&gt;          (define (sweep v)<br>&gt; &gt;&gt;            (local (;; [Vec Number] N Boolean -&gt; Result<br>&gt; &gt;&gt;                    ;; accumulators: [0,i) is bubbled -- clean? no  <br>&gt; &gt;&gt; swaps so<br>&gt; &gt;&gt; far<br>&gt; &gt;&gt;                    (define (sweep v i clean?)<br>&gt; &gt;&gt;                      (cond<br>&gt; &gt;&gt;                        [(= i (- (vector-length v) 1)) (list v  <br>&gt; &gt;&gt; clean?)]<br>&gt; &gt;&gt;                        [else (if (&lt;= (vector-ref v i) (vector-ref v  <br>&gt; &gt;&gt; (+ i<br>&gt; &gt;&gt; 1)))<br>&gt; &gt;&gt;                                  (sweep v (+ i 1) clean?)<br>&gt; &gt;&gt;                                  (sweep (swap v i) (+ i 1)  <br>&gt; &gt;&gt; false))])))<br>&gt; &gt;&gt;              (sweep v 0 true))))<br>&gt; &gt;&gt;    ;; IN<br>&gt; &gt;&gt;    (generative-driver v)))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;; fold the geneative-driver into the sweep function<br>&gt; &gt;&gt; ;; observation: the base case packages up the result,<br>&gt; &gt;&gt; ;; which is immediately unfolded and used for another call<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (define (bsort.v1 v)<br>&gt; &gt;&gt;  (local (;; [Vec Number] -&gt; [Vec Number]<br>&gt; &gt;&gt;          ;; (effect) swap all out of place neighbors throughout  <br>&gt; &gt;&gt; vector<br>&gt; &gt;&gt;          (define (sweep v)<br>&gt; &gt;&gt;            (local (;; [Vec Number] N Boolean -&gt; Result<br>&gt; &gt;&gt;                    ;; accumulators: [0,i) is bubbled -- clean? no  <br>&gt; &gt;&gt; swaps so<br>&gt; &gt;&gt; far<br>&gt; &gt;&gt;                    (define (sweep v i clean?)<br>&gt; &gt;&gt;                      (cond<br>&gt; &gt;&gt;                        [(= i (- (vector-length v) 1))<br>&gt; &gt;&gt;                         (if clean? v (sweep v 0 true))]<br>&gt; &gt;&gt;                        [else (if (&lt;= (vector-ref v i) (vector-ref v  <br>&gt; &gt;&gt; (+ i<br>&gt; &gt;&gt; 1)))<br>&gt; &gt;&gt;                                  (sweep v (+ i 1) clean?)<br>&gt; &gt;&gt;                                  (sweep (swap v i) (+ i 1)  <br>&gt; &gt;&gt; false))])))<br>&gt; &gt;&gt;              (sweep v 0 true))))<br>&gt; &gt;&gt;    ;; IN<br>&gt; &gt;&gt;    (sweep v)))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;; eliminate the indirection from 1-ary sweep through 1-ary sweep<br>&gt; &gt;&gt; ;; lift the vector-length computation<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (define (bsort v)<br>&gt; &gt;&gt;  (local (;; [Vec Number] N Boolean -&gt; Result<br>&gt; &gt;&gt;          ;; accumulators: [0,i) is bubbled -- clean? no swaps so far<br>&gt; &gt;&gt;          (define (sweep v i clean?)<br>&gt; &gt;&gt;            (cond<br>&gt; &gt;&gt;              [(= i (- n 1)) (if clean? v (sweep v 0 true))]<br>&gt; &gt;&gt;              [else (if (&lt;= (vector-ref v i) (vector-ref v (+ i 1)))<br>&gt; &gt;&gt;                        (sweep v (+ i 1) clean?)<br>&gt; &gt;&gt;                        (sweep (swap v i) (+ i 1) false))]))<br>&gt; &gt;&gt;          ;; where<br>&gt; &gt;&gt;          (define n (vector-length v)))<br>&gt; &gt;&gt;    ;; IN<br>&gt; &gt;&gt;    (sweep v 0 true)))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;;<br>&gt; &gt;&gt; -----------------------------------------------------------------------------<br>&gt; &gt;&gt; ;; auxiliaries<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;; [Vec Number] N -&gt; [Vec Number]<br>&gt; &gt;&gt; ;; swap items i and i+1 in v<br>&gt; &gt;&gt; (define (swap v i)<br>&gt; &gt;&gt;  (local ((define v@i (vector-ref v i)))<br>&gt; &gt;&gt;    (begin<br>&gt; &gt;&gt;      (vector-set! v i (vector-ref v (+ i 1)))<br>&gt; &gt;&gt;      (vector-set! v (+ i 1) v@i)<br>&gt; &gt;&gt;      v)))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; ;;<br>&gt; &gt;&gt; -----------------------------------------------------------------------------<br>&gt; &gt;&gt; ;; tests<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (define (generate-test) (vector 3 1 9 8 5 6 7 0 4 2))<br>&gt; &gt;&gt; (define swapped0 (vector 1 3 9 8 5 6 7 0 4 2))<br>&gt; &gt;&gt; (define swapped2 (vector 3 1 8 9 5 6 7 0 4 2))<br>&gt; &gt;&gt; (define sorted (vector 0 1 2 3 4 5 6 7 8 9))<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (check-expect (swap (generate-test) 0) swapped0)<br>&gt; &gt;&gt; (check-expect (swap (generate-test) 2) swapped2)<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; (check-expect (bsort (generate-test)) sorted)<br>&gt; &gt;&gt;<br>&gt; &gt;&gt; _________________________________________________<br>&gt; &gt;&gt;  For list-related administrative tasks:<br>&gt; &gt;&gt;  http://list.cs.brown.edu/mailman/listinfo/plt-scheme<br>&gt; &gt;&gt;<br>&gt; <br></div>                                               <br /><hr />Do you have a story that started on Hotmail? <a href='http://clk.atdmt.com/UKM/go/195013117/direct/01/' target='_new'>Tell us now</a></body>
</html>