java - Optimal median function -
i experimenting code in attempt answer generic method find median of 3 values , trying ensure compareto
method called minimum number of times , maximise efficiency of code , came this:
// flattens results of compareto -1, 0, 1 static int sign(int x) { return x < 0 ? -1 : x == 0 ? 0 : 1; } // use enum help. enum abc { a() { @override <t> t which(t a, t b, t c) { return a; } }, b() { @override <t> t which(t a, t b, t c) { return b; } }, c() { @override <t> t which(t a, t b, t c) { return c; } }, insane() { @override <t> t which(t a, t b, t c) { // < b , b < c c < return null; } }; abstract <t> t which(t a, t b, t c); } // straight lookup. private static final abc[][][] median = { { // < b { // b < c // < c abc.b, // == c abc.insane, // > c abc.insane }, { // b == c // < c abc.b, // == c abc.insane, // > c abc.insane }, { // b > c // < c abc.c, // == c abc.a, // > c abc.a } }, { // == b { // b < c // < c abc.b, // == c abc.insane, // > c abc.insane }, { // b == c // < c abc.insane, // == c abc.b, // > c abc.insane }, { // b > c // < c abc.a, // == c abc.b, // > c abc.a } }, { // > b { // b < c // < c abc.a, // == c abc.a, // > c abc.c }, { // b == c // < c abc.insane, // == c abc.insane, // > c abc.b }, { // b > c // < c abc.insane, // == c abc.insane, // > c abc.b } } }; private static <t extends comparable> t median(t a, t b, t c) { system.out.print(" ab=" + sign(a.compareto(b)) + " bc=" + sign(b.compareto(c)) + " ac=" + sign(a.compareto(c))); // least number of comparisons. return median[sign(a.compareto(b)) + 1][sign(b.compareto(c)) + 1][sign(a.compareto(c)) + 1] .which(a, b, c); } // test case. private static <t extends comparable> t median2(t a, t b, t c) { list<t> medianhelper = arrays.aslist(a, b, c); collections.sort(medianhelper); return medianhelper.get(1); } public void test() { (int = -5; <= 5; += 5) { (int b = -3; b <= 3; b += 3) { (int c = -1; c <= 1; c++) { system.out.print("(" + + "," + b + "," + c + ")"); integer m = median(a, b, c); integer m2 = median2(a, b, c); system.out.print(" -> " + m + " & " + m2); if (m != m2) { system.out.print(" <-- wrong"); } system.out.println(); } } } }
to working used sort them , pick middle one
technique , manually tweaked matrix until returned same result.
although seems work not cover of possibilities when compareto
unstable (e.g. a < b && b < c && c < a
) don't think important.
is there mechanism use correctly generate matrix? ideally 1 used generate min
, max
matrices too.
if want call compareto
3 times (i don't think can make work 2 calls), why not simple nested if/else:
public static <t extends comparable> t median(t a, t b, t c) { if (a.compareto(b) <= 0) { if (a.compareto(c) <= 0) { return b.compareto(c) <= 0 ? b : c; //a <= b && <= c, return min(b, c) } else { return a; //c < <= b, return } } else { // b < if (a.compareto(c) <= 0) { return a; // b < <= c, return } else { return b.compareto(c) <= 0 ? c : b; //b < && > c, return max(b, c) } } }
Comments
Post a Comment