[OT] Lower and upper median of 4

Timon Gehr via Digitalmars-d digitalmars-d at puremagic.com
Sat Nov 26 12:19:38 PST 2016


On 26.11.2016 18:17, Andrei Alexandrescu wrote:
> I'm submitting the median paper to
> http://2017.programmingconference.org/track/programming-2017-papers. (It
> was rejected by ALENEX... the short story is there was no open-source
> implementation and they simply didn't buy the results.)
>
> Now I have a C++ implementation available. I wanted to ask for your help
> with lower/upper median of 4, which I coded like this (based on the
> median of 5 posted here by user "tn" aka Teppo Niinimäki):
>
> template <bool leanRight, class T>
> void medianOf(T* r, size_t a, size_t b, size_t c, size_t d)
> {
>     assert(a != b && a != c && a != d && b != c && b != d
>         && c != d);
>     if (leanRight)
>     {
>         // In the median of 5 algorithm, consider r[e] infinite
>         if (r[c] < r[a]) {
>             std::swap(r[a], r[c]);
>         }
>         if (r[d] < r[b]) {
>             std::swap(r[b], r[d]);
>         }
>         if (r[d] < r[c]) {
>             std::swap(r[c], r[d]);
>             std::swap(r[a], r[b]);
>         }
>         if (r[c] < r[b]) {
>             std::swap(r[b], r[c]);
>         }
>         assert(r[a] <= r[c] && r[b] <= r[c] && r[c] <= r[d]);
>     }
>     else
>     {
>         // In the median of 5 algorithm consider r[a] infinitely small,
> then
>         // change b->a. c->b, d->c, e->d
>         if (r[c] < r[a]) {
>             std::swap(r[a], r[c]);
>         }
>         if (r[c] < r[b]) {
>             std::swap(r[b], r[c]);
>         }
>         if (r[d] < r[a]) {
>             std::swap(r[a], r[d]);
>         }
>         if (r[d] < r[b]) {
>             std::swap(r[b], r[d]);
>         } else {
>             if (r[b] < r[a]) {
>                 std::swap(r[a], r[b]);
>             }
>         }
>         assert(r[a] <= r[b] && r[b] <= r[c] && r[b] <= r[d]);
>     }
> }
>
> I started with Teppo's median-of-5 algorithm and eliminated the
> first/last element. Do you think you can do better?
>
>
> Thanks,
>
> Andrei

The following code (which I found using a quick brute-force search) uses 
at most 4 comparisons.


int median(bool leanRight)(int[4] a){
     static if(leanRight){
         return 
a[a[0]<a[1]?a[2]<a[3]?a[1]<a[3]?a[1]<a[2]?2:1:a[0]<a[3]?3:0:a[1]<a[2]?a[1]<a[3]?3:1:a[0]<a[2]?2:0:a[2]<a[3]?a[0]<a[3]?a[0]<a[2]?2:0:a[1]<a[3]?3:1:a[0]<a[2]?a[0]<a[3]?3:0:a[1]<a[2]?2:1];
     }else{
         return 
a[a[0]<a[1]?a[2]<a[3]?a[0]<a[2]?a[1]<a[2]?1:2:a[0]<a[3]?0:3:a[0]<a[3]?a[1]<a[3]?1:3:a[0]<a[2]?0:2:a[2]<a[3]?a[1]<a[2]?a[0]<a[2]?0:2:a[1]<a[3]?1:3:a[1]<a[3]?a[0]<a[3]?0:3:a[1]<a[2]?1:2];
     }
}

I guess you can also adapt the leanRight case to the leanLeft case by 
inverting all comparisons, then you should also get an algorithm that 
uses at most 4 comparisons.


More information about the Digitalmars-d mailing list