/** test out linear and binary search on sorted lists of
 *  integers
 */
import java.io.*;
import java.util.Vector;
public class Searches {
  // br will read from files
  private BufferedReader br;
  //sorted list to search
  private Vector list= new Vector();

  /** constructor: create Searches by setting
   *  list to contain the numbers in filename,
   *  which are assumed to be sorted (non-decreasing)
   */
  public Searches(String filename) throws IOException {
    br= new BufferedReader(new InputStreamReader(
						 new FileInputStream(filename)));
    String input= br.readLine();
    while (input != null) {
      list.addElement(new Integer(input)); // use String constructor...
      input= br.readLine();
    }
  }

  /** binarySearch: return index of last array element <= s
   *  in non-decreasing list
   */
  public int binarySearch(int s){
    int i= -1; int j= list.size();
    // list[0..i] <= s && list[j..list.size() -1] > s &&
    // -1 <= i < j <= list.size()
    while (i != j-1) {
      int m= (i+j)/2;
      int midInt= ((Integer)list.elementAt(m)).intValue();
      if (midInt <= s) {
	i= m;
      }
      else {
	j= m;
      }
    }
    return i;
  }

  /** linearSearch: return index of last array element <= s
   *  in non-decreasing list
   */
  public int linearSearch(int s) {
    list.addElement(new Integer(s+1)); // add sentinel guaranteed to terminate search
    int i;
    // list[0..i-1] <= s
    for (i= 0; ((Integer)list.elementAt(i)).intValue() <= s;
	 i++) { // empty condition, we have sentinel
    }
    list.remove(list.size() - 1); // remove the sentinel
    return i - 1;
    
  }

  /** main searches for a value near the middle of tenThousandNumbers
   *  or hundredThousandNumbers
   */
  public static void main(String[] args) throws IOException{
    int s;
    Searches search= new Searches(args[0]); // load the appropriate filename
    if (args[0].equals("tenThousandNumbers")) {
      s= 6223220; // the 5 thousandth element
    }
    else {
      s= 4568949; // the 50 thousandth element
    }
    // get a rough idea of how long binary search takes...
    long startTime= System.currentTimeMillis();
    int i= search.binarySearch(s);
    System.out.println("Time consumed for binary search: " + 
		       (System.currentTimeMillis() - startTime) + 
		       " millisecond(s)");
    // get a rough idea of how long linear search takes...    
    startTime= System.currentTimeMillis();
    int j= search.linearSearch(s);
    System.out.println("Time consumed by linear search: " + 
		       (System.currentTimeMillis() - startTime) + 
		       " millisecond(s)");
    System.out.println("Index found by binary Search: " + i);
    System.out.println("Index found by linear Search: " + j);
    System.out.println("binarySearch found: " + (Integer)search.list.elementAt(i));
    System.out.println("binarySearch found: " + (Integer)search.list.elementAt(j));
  }
}
  

