Sunday, February 5, 2017

LookinForLove

// ===============================================================
// Lookin' for Love (YouTube)
//
// WELL I've spent a lifetime lookin' for you
// Single bars and good time lovers were never TRUE
// Playin' a fool's game, hopin' to win
// And tellin' those sweet lies and losin' again
// I was lookin' for love in all the wrong places
// Lookin' for love in too many faces
// Searching their i's, lookin' for traces
// Of what
//   I'm
//     dreamin' of
// Hopin' to find a friend and a lover
// I'll bless the day I discover
// Another heart
//     lookin' for love.
//
// AND I was alone then, no love in sight
// I did everything I could to get me through the night
// I don't know where it started or where it might end
// I turn to a stranger just like a friend
// 'cause I was lookin' for love in all the wrong places
// Lookin' for love in too many faces
// Searching their i's, lookin' for traces
// Of what
//   I'm
//     dreamin' of
// Hopin' to find a friend and a lover
// I'll bless the day I discover
// Another heart
//   lookin' for love.
//
// THEN you came a knockin' at my heart's door
// Your everything I've been looking for
// There's no more ||: lookin' for love in all the wrong places
// Lookin' for love in too many faces
// Searching their i's, lookin' for traces
// Of what
//   I'm
//     dreamin' of
// Now that I've found a friend and a lover,
// God bless the day I discovered you
//   O you
//     looking for love... :||
//
//                               - recorded by Johnny Lee (singer)
//         not to be confused with Johnny Lee (computer scientist)
// ===============================================================

class Matchmaker<T extends Comparable<T>> {

  private MeteredSearcher<T> searcher;
  private MeteredSorter<T> sorter;

  private void printArray(T[] array, int headSize, int tailSize) {
    int i;
    boolean skipSome;
    int n = array != null ? array.length : 0;
    int headBegin = 0;
    int headEnd = headSize - 1;
    int tailBegin = n - tailSize;
    int tailEnd = n - 1;

    // Print number of elements

    System.out.println("n: " + n);

    // Print (possibly partial) list of elements

    System.out.print("[");
    if (headSize > n) {
      headEnd = n - 1;
    }
    for (i = 0; i <= headEnd; i++) {
      if (i > 0) {
        System.out.print(", ");
      }
      System.out.print(array[i]);
    }
    if (headSize + tailSize > n) {
      tailBegin = headEnd + 1;
    }
    for (i = tailBegin; i <= tailEnd; i++) {
      skipSome = i == tailBegin && i < tailEnd;
      System.out.print(skipSome ? ", ..., " : ", ");
      System.out.print(array[i]);
    }
    System.out.println("]");
  }

  private void search(T[] array, T key, int from, int to) {
    String output;
    try {
      to = to < 0 && array != null ? array.length - 1 : to;
      int i = searcher.find(array, key, from, to);
      printArray(array, 7, 3);
      if (i > -1) {
        output = "Found " + key + " at index " + i;
      }
      else {
        output = "Did not find " + key;
      }
      output += ".\nCost (units): ";
      output += searcher.unitsCounted();
      output += "\nTime (ns): ";
      output += searcher.timeConsumed();
    }
    catch (IllegalArgumentException ia) {
      output = ia.getMessage();
    }
    catch (IndexOutOfBoundsException oob) {
      output = oob.getMessage();
    }
    System.out.println(output);
  }

  private void sort(T[] array, int from, int to) {
    String output = "";
    try {
      to = to < 0 && array != null ? array.length - 1 : to;
      printArray(array, 7, 3);
      sorter.sort(array, from, to);
      printArray(array, 7, 3);
      output += "Cost (units): ";
      output += sorter.unitsCounted();
      output += "\nTime (ns): ";
      output += sorter.timeConsumed();
    }
    catch (IllegalArgumentException ia) {
      output = ia.getMessage();
    }
    catch (IndexOutOfBoundsException oob) {
      output = oob.getMessage();
    }
    System.out.println(output);
  }

  public void evaluate(T[] array, T key, int from, int to) {

    // Sequential searching

    System.out.println("\nMeteredLinearSearcher");
    searcher = new MeteredLinearSearcher<T>();
    search(array, key, from, to);
    System.out.println("\nMeteredQuickLinearSearcher");
    searcher = new MeteredQuickLinearSearcher<T>();
    search(array, key, from, to);
    System.out.println("\nMeteredQuickerLinearSearcher");
    searcher = new MeteredQuickerLinearSearcher<T>();
    search(array, key, from, to);

    // Sorting

    System.out.println("\nMeteredInsertionSorter");
    sorter = new MeteredInsertionSorter<T>();
    sort(array, from, to);

    // Binary search

    searcher = new MeteredBinarySearcher<T>();
    System.out.println("\nMeteredBinarySearcher (loops)");
    search(array, key, from, to);
    System.out.println("\nMeteredBinarySearcher (recurses)");
    search(array, key, to, from);
  }
}

public class LookinForLove {
  public static void main(String[] args) {

    // Constants

    final Boolean love = true; // one in a ...
    final int million = 1000000;

    // Matchmakers

    final Matchmaker<Boolean> boolMatcher =
      new Matchmaker<Boolean>();
    final Matchmaker<Integer> intMatcher =
      new Matchmaker<Integer>();
    final Matchmaker<Long> longMatcher =
      new Matchmaker<Long>();

    // Candidates

    Boolean[] boolSeq = new Boolean[million];
    Integer[] nullSeq = null;
    Integer[] emptySeq = {};
    Integer[] soleSeq = { 1 };
    Integer[] intSeq = {
      21701, 23209, 44497, 86243, 132049, 216091,
      4253, 4423, 9689, 9941, 11213, 19937,
      521, 607, 1279, 2203, 2281, 3217,
      19, 31, 61, 89, 107, 127,
      2, 3, 5, 7, 13, 17
    };
    Long[] longSeq = {
      2305843008139952128L, 137438691328L, 8589869056L,
      33550336L, 8128L, 496L, 28L, 6L
    };

    // Initialize variables

    int i = million;
    boolSeq[--i] = love;
    while (--i > -1)
      boolSeq[i] = !love;

    Boolean boolKey = love;
    Integer intKey = 0;
    Long longKey = 0L;
    int from = 0;
    int i2 = intSeq.length - 1;
    int l2 = longSeq.length - 1;
    int b2 = boolSeq.length - 1;
    int o2 = soleSeq.length - 1;
    int e2 = emptySeq.length - 1;
    int n2 = -1;

    // Parse arguments and update variables

    if (args.length > 0) {
      try { longKey = Long.parseLong(args[0]); }
      catch (NumberFormatException e) {
        System.out.println("Invalid Integer key. Using default.");
      }
      try { intKey = Integer.parseInt(args[0]); }
      catch (NumberFormatException e) {
        System.out.println("Invalid Long key. Using default.");
      }
      boolKey = Boolean.parseBoolean(args[0]);
    }
    if (args.length > 1) {
      try { from = Integer.parseInt(args[1]); }
      catch (NumberFormatException e) {
        System.out.println("Invalid from value. Using default.");
      }
    }
    if (args.length > 2) {
      try {
        i2 = l2 = b2 = o2 = e2 = n2 = Integer.parseInt(args[2]);
      }
      catch (NumberFormatException e) {
        System.out.println("Invalid to value. Using default.");
      }
    }

    // Evaluate candidates

    System.out.println("*** integer candidates ***");
    intMatcher.evaluate(intSeq, intKey, from, i2);

    System.out.println("\n*** long candidates ***");
    longMatcher.evaluate(longSeq, longKey, from, l2);

    System.out.println("\n*** boolean candidates ***");
    boolMatcher.evaluate(boolSeq, boolKey, from, b2);

    System.out.println("\n*** sole candidate ***");
    intMatcher.evaluate(soleSeq, intKey, from, o2);

    System.out.println("\n*** no candidates ***");
    intMatcher.evaluate(emptySeq, intKey, from, e2);

    System.out.println("\n*** null candidates ***");
    intMatcher.evaluate(nullSeq, intKey, from, n2);
  }
}