From: Sudin
Subject: median of 3 values.
Date: 
Message-ID: <1dcfba52.0410042211.3d447078@posting.google.com>
Hi i am trying to get Median of three values x, y, z but this doesn't
seem to work. Any help??
(DEFUN MEDIAN-OF-THREE(x y z)
      ( COND 
            ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
return x(mid)
            ( (AND (> y x) (< y z))  y) ;; same here
            ( (AND (> z x) (< z y))  z) ;; same here
       )
)

> (MEDIAN-OF-THREE 1 2 3) 
> 2  
Correct.
But..
> (MEDIAN-OF-THREE 3 1 2) 
> NIL
??? any help would be apreciated.

Cheers,
Sudin.

From: Steven M. Haflich
Subject: Re: median of 3 values.
Date: 
Message-ID: <kOr8d.4972$JG2.1215@newssvr14.news.prodigy.com>
Sudin wrote:

> Hi i am trying to get Median of three values x, y, z but this doesn't
> seem to work. Any help??
> (DEFUN MEDIAN-OF-THREE(x y z)
>       ( COND 
>             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> return x(mid)
>             ( (AND (> y x) (< y z))  y) ;; same here
>             ( (AND (> z x) (< z y))  z) ;; same here
>        )
> )
> 
> 
>>(MEDIAN-OF-THREE 1 2 3) 
>>2  
> 
> Correct.
> But..
> 
>>(MEDIAN-OF-THREE 3 1 2) 
>>NIL

There are cases for which none of your three clauses are satisfied.

You should start with a computational definition of median, such as
here:  http://davidmlane.com/hyperstat/A27533.html

It is straightforward to implement this definition for any number
values, not just three.  Here is a quick version, not carefully
checked, which works for any number of arguments up to the limit
of the implementation's call-arguments-limit.  It also produces
a mathematically correct result if I've written it correctly...

(defun median (&rest values)
   (if (null (cdr values))
       (car values)
     (let* ((vals (sort values #'<))
	   (len (length vals)))
       (if (oddp len)
	  (elt vals (ash len -1))
	(let ((p (nthcdr (1- (ash len -1)) vals)))
	  (/ (+ (car p) (cadr p)) 2))))))
From: ·······@yahoo.com
Subject: Re: median of 3 values.
Date: 
Message-ID: <1096971776.274828.55480@k17g2000odb.googlegroups.com>
Thanks Patrick. still learning lisp man.. thats tough to digest..I
tried it and it works like charm for any number of values.. However i
tried analysing code in 'Lisp' by Horn & Winston where they have done
it this way..

(defun median-of-three (a b c)
(cond (  (< a b)               ;; a &  b in order?
(cond ( (< b c ) b)          ;; b & c in order? if so b
( T (cond (( < a c) c) ;; a & c in order? if so c
(T a) ))))             ;;else A
(T (cond ( (< a c) a)     ;;a & c in order? if so A
(T (cond ((< b c) c)     ;;b & c in order? if so c
(T b ) ))))))            ;; else b

What does line ( T (cond (( < a c) c) do exactly? If i am not wrong
does it mean "If a < c then return c" (line 4)? But why that 'True'
there? and same in (T a) as well?
any help is appreciated.. :)
Cheers,
Sudin
From: Joe Marshall
Subject: Re: median of 3 values.
Date: 
Message-ID: <ekkdjmjr.fsf@ccs.neu.edu>
·······@yahoo.com writes:

> Thanks Patrick. still learning lisp man.. thats tough to digest..I
> tried it and it works like charm for any number of values.. However i
> tried analysing code in 'Lisp' by Horn & Winston where they have done
> it this way..
>
> (defun median-of-three (a b c)
> (cond (  (< a b)               ;; a &  b in order?
> (cond ( (< b c ) b)          ;; b & c in order? if so b
> ( T (cond (( < a c) c) ;; a & c in order? if so c
> (T a) ))))             ;;else A
> (T (cond ( (< a c) a)     ;;a & c in order? if so A
> (T (cond ((< b c) c)     ;;b & c in order? if so c
> (T b ) ))))))            ;; else b

Shame on them!  This is terribly confusing.  Let's fix it.

First, we'll use emacs to indent it properly:

(defun median-of-three (a b c)
  (cond ((< a b)                        ; a &  b in order?
         (cond ((< b c ) b)             ; b & c in order? if so b
               (T (cond ((< a c) c)     ; a & c in order? if so c
                        (T a)))))       ; else A
        (T (cond ((< a c) a)            ; a & c in order? if so A
                 (T (cond ((< b c) c)   ; b & c in order? if so c
                          (T b)))))))   ; else b

Second, we fix the COND expressions.  The last clause in a COND is
often a else clause which you write by using a condition of `T' (which
is always true).  In fact, it is probably a good idea to always have
an else clause just to indicate that you have covered all the bases.

But when a COND expression only has two clauses and the second one is
an else, it is *much* clearer to write it as an IF expression.

(cond (<some-condition> <some-result>)  <=>  (if <some-condition>
      (T <else-result>))                         <some-result>
                                                 <else-result>)

So our expression becomes:

(defun median-of-three (a b c)
  (if (< a b)                           ; a &  b in order?
      (if (< b c )                      ; b & c in order?
          b                             ; if so b
          (if (< a c)                   ; a & c in order?
              c                         ; if so c
              a))                       ; else A
    (if (< a c)                         ; a & c in order
        a                               ; if so A
        (if (< b c)                     ; b & c in order?
            c                           ; if so c
            b))))                       ; else b

That's better, but as it turns out when an IF expression has another
IF expression as it's <else-clause>, it is clearer to use a COND!

(if <condition1>     <=> (cond (<condition1> <result1>)
    <result1>                  (<condition2> <result2>)
    (if <condition2>           (t            <result3>))
        <result2>
        <result3>))

But this isn't undoing what we just did as you can see below:

(defun median-of-three (a b c)
  (cond ((< a b)   (cond ((< b c) b)   
                         ((< a c) c)   
                         (t       a))) 
        ((< a c) a)                    
        ((< b c) c)                    
        (t       b)))                  

I think this is much clearer than the original.
From: Frank Buss
Subject: Re: median of 3 values.
Date: 
Message-ID: <cjttl8$r4k$1@newsreader2.netcologne.de>
·······@yahoo.com wrote:

> (defun median-of-three (a b c)
> (cond (  (< a b)               ;; a &  b in order?
> (cond ( (< b c ) b)          ;; b & c in order? if so b
> ( T (cond (( < a c) c) ;; a & c in order? if so c
> (T a) ))))             ;;else A
> (T (cond ( (< a c) a)     ;;a & c in order? if so A
> (T (cond ((< b c) c)     ;;b & c in order? if so c
> (T b ) ))))))            ;; else b
> 
> What does line ( T (cond (( < a c) c) do exactly? If i am not wrong
> does it mean "If a < c then return c" (line 4)? 

you are right.

> But why that 'True' there? and same in (T a) as well?

this is the last default, if no cases of the cond matches. Perhaps you 
understand it better, if formatted better (use a fixed-font like Courier 
to view it)

(defun median-of-three (a b c)
  (cond ((< a b)                       ;; a &  b in order?
         (cond ((< b c ) b)            ;; b & c in order? if so b
               (T (cond (( < a c) c)   ;; a & c in order? if so c
                        (T a) ))))     ;; else A
        (T (cond ((< a c) a)           ;; a & c in order? if so A
                 (T (cond ((< b c) c)  ;; b & c in order? if so c
                          (T b)))))))  ;; else b

The algorithm has to main branches: if a < b and if a >= b. Within these 
branches the rest is checked.

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Frank Buss
Subject: Re: median of 3 values.
Date: 
Message-ID: <cjtokq$jql$1@newsreader2.netcologne.de>
"Steven M. Haflich" <·················@alum.mit.edu> wrote:

> (defun median (&rest values)
>    (if (null (cdr values))
>        (car values)

why did you wrote the check for null not like this:

  (if null values) nil

>      (let* ((vals (sort values #'<))
>         (len (length vals)))
>        (if (oddp len)
>        (elt vals (ash len -1))
>      (let ((p (nthcdr (1- (ash len -1)) vals)))
>        (/ (+ (car p) (cadr p)) 2))))))

(ash len -1) looks nice to an assembler programmer :-) , and your 
optimization with nthcdr might produce faster code, but perhaps this is 
easier to read:

(defun median (values)
  (if (null values) nil
    (let* ((vals (sort values #'<))
           (len (length vals))
           (len2 (floor len 2)))
      (if (oddp len)
          (elt vals len2)
        (/ (+ (elt values (1- len2)) 
              (elt values len2)) 
           2)))))

I've changed the &rest argument to a list, because I think most time a 
median is used for an unknown number of elements.

The median function can be used to derive a very short median-of-three 
function:

(defun median-of-three (x y z)
  (elt (sort (list x y z) #'<) 1))

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Steven M. Haflich
Subject: Re: median of 3 values.
Date: 
Message-ID: <tZ09d.7649$nj.3397@newssvr13.news.prodigy.com>
Frank Buss wrote:

> "Steven M. Haflich" <·················@alum.mit.edu> wrote:
> 
> 
>>(defun median (&rest values)
>>   (if (null (cdr values))
>>       (car values)
> 
> 
> why did you wrote the check for null not like this:
> 
>   (if null values) nil

Your test is _not_ the same thing.  My test checked for
zero or one argument.  Your test checks for zero arguments.

There is a real mathematical question what should be the
median of _no_ values.  Cmopare the CL functions + - *
and /.  + and * accept zero arguments, but - and / are
specified to signal error with zero arguments.  I suspect
median should also signal error, but I haven't thought
about it carefully.  If a median is defined to be a number,
or maybe a real, nil is not an acceptable value to return.

>>     (let* ((vals (sort values #'<))
>>        (len (length vals)))
>>       (if (oddp len)
>>       (elt vals (ash len -1))
>>     (let ((p (nthcdr (1- (ash len -1)) vals)))
>>       (/ (+ (car p) (cadr p)) 2))))))
> 
> (ash len -1) looks nice to an assembler programmer :-) , and your 
> optimization with nthcdr might produce faster code, but perhaps this is 
> easier to read:

The difference is that a normal compiler might not be able to see
the combination of oddp and / to infer that the index is a nonegative
integer, while ash of a nonnegative integer is trivially always another
nonnegative integer.

> (defun median (values)
>   (if (null values) nil
>     (let* ((vals (sort values #'<))
>            (len (length vals))
>            (len2 (floor len 2)))
>       (if (oddp len)
>           (elt vals len2)
>         (/ (+ (elt values (1- len2)) 
>               (elt values len2)) 
>            2)))))
> 
> I've changed the &rest argument to a list, because I think most time a 
> median is used for an unknown number of elements.

Fnie, but your function is incompatible with the callnig convention
assumed in the original flawed solution.

> The median function can be used to derive a very short median-of-three 
> function:
> 
> (defun median-of-three (x y z)
>   (elt (sort (list x y z) #'<) 1))

Go back and read my solution.  It is a general solution that handles
this case as well as other general median-of-n up to the implementation's
call-arguments-limit.
From: Frank Buss
Subject: Re: median of 3 values.
Date: 
Message-ID: <ck2gu7$mu0$1@newsreader2.netcologne.de>
"Steven M. Haflich" <·················@alum.mit.edu> wrote:

> Your test is _not_ the same thing.  My test checked for
> zero or one argument.  Your test checks for zero arguments.

thanks, now I understand why you wrote it like this. "cdr values" and "car 
values" returns nil, if "values" is nil or the only one element, if there is 
only one cdr, but you are right, it should signal an error, if called with 
zero arguments.

> The difference is that a normal compiler might not be able to see
> the combination of oddp and / to infer that the index is a nonegative
> integer, while ash of a nonnegative integer is trivially always another
> nonnegative integer.

I didn't use "oddp" in combination with "/". Do you mean the floor function? 
The Common Lisp HyperSpec says:

quotient---for floor, ceiling, truncate, and round: an integer

-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Steven M. Haflich
Subject: Re: median of 3 values.
Date: 
Message-ID: <36F9d.26700$QJ3.18359@newssvr21.news.prodigy.com>
Frank Buss wrote:

> I didn't use "oddp" in combination with "/". Do you mean the floor function? 
> The Common Lisp HyperSpec says:
> 
> quotient---for floor, ceiling, truncate, and round: an integer

Right you are.  This part of your code does not present different
inferencing difficulty to the compiler than mine.

However, I don't like the _two_ calls to elt in the even length
case, since elt on a list costs linear time, and the work can be
done in a single linear pass rather than two.

Yours:

     (if (oddp len)
         (elt vals len2)
       (/ (+ (elt values (1- len2))
             (elt values len2))
          2))

Mine:

     (if (oddp len)
         (elt vals (ash len -1))
       (let ((p (nthcdr (1- (ash len -1)) vals)))
         (/ (+ (car p) (cadr p)) 2)))
From: Ron Garret
Subject: Re: median of 3 values.
Date: 
Message-ID: <rNOSPAMon-981028.09203005102004@nntp1.jpl.nasa.gov>
In article <····························@posting.google.com>,
 ·······@yahoo.com (Sudin) wrote:

> Hi i am trying to get Median of three values x, y, z but this doesn't
> seem to work. Any help??
> (DEFUN MEDIAN-OF-THREE(x y z)
>       ( COND 
>             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> return x(mid)
>             ( (AND (> y x) (< y z))  y) ;; same here
>             ( (AND (> z x) (< z y))  z) ;; same here
>        )
> )
> 
> > (MEDIAN-OF-THREE 1 2 3) 
> > 2  
> Correct.
> But..
> > (MEDIAN-OF-THREE 3 1 2) 
> > NIL
> ??? any help would be apreciated.
> 
> Cheers,
> Sudin.


(defun median-of-three (x y z)
  (second (sort (list x y z) '<)))

;-)

rg
From: Andras Simon
Subject: Re: median of 3 values.
Date: 
Message-ID: <vcd3c0t7e4j.fsf@csusza.math.bme.hu>
·······@yahoo.com (Sudin) writes:

> Hi i am trying to get Median of three values x, y, z but this doesn't
> seem to work. Any help??
> (DEFUN MEDIAN-OF-THREE(x y z)
>       ( COND 
>             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> return x(mid)
>             ( (AND (> y x) (< y z))  y) ;; same here
>             ( (AND (> z x) (< z y))  z) ;; same here
>        )
> )
> 
> > (MEDIAN-OF-THREE 1 2 3) 
> > 2  
> Correct.
> But..
> > (MEDIAN-OF-THREE 3 1 2) 
> > NIL
> ??? any help would be apreciated.

There is more than one way for something to be in the middle.

By the way, (AND (> x y) (< x z)) == (< y x z)

HTH,
Andras
From: Kaz Kylheku
Subject: Re: median of 3 values.
Date: 
Message-ID: <cf333042.0410051340.15b9cda8@posting.google.com>
·······@yahoo.com (Sudin) wrote in message news:<····························@posting.google.com>...
> > (MEDIAN-OF-THREE 3 1 2) 
> > NIL
> ??? any help would be apreciated.

(defun median-of-three (a b c)
  (aref (sort (vector a b c) #'<) 1)))

:)
From: Wade Humeniuk
Subject: Re: median of 3 values.
Date: 
Message-ID: <U9z8d.13074$MV5.12643@clgrps13>
Sudin wrote:
> Hi i am trying to get Median of three values x, y, z but this doesn't
> seem to work. Any help??
> (DEFUN MEDIAN-OF-THREE(x y z)
>       ( COND 
>             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> return x(mid)
>             ( (AND (> y x) (< y z))  y) ;; same here
>             ( (AND (> z x) (< z y))  z) ;; same here
>        )
> )
One more way,

(defun median-of-three (x y z)
   ;; 3x2x1 = 3! = 6 orderings of three numbers
   (cond
    ((or (<= x y z) (<= z y x)) y)
    ((or (<= y x z) (<= z x y)) x)
    ((or (<= x z y) (<= y z x)) z)))

CL-USER 1 > (median-of-three 1 2 3)
2

CL-USER 2 > (median-of-three 3 1 2)
2

CL-USER 3 > (median-of-three 2 1 3)
2

Wade
From: ·······@yahoo.com
Subject: Re: median of 3 values.
Date: 
Message-ID: <1097123333.338508.278410@h37g2000oda.googlegroups.com>
Wade Humeniuk wrote:
> Sudin wrote:
> > Hi i am trying to get Median of three values x, y, z but this
doesn't
> > seem to work. Any help??
> > (DEFUN MEDIAN-OF-THREE(x y z)
> >       ( COND
> >             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> > return x(mid)
> >             ( (AND (> y x) (< y z))  y) ;; same here
> >             ( (AND (> z x) (< z y))  z) ;; same here
> >        )
> > )
> One more way,
>
> (defun median-of-three (x y z)
>    ;; 3x2x1 = 3! = 6 orderings of three numbers
>    (cond
>     ((or (<= x y z) (<= z y x)) y)
>     ((or (<= y x z) (<= z x y)) x)
>     ((or (<= x z y) (<= y z x)) z)))
>
> CL-USER 1 > (median-of-three 1 2 3)
> 2
>
> CL-USER 2 > (median-of-three 3 1 2)
> 2
>
> CL-USER 3 > (median-of-three 2 1 3)
> 2
>
> Wade

Thanx Pascal, everyone contributing to this problem. Quickly scanning
over, by far i found wade's solution to very much reflect my own
solution.. That was it, just an 'or' logical substitution in
mines!!hahha.. Its very readable, easy to understand for beginner like
me. but others who have contributed to the problem ofcourse designed it
to run for any number of arguments.. :)
Thanx.. I will have to look at Pascal's idea more closely. I have
recently seen some rants about Lisp being old & yada yada... but i
think Lisp is cool, gets things done quickly.
Cheers,
Sudin kc.
From: Pascal Bourguignon
Subject: Re: median of 3 values.
Date: 
Message-ID: <87655pnqfl.fsf@thalassa.informatimago.com>
·······@yahoo.com (Sudin) writes:

> Hi i am trying to get Median of three values x, y, z but this doesn't
> seem to work. Any help??
> (DEFUN MEDIAN-OF-THREE(x y z)
>       ( COND 
>             ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
> return x(mid)
>             ( (AND (> y x) (< y z))  y) ;; same here
>             ( (AND (> z x) (< z y))  z) ;; same here
>        )
> )
> 
> > (MEDIAN-OF-THREE 1 2 3) 
> > 2  
> Correct.
> But..
> > (MEDIAN-OF-THREE 3 1 2) 
> > NIL
> ??? any help would be apreciated.
> 
> Cheers,
> Sudin.


1- draw this table:

(carnot '( (< a b) (< a c) (< b c) ) '(a b c) )
+---------+---------+---------+-----+-----+-----+
| (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
+---------+---------+---------+-----+-----+-----+
|   YES   |   YES   |   YES   |     |     |     |
|   YES   |   YES   |    NO   |     |     |     |
|   YES   |    NO   |   YES   |     |     |     |
|   YES   |    NO   |    NO   |     |     |     |
|    NO   |   YES   |   YES   |     |     |     |
|    NO   |   YES   |    NO   |     |     |     |
|    NO   |    NO   |   YES   |     |     |     |
|    NO   |    NO   |    NO   |     |     |     |
+---------+---------+---------+-----+-----+-----+



2- identify the meaning of each case:

+---------+---------+---------+-----+-----+-----+
| (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
+---------+---------+---------+-----+-----+-----+
|   YES   |   YES   |   YES   |     |     |     |  a <  b <  c
|   YES   |   YES   |    NO   |     |     |     |  a <  c <= b
|   YES   |    NO   |   YES   |     |     |     |  impossible
|   YES   |    NO   |    NO   |     |     |     |  c <= a <  b
|    NO   |   YES   |   YES   |     |     |     |  b <= a <  c
|    NO   |   YES   |    NO   |     |     |     |  impossible
|    NO   |    NO   |   YES   |     |     |     |  b <  c <= a
|    NO   |    NO   |    NO   |     |     |     |  c <= b <= a
+---------+---------+---------+-----+-----+-----+


3- depending on the meaning, check the action column (a = a is median,
   b = b is median, c = c is median).


+---------+---------+---------+-----+-----+-----+
| (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
+---------+---------+---------+-----+-----+-----+
|   YES   |   YES   |   YES   |     |  X  |     |  a <  b <  c
|   YES   |   YES   |    NO   |     |     |  X  |  a <  c <= b
|   YES   |    NO   |   YES   |     |     |     |  impossible
|   YES   |    NO   |    NO   |  X  |     |     |  c <= a <  b
|    NO   |   YES   |   YES   |  X  |     |     |  b <= a <  c
|    NO   |   YES   |    NO   |     |     |     |  impossible
|    NO   |    NO   |   YES   |     |     |  X  |  b <  c <= a
|    NO   |    NO   |    NO   |     |  X  |     |  c <= b <= a
+---------+---------+---------+-----+-----+-----+


4- Write the boolean equations for each action:

4-1 consider each action in turn, for example for "a is the median":
+---------+---------+---------+-----+-----+-----+
| (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
+---------+---------+---------+-----+-----+-----+
|   YES   |    NO   |    NO   |  X  |     |     |  c <= a <  b
|    NO   |   YES   |   YES   |  X  |     |     |  b <= a <  c
+---------+---------+---------+-----+-----+-----+

4-2 when a condition is true, write it as is; when it's false, write it negated:

    (< a b)       (< a c)   (not (< b c))
    (not (< a b)) (< a c)   (< b c)

4-3 encapsulate each line in a AND, and surround the whole in a OR:

    (or
      (and  (< a b)       (< a c)   (not (< b c)))
      (and  (not (< a b)) (< a c)   (< b c)))

    that gives you the condition for the action "a is the median".



(let ((print-circle nil))
  (print
   (carnot-solve '( (< a b) (< a c) (< b c) ) '(a b c)
                 '((yes yes yes   no  yes no)
                   (yes yes no    no  no  yes)
                   (yes no  no    yes no  no)
                   (no  yes yes   yes no  no)
                   (no  no  yes   no  no  yes)
                   (no  no  no    no  yes no)) 
                 '(no . yes) '(no . yes))))

((a lambda ((< a b) (< a c) (< b c)) 
    (or (and (< a b) (not (< a c)) (not (< b c))) 
        (and (not (< a b)) (< a c) (< b c)))) 
 (b lambda ((< a b) (< a c) (< b c)) 
    (or (and (< a b) (< a c) (< b c)) 
        (and (not (< a b)) (not (< a c)) 
             (not (< b c))))) 
 (c lambda ((< a b) (< a c) (< b c)) 
    (or (and (< a b) (< a c) (not (< b c)))
        (and (not (< a b)) (not (< a c)) (< b c)))))


(let ((print-circle nil))
  (print (cons 'cond
               (mapcar (lambda (case) (list (fourth case) (first case)))
                       (carnot-solve '( (< a b) (< a c) (< b c) ) '(a b c)
                                     '((yes yes yes   no  yes no)
                                       (yes yes no    no  no  yes)
                                       (yes no  no    yes no  no)
                                       (no  yes yes   yes no  no)
                                       (no  no  yes   no  no  yes)
                                       (no  no  no    no  yes no))
                                     '(no . yes) '(no . yes))))))


(cond ((or (and (< a b) (not (< a c)) (not (< b c))) 
           (and (not (< a b)) (< a c) (< b c))) 
       a)
      ((or (and (< a b) (< a c) (< b c)) 
           (and (not (< a b)) (not (< a c)) (not (< b c))))
       b)
      ((or (and (< a b) (< a c) (not (< b c)))
           (and (not (< a b)) (not (< a c)) (< b c))) 
       c))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

To vote Democrat or Republican, it's like changing of cabin in the Titanic.
From: Cesar Rabak
Subject: Re: median of 3 values.
Date: 
Message-ID: <4162DC51.90500@acm.org>
Pascal Bourguignon escreveu:
> ·······@yahoo.com (Sudin) writes:
> 
> 
>>Hi i am trying to get Median of three values x, y, z but this doesn't
>>seem to work. Any help??
>>(DEFUN MEDIAN-OF-THREE(x y z)
>>      ( COND 
>>            ( (AND (> x y) (< x z))  x) ;; if x > y && x < z then
>>return x(mid)
>>            ( (AND (> y x) (< y z))  y) ;; same here
>>            ( (AND (> z x) (< z y))  z) ;; same here
>>       )
>>)
>>
>>
>>>(MEDIAN-OF-THREE 1 2 3) 
>>>2  
>>
>>Correct.
>>But..
>>
>>>(MEDIAN-OF-THREE 3 1 2) 
>>>NIL
>>
>>??? any help would be apreciated.
>>
>>Cheers,
>>Sudin.
> 
> 
> 
> 1- draw this table:
> 
> (carnot '( (< a b) (< a c) (< b c) ) '(a b c) )
> +---------+---------+---------+-----+-----+-----+
> | (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
> +---------+---------+---------+-----+-----+-----+
> |   YES   |   YES   |   YES   |     |     |     |
> |   YES   |   YES   |    NO   |     |     |     |
> |   YES   |    NO   |   YES   |     |     |     |
> |   YES   |    NO   |    NO   |     |     |     |
> |    NO   |   YES   |   YES   |     |     |     |
> |    NO   |   YES   |    NO   |     |     |     |
> |    NO   |    NO   |   YES   |     |     |     |
> |    NO   |    NO   |    NO   |     |     |     |
> +---------+---------+---------+-----+-----+-----+
> 
> 
> 
> 2- identify the meaning of each case:
> 
> +---------+---------+---------+-----+-----+-----+
> | (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
> +---------+---------+---------+-----+-----+-----+
> |   YES   |   YES   |   YES   |     |     |     |  a <  b <  c
> |   YES   |   YES   |    NO   |     |     |     |  a <  c <= b
> |   YES   |    NO   |   YES   |     |     |     |  impossible
> |   YES   |    NO   |    NO   |     |     |     |  c <= a <  b
> |    NO   |   YES   |   YES   |     |     |     |  b <= a <  c
> |    NO   |   YES   |    NO   |     |     |     |  impossible
> |    NO   |    NO   |   YES   |     |     |     |  b <  c <= a
> |    NO   |    NO   |    NO   |     |     |     |  c <= b <= a
> +---------+---------+---------+-----+-----+-----+
> 
> 
> 3- depending on the meaning, check the action column (a = a is median,
>    b = b is median, c = c is median).
> 
> 
> +---------+---------+---------+-----+-----+-----+
> | (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
> +---------+---------+---------+-----+-----+-----+
> |   YES   |   YES   |   YES   |     |  X  |     |  a <  b <  c
> |   YES   |   YES   |    NO   |     |     |  X  |  a <  c <= b
> |   YES   |    NO   |   YES   |     |     |     |  impossible
> |   YES   |    NO   |    NO   |  X  |     |     |  c <= a <  b
> |    NO   |   YES   |   YES   |  X  |     |     |  b <= a <  c
> |    NO   |   YES   |    NO   |     |     |     |  impossible
> |    NO   |    NO   |   YES   |     |     |  X  |  b <  c <= a
> |    NO   |    NO   |    NO   |     |  X  |     |  c <= b <= a
> +---------+---------+---------+-----+-----+-----+
> 
> 
> 4- Write the boolean equations for each action:
> 
> 4-1 consider each action in turn, for example for "a is the median":
> +---------+---------+---------+-----+-----+-----+
> | (< a b) | (< a c) | (< b c) |  a  |  b  |  c  |
> +---------+---------+---------+-----+-----+-----+
> |   YES   |    NO   |    NO   |  X  |     |     |  c <= a <  b
> |    NO   |   YES   |   YES   |  X  |     |     |  b <= a <  c
> +---------+---------+---------+-----+-----+-----+
> 
> 4-2 when a condition is true, write it as is; when it's false, write it negated:
> 
>     (< a b)       (< a c)   (not (< b c))
>     (not (< a b)) (< a c)   (< b c)
> 
> 4-3 encapsulate each line in a AND, and surround the whole in a OR:
> 
>     (or
>       (and  (< a b)       (< a c)   (not (< b c)))
>       (and  (not (< a b)) (< a c)   (< b c)))
> 
>     that gives you the condition for the action "a is the median".
> 
> 
> 
> (let ((print-circle nil))
>   (print
>    (carnot-solve '( (< a b) (< a c) (< b c) ) '(a b c)
>                  '((yes yes yes   no  yes no)
>                    (yes yes no    no  no  yes)
>                    (yes no  no    yes no  no)
>                    (no  yes yes   yes no  no)
>                    (no  no  yes   no  no  yes)
>                    (no  no  no    no  yes no)) 
>                  '(no . yes) '(no . yes))))
> 
> ((a lambda ((< a b) (< a c) (< b c)) 
>     (or (and (< a b) (not (< a c)) (not (< b c))) 
>         (and (not (< a b)) (< a c) (< b c)))) 
>  (b lambda ((< a b) (< a c) (< b c)) 
>     (or (and (< a b) (< a c) (< b c)) 
>         (and (not (< a b)) (not (< a c)) 
>              (not (< b c))))) 
>  (c lambda ((< a b) (< a c) (< b c)) 
>     (or (and (< a b) (< a c) (not (< b c)))
>         (and (not (< a b)) (not (< a c)) (< b c)))))
> 
> 
> (let ((print-circle nil))
>   (print (cons 'cond
>                (mapcar (lambda (case) (list (fourth case) (first case)))
>                        (carnot-solve '( (< a b) (< a c) (< b c) ) '(a b c)
>                                      '((yes yes yes   no  yes no)
>                                        (yes yes no    no  no  yes)
>                                        (yes no  no    yes no  no)
>                                        (no  yes yes   yes no  no)
>                                        (no  no  yes   no  no  yes)
>                                        (no  no  no    no  yes no))
>                                      '(no . yes) '(no . yes))))))
> 
> 
> (cond ((or (and (< a b) (not (< a c)) (not (< b c))) 
>            (and (not (< a b)) (< a c) (< b c))) 
>        a)
>       ((or (and (< a b) (< a c) (< b c)) 
>            (and (not (< a b)) (not (< a c)) (not (< b c))))
>        b)
>       ((or (and (< a b) (< a c) (not (< b c)))
>            (and (not (< a b)) (not (< a c)) (< b c))) 
>        c))
> 
> 

If this had not be written in Lisp I could swear it was done by a DBA!

--
Cesar Rabak
From: ··············@hotmail.com
Subject: Re: median of 3 values.
Date: 
Message-ID: <1097033518.657792.270790@k26g2000oda.googlegroups.com>
Impressive, Pascal!

However, I believe the name you are reaching for is "Karnaugh" as in M.
Karnaugh, Trans. AIEE Comm. and Electron., _72_, part I, 593--599
(1953).
From: Pascal Bourguignon
Subject: Re: median of 3 values.
Date: 
Message-ID: <87fz4smeuh.fsf@thalassa.informatimago.com>
···············@hotmail.com" <··············@hotmail.com> writes:

> Impressive, Pascal!
> 
> However, I believe the name you are reaching for is "Karnaugh" as in M.
> Karnaugh, Trans. AIEE Comm. and Electron., _72_, part I, 593--599
> (1953).

Oops!

       Carnot, the thermodynamic diagrams.
     Karnaugh, the logic diagrams. 

I'll have some function renaming to do...
 

Thanks for the hint.
-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

To vote Democrat or Republican, it's like changing of cabin in the Titanic.
From: Ed Symanzik
Subject: Re: median of 3 values.
Date: 
Message-ID: <ck4018$15s0$1@msunews.cl.msu.edu>
Pascal Bourguignon wrote a cool Karnaugh solver:

Nice, but wouldn't it be more appropriate to solve the general median problem?

(defun median (&rest numbers)
   (let* ((count (length numbers))
          (center (floor i 2))
          (numbers (sort numbers #'>)))
     (cond ((zerop count) 0)                    ; nothing to do
           ((oddp count) (nth center numbers))  ; return the middle number
           ((evenp count)                       ; average the middle two numbers
            (/ (+ (nth (- center 1) numbers)
                  (nth center numbers))
               2)))))