// The "Searches" class.
//This class includes a linear search, an interative binary search, and 
// a recursive binary search.

import hsa.Console;// for I/O

public class Searches
{
    static Console c = new Console();
    
    void getValues(int[] v, int n)
    //This method reads in an array of n integers.
    {
	int count=0;//to count the values
	c.println("Enter your values one per line.");
	for (count=0; count<n; count=count+1)//repeat n times
	{
	    v[count] = c.readInt();//read a value and place it in the array at the position count
	}
    }
    
    int linearSearch(int[] a, int value, int n)
    //Linear search checks every element in the array to see if the value passed in is there.
    //If the value is at the position called location, that value is returned.
    //If the value is not there, then location has its initial value of -1 and that is returned
    {
	int i = 0;//for moving through the array
	int location=-1;//initialize to a value that cannot be an index into the array
	
	for (i=0; i<n; i=i+1)//repeat for every element in the array
	{
	    if (a[i]==value)//check to see if the value requested is at the ith position
		location = i;//If the value is there, set location to be the ith index.
	}
	
	return location;//return the appropriate result.
     }  
     
     static int getMinIndex (int [] v, int first, int last)
    //find the index of the smallest element starting at first and
    //ending at last
    {
	int minInd = first;//start the min index at 1
	int i = first;//start i at first
	while (i < last)//repeat the loop from i to last
	{
	    
	    if (v [i] < v [minInd])//check to see if any array values
				//are less than the value at the minInd
		minInd = i;//if so, replace minInd with the newly found minimum
			    //index
	    i = i + 1;//increment i
	}
	return minInd;//return the index of the smallest element between
			//first and last
    }


    void selectSort (int [] v, int n)
    //put the values of v in order using the selection approach
    {
	int i = 0;//to use as a counter
	int temp = 0;//to store a value temporarily for swapping
	int minI = 0;//to hold the index of the smallest element

	for (i = 0 ; i < n ; i++)//repeat for each element in ithe array
	{
		     
	    minI = getMinIndex (v, i, n);//use the method getMinIndex to find out where
	    //the smallest element is starting at the ith entry
	   
	    temp = v [i];//save the ith element
	    v [i] = v [minI];//replace the ith element 
	    v [minI] = temp;//use the temp to put in the minI element
	    
	}

    }
     
     int binarySearchRecursive (int[] v, int w, int first, int last)
     //This recursive method splits the array in half, checks the middle value to see if
     //is the w passed in, and if so, sets the index to be the middle index.  If not, the same 
     //process is repeated for each half, until there are no more splits to be made.
     {
	int mid=-1;//a variable to hold the middle index.
	int index=-1;//initialize the variable to be returned so that if the value w is
		    //never found, -1 will be returned.
	
	if (first > last)//Check to see if the index for starting the search is higher than
			//the index for ending the search.  If so, stop and return the index
			//value since there are no more places to search.
	    return index;//return the index.
	    else //if the value was not yet found and there are still more elements to check
	    {
		mid = (last+first)/2;//find the middle index of the array part being searched
		
		if (v[mid] == w)//check to see if the value passed in (w) is at the mid position
		    {
			index = mid;//if w is the middle value, set the index to mid
			
			return index;//return the index
		    }
		else if (w < v[mid])//check to see if the desired value w is below the middle
		    index = binarySearchRecursive(v, w, first, mid-1);//call the method on the first 
						//half of the array
		else //assume the value cannot be in the first half, but may be in the upper half of the array
		{
		    index = binarySearchRecursive(v, w, mid+1,last);//call the method on the upper half
		    
		}
	     }
	  return index; //return the index
	 
    }
    
    int binarySearchIterative (int[] v, int w, int first, int last)
    //an iterative method for searching
    {
	int mid=0;//a variable to hold the middle index of the array
	while (first <= last)//repeat as long as the first index of the array part to be searched
		//is below the end
	{
	    mid = (first+last)/2;//find the middle index of the array being searched
	    if (w==v[mid])//check to see if the desired value w is there
		return mid;//if it is, return the mid index
	    else if (w < v[mid])//if not, check to see if w is below the mid value
		last = mid-1;//if so, change the last index to be mid-1 so the search
			//will take place only in the lower part of the array
	    else //otherwise assume that w cannot be in the lower part, but may be in the upper part
		first = mid+1;//set the beginning index to be at mid+1 to avoid searching the lower part.
	 }
	return -1;//if the while loop finishes without finding w, return -1
     }   
    
    void printResult(int ind, int w)
    {
	//print an appropriate message
       
	if (ind >= 0)
	    c.println("The number you wanted,  "+w+ "  appears at position "+ind+ "  in the sorted collection.");
	   else 
	    c.println("The number you wanted,  "+ w+ "  was not found.");
    }
    
    public static void main (String[] args)
    {
	int [] values;//to hold the values to be searched
	int number=0;//to hold the number of values the user wants to enter
	Searches s = new Searches();//a class member to call methods
	int index=0;////variable to hold the index returned by the search method 
	int wanted=0;//variable to hold the value wanted
	int choice = 0;//which search the user wants to do
	
	c.println("How many values do you want to search?");
	number = c.readInt();//read in the number of values to be entered
	values = new int[number];//initialize an array to hold number values.
	s.getValues(values, number);//call the getValues method to read in the values
	
	s.selectSort(values, number);//sort the numbers so that binary search can be done
	c.println("What value do you want to search for?");
	wanted = c.readInt();//read in the value wanted
	
	while (choice != 4)//repeat until the user chooses to quit
	{
	    //show the user the choices
	    c.println("Choose one:");
	    c.println("1.  Linear Search");
	    c.println("2.  Iterative Binary Search");
	    c.println("3.  Recursive Binary Search");
	    c.println("4.  Quit");
	    choice = c.readInt();//read the user's choice
	
	    if (choice == 1)
	    {
		index = s.linearSearch(values, wanted, number);//call the linear search method
		s.printResult(index, wanted);//cll the method to print the result
	    }
	    else if (choice == 2)
	    {
		index = s.binarySearchIterative(values, wanted, 0, number-1);//call the iterative binary search
		s.printResult(index,wanted);//call the print
	    }
	    else if (choice ==3)
	    {
		index = s.binarySearchRecursive(values, wanted, 0, number-1);//call the recursive binary choice
		s.printResult(index,wanted);//call the print
	    }
	
	}
       
	    
		
	
	
	
    } // main method
} // Searches class

