// Arup Guha
// 6/23/2015
// Written for SI@UCF Video Lecture on the Java API

import java.util.*;

public class DataStructs {

	// Run our various tests.
	public static void main(String[] args) {
		testArray();
		testSort();
		testArrayList();
		testArrayDeque();
		testHashSet();
		testTreeSet();
		testHashMap();
	}
	
	public static void testArray() {
		
		// Test fill and to String
		Random r = new Random();
		Scanner stdin = new Scanner(System.in);
		int n = stdin.nextInt();
		int[] array = new int[n];
		Arrays.fill(array, 7);
		System.out.println(Arrays.toString(array));
		
		// copyOf
		int[] newarray = Arrays.copyOf(array, 10);
		System.out.println(Arrays.toString(newarray));
		for (int i=0; i<newarray.length; i++)
			newarray[i] = r.nextInt(20) + 1;
		
		// sort
		System.out.println(Arrays.toString(newarray));
		Arrays.sort(newarray);
		System.out.println(Arrays.toString(newarray));		
	}
	
	public static void testSort() {

		// Fill a small class.
		student[] myclass = new student[4];
		myclass[0] = new student("Amy", 6);
		myclass[1] = new student("Sarah", 17);
		myclass[2] = new student("Mark", 27);
		myclass[3] = new student("Amy", 4);
		System.out.println(Arrays.toString(myclass));
		
		// Defined sort for class.
		Arrays.sort(myclass);
		System.out.println(Arrays.toString(myclass));
		
		// If I want to sort in another way...
		Arrays.sort(myclass, new Comparator<student>(){
				public int compare(student a, student b) {
					int idDiff = a.ID - b.ID;
					if (idDiff !=0) return idDiff;
					return a.name.compareTo(b.name);
				}
		});
		System.out.println(Arrays.toString(myclass));
		
	}
	
	public static void testArrayList() {

		// Add/remove stuff to an array list.
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(7);
		list.add(3);
		list.add(17);
		System.out.println(list);
		
		// Removes from an index.
		list.remove(1);
		System.out.println(list);
		list.add(5);
		list.add(16);
		System.out.println(list);
		
		// Removes the item itself.
		list.remove(new Integer(16));
		System.out.println(list);
		
		// One way to iterate through an ArrayList.
		int sum = 0;
		for (Integer x: list)
			sum += x;
		System.out.println(sum);
		
		// Another way to iterate through an ArrayList.
		int sumUnits = 0;
		for (int i=0; i<list.size(); i++)
			sumUnits += (list.get(i)%10);
		System.out.println(sumUnits);
		
		// Third method for iteration.
		Iterator<Integer> myIterator = list.iterator(); // hasNext,next,remove
		int prod = 1;
		while (myIterator.hasNext())
			prod *= myIterator.next();
		System.out.println(prod);
	
		// Fun Collections methods for all Java lists.
		Collections.shuffle(list);
		System.out.println(list);
		Collections.sort(list);
		System.out.println(list);
		Collections.reverse(list);
		System.out.println(list);
	}
	
	public static void testArrayDeque() {

		// add items in both front and back
		ArrayDeque<Integer> myArrayDeque = new ArrayDeque<Integer>();
		myArrayDeque.addFirst(3);
		myArrayDeque.addLast(7);
		myArrayDeque.addFirst(4);
		System.out.println(myArrayDeque);
		
		// Do some removing and some adding.
		System.out.println("removing first in line: "+myArrayDeque.pollFirst());
		System.out.println(myArrayDeque);
		myArrayDeque.addFirst(15);
		myArrayDeque.addFirst(18);
		System.out.println("removing last in line: "+myArrayDeque.pollLast());
		System.out.println(myArrayDeque);
		
		// How to look at front and end without removing.
		System.out.println("first in line but not removed: "+myArrayDeque.peekFirst());
		System.out.println("last in line but not removed: "+myArrayDeque.peekLast());
		System.out.println(myArrayDeque);
		System.out.println("size is "+myArrayDeque.size());
	}
	
	public static void testHashSet() {

		// Add some names.
		HashSet<String> names = new HashSet<String>();
		names.add("John");
		names.add("Mary");
		names.add("Martha");
		names.add("Stewart");
		
		// Test contains and iterator.
		if (names.contains("Mary")) System.out.println("found mary");
		for (String s: names)
			System.out.println(s);
		
		// Show that duplicates don't matter.
		names.add("Mary");
		for (String s: names)
			System.out.println(s);
		
		// You can remove stuff too.
		names.remove("Mary");
		for (String s: names)
			System.out.println(s);	
		System.out.println(names.size());
	}
	
	public static void testTreeSet() {

		// Add stuff.
		TreeSet<String> names = new TreeSet<String>();
		names.add("James");
		names.add("Marnie");
		names.add("Abigail");
		names.add("Samantha");
		names.add("Dave");
		
		// Iterate in order
		for (String s: names)
			System.out.println(s);
		
		// Several methods tested - quite a few more exist.
		System.out.println("first = "+names.first());
		System.out.println("last= "+names.last());
		System.out.println(names.size());
		names.remove("Marnie");
		System.out.println(names.size());
		System.out.println(names.contains("Dave")+" "+names.contains("abigail"));
		String item = names.floor("Harold");
		names.remove(item);
		
		// Show effect.
		for (String s: names)
			System.out.println(s);
	}
	
	public static void testHashMap() {

		// Store each person's number of friends!
		HashMap<String,Integer> numFriends = new HashMap<String,Integer>();
		numFriends.put("Harold", 3);
		numFriends.put("Jessica", 12);
		numFriends.put("Bobby", 3);
		System.out.println(numFriends.get("Jessica"));
		System.out.println(numFriends.get("Harold"));

		Scanner stdin = new Scanner(System.in);
		
		// Pretend that two people add one friend each.
		for (int i=0; i<2; i++) {
			
			// Read from user.
			String name = stdin.next();
		
			// This person's on our list, add 1 to their count.
			if (numFriends.containsKey(name)) {
				int ans = numFriends.get(name);
				numFriends.put(name, ans+1);
			}
			
			// New person, put them in our list with 1 friend.
			else
				numFriends.put(name, 1);
		}
		
		// Show map.
		System.out.println(numFriends);
	
		// How to iterate through keys.
		for (String s: numFriends.keySet())
			System.out.println(s);
	}

}

class student implements Comparable<student> {
	
	public String name;
	public int ID;
	
	public student(String n, int myID) {
		name = n;
		ID = myID;
	}
	
	public int compareTo(student other) {
		int strCmp = name.compareTo(other.name);
		if (strCmp != 0) return strCmp;
		return other.ID - this.ID;
	}
	
	public String toString() {
		return ID+":"+name;
	}
}
