package searching;

import java.io.*;
import java.lang.System;
import java.lang.Math;

public class searchTest {
    // this procedure provides timing data for linear and binary searches

    public static void main (String argv[]) 
        throws Exception {

        // declaration of variables
        InputStreamReader istream  = new InputStreamReader(System.in);
        BufferedReader in = new BufferedReader(istream);
        PrintWriter out = new PrintWriter(System.out, true);

        int numTrials;    // number of experiments per array size
        int numReps = 1000; // number of times experiment completed
        int currentTrial; // number of current trial at given size
        int arraySize;    // size of current array
        int minSize;      // smallest array size to be checked
        int maxSize;      // largest array size to be checked
        int item;         // item to search for in array
        int i, j;         // index variables
        int lo, hi, mid;  // binary search variables
        long startTime, endTime; // variables to count milliseconds
        boolean result = false;  // conclusion of search
        String line;      // for reading a line of input

        out.println ("Program to provide timing data for search algorithms");
        out.print ("Enter smallest size array to test: ");
        out.flush ();
        line = in.readLine();
        minSize = new Integer(line).intValue();

        out.println ("Array size will be doubled in successive tests "
                      + "until reaching a maximum");
        out.print ("Enter largest size array to test: ");
        out.flush ();
        line = in.readLine();
        maxSize = new Integer(line).intValue();

        out.println ("Random values will be searched in array 0, 2, 4, ...");
        out.print ("Enter number of trials at each size: ");
        out.flush ();
        line = in.readLine();
        numTrials = new Integer(line).intValue();

        out.println ();
        out.println ("Results of experiments (all times in milliseconds)");
        out.println ("                   linear          binary");
        out.println ("array              search          search");
        out.println ("size  item     result time     result time");
        for (arraySize = minSize; arraySize <= maxSize; arraySize *= 2) {
            // setup array
            int[] a = new int [arraySize];
            for (i = 0; i<arraySize; i++)
                a[i] = 2*i;

            out.println();
            for (currentTrial = 0; currentTrial < numTrials; currentTrial++) {
                // conduct experiments

                out.print (arraySize);

                // pick item to search for
                item = (int)Math.floor(3*arraySize*Math.random()-(minSize/2));

                out.print ("\t"+item);
                // record time and result for linear search
                startTime = System.currentTimeMillis();
                for (i = 0; i<numReps; i++) {
                    // linear search algorithm
                    j = 0;
                    while (j < a.length && item != a[j])
                        j++;
                    result = (j != a.length);
                }
                endTime = System.currentTimeMillis();
                out.print ("\t" + result);
                out.print ("\t" + (endTime-startTime));

                // record time and result for binary search
                startTime = System.currentTimeMillis();
                for (i = 0; i<numReps; i++) {
                    // binary search algorithm
                    lo = 0;
                    hi = a.length;
                    mid = (hi + lo)/2;
                    result = false;
                    while (!result && lo < hi) {
                        if (a[mid] == item)
                            result = true;
                        else if (a[mid] < item)
                            lo = mid + 1;
                        else hi = mid;
                        mid = (hi + lo)/2;
                    }
                }
                endTime = System.currentTimeMillis();
                out.print ("\t" + result);
                out.println ("\t" + (endTime-startTime));
            }
        } // for
    } // main
} // searchTest
