import java.util.*;

public class Arraz {

    public Arraz() {}

    public Integer sumValuesOfArray(Integer[] nums){
        int sum = 0;
        for(Integer i : nums)
            sum += i;
        return sum;
    }
    public Double sumDoublesOfArray(Double[] nums){
        double sum = 0;
        for(Double i : nums)
            sum += i;
        return sum;
    }
    public Integer averageOfArray(Integer[] nums) {
        return sumValuesOfArray(nums)/nums.length;
    }

    public Double doubleAverageOfArray(Double[] numsDbl){
        return sumDoublesOfArray(numsDbl)/numsDbl.length;
    }

    public boolean contains(Integer[] nums, int i){
        for (Integer val : nums)
            if (val == i)
                return true;
        return false;
    }

    public Integer[] reverseArray(Integer[] nums){
        Integer[] rev = new Integer[nums.length];
        for(int i = nums.length-1, j = 0; i >= 0; i--,j++)
            rev[j] = nums[i];
        return rev;
    }

    public String toString(Integer[] nums){
        String str = "ArrayVals: ";
        for(Integer i : nums)
            str += i + " ";
        return str;
    }

    public String toString(ArrayList<Integer>nums){
        String str = "ArrayVals: ";
        for(Integer i : nums)
            str += i + " ";
        return str;
    }

    public OddEven getOddEvensOfArray(Integer[] nums){
        int odds = 0, evens = 0;
         for(Integer i : nums) {
            odds += (i % 2 == 0) ? 1 : 0;
            evens += (i % 2 == 0) ? 0 : 1;
        }
        return new OddEven(odds,evens);
    }

    public int findIndexOf(Object[] objArr, Object val){
        for(int i = 0; i < objArr.length; i++)
            if(objArr[i] == val)
                return i;
        return -1;
    }

    public Integer[] copyArrayByIterator(Integer[] nums){
        Iterator<Integer> itr = Arrays.asList(nums).iterator();
        Integer[] copy = new Integer[nums.length];
        int i = 0;
        while(itr.hasNext())
            copy[i++] = itr.next();
        return copy;
    }

    public Integer[] copyArrayByLoop(Integer[] nums){
        Integer[] copy = new Integer[nums.length];
        for(int i = 0;i < nums.length; i++)
            copy[i] = nums[i];
        return copy;
    }

    public Integer[] removeElementFromArray(Integer[] nums, int val){
         if(contains(nums,val)) {
             Integer[] newArr = new Integer[nums.length - 1];
             int index = 0;
             for (Integer i : nums)
                 if (val != i)
                     newArr[index++] = i;
             return newArr;
         } else
             return nums;
    }

    public Integer[] insertIntoArrayAt(Integer[] nums,Integer index, Integer val) throws IndexOutOfBoundsException{
      try {
          Integer[] newArr = new Integer[nums.length + 1];
          for(int i = 0; i < newArr.length; i++){
              if(i < index)
                  newArr[i] = nums[i];
              else if(index == i)
                  newArr[i] = val;
              else
                  newArr[i] = nums[i-1];
          }
          return newArr;
      } catch (IndexOutOfBoundsException e) {
          e.printStackTrace();
      }
      return nums;
    }

    public MaxMin findMaxMinOfArray(Integer[] nums){
        Integer min = getExtrema(nums)[0];
        Integer max = getExtrema(nums)[1];
        return new MaxMin(min,max);
    }
    public static Integer[] getExtrema(Integer[] nums) {
        int max = nums[0], min = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > max)
                max = nums[i];
            else if (nums[i] < min)
                min = nums[i];
        }
        return new Integer[] {min,max};
    }

    public Integer[] removeDupesFromArray(Integer[] nums) {
        SortedSet<Integer> set = new TreeSet<>(Arrays.asList(nums));
        List<Integer> list = new ArrayList<>(set);
        return list.toArray(new Integer[0]);
    }

    public Integer find2ndLargestValueFromArray(Integer[] nums){
        SortedSet<Integer> set = new TreeSet<>(Arrays.asList(nums));
        List<Integer> list = new ArrayList<>(set);
        return list.get(list.size()-2);
    }

    public ArrayList<Integer> makeMeAnArrayListFromArray(Integer[] nums){
        ArrayList<Integer> list = new ArrayList<>(Arrays.asList(nums));
        return list;
    }

    public Integer[] makeMeAnArrayFromArrayList(ArrayList<Integer> list){
        return list.toArray(new Integer[0]);
    }

    public boolean check2ArraysForEqual(Integer[] arr1, Integer[] arr2) {
        for (int i = 0; i < arr1.length; i++)
            if(arr1[i] != arr2[i])
                return false;
        return true;
    }

    public double averageArrayWithoutMaxMin(Integer[] nums){
        Integer max = findMaxMinOfArray(nums).max;
        Integer[] result = removeElementFromArray(nums, max);
        Integer min = findMaxMinOfArray(result).min;
        Integer[] ouput = removeElementFromArray(result, min);
        return sumValuesOfArray(ouput)/(double)ouput.length;
    }

    public boolean arrayHas65and77(Integer[] nums){
        return (contains(nums, 65) && contains(nums,77));
    }

    public boolean totalOfTensIs30(Integer[] nums){
        int sum = 0;
        for(int i: nums)
            if(i == 10)
                sum++;
        return (sum == 3);
    }

    public Integer find2ndSmallestValueFromArray(Integer[] nums){
        Integer mini = findMaxMinOfArray(nums).min;
        Integer[] noMin = removeElementFromArray(nums, mini);
        return findMaxMinOfArray(noMin).min;
    }

    public Integer[] reverseCopyOfArray(Integer[] nums){
        return reverseArray(nums);
    }

    public Integer[] removeLastItem(Integer[] nums){
        return removeElementFromArray(nums, nums[nums.length - 1]);
    }

    public Integer[] removeFirstItem(Integer[] nums){
        return removeElementFromArray(nums, nums[0]);
    }

    public Integer[] insertAtStart(Integer[] nums, Integer val){
        return insertIntoArrayAt(nums, 0, val);
    }

    public Integer[] insertAtEnd(Integer[] nums, Integer val){
        return insertIntoArrayAt(nums,nums.length, val);
    }

    public Integer[] sortArrayIntoEvensThenOdds(Integer[] nums){
        Integer[] result = new Integer[nums.length];
        Integer front = 0;
        Integer back = nums.length - 1;
        for (int i : nums)
            if(i % 2 == 0)
                result[front++] = i;
            else
                result[back--] = i;
        return result;
    }
}
