Project Euler – Problem 54

Problem 54:
The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1’s cards and the last five are Player 2’s cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player’s hand is in no specific order, and in each hand there is a clear winner.

How many hands does Player 1 win?

public class Card implements Comparable<Card> {
	byte n,s;
	/**
	 * 
	 * @param n Number
	 * @param s Suit
	 */
	public Card(byte n, byte s){
		this.n = n; this.s = s;
	}
	@Override
	public int compareTo(Card o) {
		if(o.n == this.n)
			return this.s - o.s;
		return this.n-o.n;
	}
 
	public Card clone(){
		return new Card(n,s);
	}
 
	public String toString(){
		return n+" "+s;
	}
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Vector;
 
class runner
{	
	private static byte isSameSuite(Card[] arr){
		byte suit = arr[0].s;
		for(byte i=1; i<arr.length; i++){
			if(suit != arr[i].s)
				return -1;
		}
		return suit;
	}
 
	private static byte consecutiveLowestNumber(Card[] normalized){
		if(normalized.length != 5) return -1;
		Card[] normalizedcopy = new Card[5];
		for(byte i=0; i<normalized.length; i++){
			normalizedcopy[i] = normalized[i];
		}
		Arrays.sort(normalizedcopy);
		if((normalizedcopy[0].n+1 == normalizedcopy[1].n) 
				&& (normalizedcopy[1].n+1 == normalizedcopy[2].n)
				&& (normalizedcopy[2].n+1 == normalizedcopy[3].n)
				&& (normalizedcopy[3].n+1 == normalizedcopy[4].n))
			return normalizedcopy[0].n;
		return -1;
	}
 
	/**
	 * 
	 * @param cards
	 * @return [0] NumberOfDupe [1] Value of Card
	 */
	private static byte[] numOfHighestDuplicate(Card[] cards){
		byte[] arr = new byte[13];
		byte[] result = new byte[2]; 
 
		byte max = 0, highcard = -1;
		for(byte i=0; i<cards.length; i++){
			byte ch = cards[i].n;
			byte y = ++arr[ch];
			if(max < y){
				highcard = ch;
				max = y;
			}else if(max == y){
				if(highcard < ch){
					highcard = ch;
				}
			}
		}
		result[0]=max;result[1]=highcard;
		return result;
	}
 
	private static byte normalizeNumbers(char x){
		if(x=='A') return 12;
		if(x=='K') return 11;
		if(x=='Q') return 10;
		if(x=='J') return 9;
		if(x=='T') return 8;
		return (byte)(x - 50);//48-0, 49-1, 50-2
	}
 
	private static byte normalizeSuit(char x){
		if(x=='S') return 3;
		if(x=='H') return 2;
		if(x=='C') return 1;
		return 0;
	}
 
	private static Card[] normalizeArr(String[] arr){
		Card[] result = new Card[arr.length];
		for(int i=0; i<arr.length;i++){
			result[i] = new Card(normalizeNumbers(arr[i].charAt(0)), normalizeSuit(arr[i].charAt(1)));
		}
		return result;
	}
 
	private static Card[] filterArr(Card[] arr, byte[] filterNum){
		Vector<Card> tmp = new Vector<Card>();
		for(int i=0;i<arr.length;i++){
			boolean found = false;
			for(int j=0;j<filterNum.length;j++){
				if(arr[i].n == filterNum[j]){
					found = true; break;
				}
			}
			if(!found){
				tmp.add(arr[i].clone());
			}
		}
		Card[] result = new Card[tmp.size()];
		for(int i=0; i<result.length; i++){
			result[i] = tmp.get(i);
		}
		return result;
	}
 
	public static boolean winner(String[] raw1, String[] raw2){
		Card[] cards1 = normalizeArr(raw1), cards2 = normalizeArr(raw2);
		return winner_aux(cards1, cards2);
	}
 
	//true is player 1
	public static boolean winner_aux(Card[] cards1, Card[] cards2){
		//Gets the number of duplicates and the card that is being duplicated
		byte[] dupeAndCard1 = numOfHighestDuplicate(cards1), dupeAndCard2 = numOfHighestDuplicate(cards2);
		byte[] filterTripleOrPair1 = {dupeAndCard1[1]}, filterTripleOrPair2 = {dupeAndCard2[1]};
		Card[] leftOverCards1 = filterArr(cards1, filterTripleOrPair1), leftOverCards2 = filterArr(cards2, filterTripleOrPair2);
		byte[] dupeOfLeftOverCards1 = numOfHighestDuplicate(leftOverCards1), dupeOfLeftOverCards2 = numOfHighestDuplicate(leftOverCards2);
 
		if(cards1.length == 5){//they should have the same # of cards
			byte samesuit1 = isSameSuite(cards1), samesuit2 = isSameSuite(cards2);
			byte consecLow1 = consecutiveLowestNumber(cards1), consecLow2 = consecutiveLowestNumber(cards2);
 
			//check for royal flush
			if(consecLow1 == 8 && consecLow2 == 8){
				if(samesuit1 > samesuit2) return true;
				return false;
			}else if(consecLow1 == 8) return true;
			else if(consecLow2 == 8) return false;
 
			//check for Straight Flush
			if(consecLow1 != -1 && consecLow2 != -1 && samesuit1 != -1 && samesuit2 != -1){
				if(consecLow1 == consecLow2){
					if(samesuit1 > samesuit2) return true;
					else return false;
				}else if(consecLow1 > consecLow2) return true;
				return false;
			}else if(consecLow1 != -1 && samesuit1 != -1 ) return true;
			else if(consecLow2 != -1  && samesuit2 != -1 ) return false;
 
			//Check for four of a kind
			if(dupeAndCard1[0] == 4 && dupeAndCard2[0] == 4){
				if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
				else if(dupeAndCard1[1] < dupeAndCard2[1]) return false;
				else{//check for next 'highest card'
					System.out.println("invalid! ");
					return false;
				}
			}else if(dupeAndCard1[0] == 4) return true;
			else if(dupeAndCard2[0] == 4) return false;
 
			//Full House
			if((dupeAndCard1[0] == 3 && dupeOfLeftOverCards1[0] == 2) && (dupeAndCard2[0] == 3 && dupeOfLeftOverCards2[0] == 2)){ //Either have triples.
				if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
				return false;
				//Keep going if it's only a triple.
			}else if(dupeAndCard1[0] == 3 && dupeOfLeftOverCards1[0] == 2) return true;
			else if(dupeAndCard2[0] == 3 && dupeOfLeftOverCards2[0] == 2) return false;
 
 
			//Flush
			if(samesuit1 != -1 && samesuit2 != -1){//Both have flushes... check for high card
				if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
				return false;
			}else if(samesuit1 != -1) return true;
			else if(samesuit2 != -1) return false;
 
			//Straight
			if(consecLow1 > -1 || consecLow2 > -1){
				if(consecLow1 == consecLow2){
					//tie... we should check suit, but Q. does not have that as answer.
					System.out.println("not supposed to get here... straight tie");
				}else if(consecLow1 > consecLow2) return true;
				return false;
			}
		}
 
		if(cards1.length >= 3){
			//Three of a Kind:
			if(dupeAndCard1[0] == 3 &&dupeAndCard2[0] == 3){
				//Full house is out of the equation, just highcard of triple.
				if(dupeOfLeftOverCards1[1] > dupeOfLeftOverCards2[1]) return true;
				return false;
			}else if(dupeAndCard1[0] == 3) return true;
			else if(dupeAndCard2[0] == 3) return false;
		}
 
		if(cards1.length >= 4){
			//Two Pairs: Two different pairs.
			if((dupeAndCard1[0] == 2 && dupeOfLeftOverCards1[0] == 2) && (dupeAndCard2[0] == 2 && dupeOfLeftOverCards2[0] == 2)){
				//both sides have two pair
				if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
				else if(dupeAndCard1[1] < dupeAndCard2[1]) return false;
				else{//they are equal.. check second pair
					if(dupeOfLeftOverCards1[1] > dupeOfLeftOverCards2[1]) return true;
					else if(dupeOfLeftOverCards1[1] < dupeOfLeftOverCards2[1]) return false;
					else{//both pairs are the same.. check highcard... 
						byte[] filterHighCard1 = {dupeAndCard1[1], dupeOfLeftOverCards1[1]}, filterHighCard2 = {dupeAndCard2[1], dupeOfLeftOverCards2[1]};
						Card[] highCard1 = filterArr(cards1, filterHighCard1), highCard2 = filterArr(cards2, filterHighCard2);
						/*if(highCard1[0].n > highCard2[0].n) return true;
						else if(highCard1[0].n < highCard2[0].n) return false;
						else{//same card as well wtf. check highcard suite.
							if(highCard1[0].s > highCard2[0].s) return true;
							return false;
						}*/
						return winner_aux(highCard1, highCard2);
					}
				}
			}else if(dupeAndCard1[0] == 2 && dupeOfLeftOverCards1[0] == 2) return true;
			else if(dupeAndCard2[0] == 2 && dupeOfLeftOverCards2[0] == 2) return false;
		}
 
		if(cards1.length >= 2){
			//Single Pair
			if(dupeAndCard1[0] == 2 && dupeAndCard2[0] == 2){
				if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
				else if(dupeAndCard1[1] < dupeAndCard2[1]) return false;
				else{
					if(dupeOfLeftOverCards1[1] > dupeOfLeftOverCards2[1]) return true;
					else if(dupeOfLeftOverCards1[1] < dupeOfLeftOverCards2[1]) return false;
					else{//two more cards to check.. will need to filter again
						byte[] filterTwoCards1 = {dupeAndCard1[1], dupeOfLeftOverCards1[1]}, filterTwoCards2 = {dupeAndCard2[1], dupeOfLeftOverCards2[1]};
						Card[] lastTwoCards1 = filterArr(cards1, filterTwoCards1), lastTwoCards2 = filterArr(cards2, filterTwoCards2);
						byte[] dupeAndCardOfTwo1 = numOfHighestDuplicate(lastTwoCards1), dupeAndCardOfTwo2 = numOfHighestDuplicate(lastTwoCards2);
						if(dupeAndCardOfTwo1[1] > dupeAndCardOfTwo2[1]) return true;
						else if(dupeAndCardOfTwo1[1] < dupeAndCardOfTwo1[1]) return false;
						else{//one more card to check...
							byte[] filterLastCard1 = {dupeAndCardOfTwo1[1]}, filterLastCard2 = {dupeAndCardOfTwo1[1]};
							Card[] lastCard1 = filterArr(lastTwoCards1, filterLastCard1), lastCard2 = filterArr(lastTwoCards2, filterLastCard2);
							if(lastCard1[0].n > lastCard2[0].n) return true;
							return false;
						}
					}
				}
			}else if(dupeAndCard1[0] == 2) return true;
			else if(dupeAndCard2[0] == 2) return false;
		}
 
		//Single
		if(dupeAndCard1[1] == dupeAndCard2[1]){
			byte[] filterCard1 = {dupeAndCard1[1]}, filterCard2 = {dupeAndCard2[1]};
			Card[] lastCards1 = filterArr(cards1, filterCard1), lastCards2 = filterArr(cards2, filterCard2);
			return winner_aux(lastCards1, lastCards2);
		}else if(dupeAndCard1[1] > dupeAndCard2[1]) return true;
		else return false;
	}
 
 
	public static void testing(String p1, String p2, boolean winner){
		boolean result = winner(p1.split(" "), p2.split(" "));
		System.out.println("Test - P1:"+p1+" P2:"+p2+" Expected:"+winner+" actual:"+result+" \tNet:"+(result==winner));
	}
 
	public static void main (String[] args) throws java.lang.Exception
	{
		long time = System.currentTimeMillis();
 
 
		int c=0;
		try {
		    BufferedReader in = new BufferedReader(new FileReader("http://archiver.joshho.com/display.php?full=1&q=https://projecteuler.net/project/poker.txt"));
		    String str;
		    while ((str = in.readLine()) != null) {
		        String[] cur = str.split(" ");
		        boolean result = winner(Arrays.copyOfRange(cur, 0, 5),Arrays.copyOfRange(cur, 5, cur.length));
		    	System.out.println(str + " " + result);
		        if(result){
		        	c++;
		        }
		    }
		    in.close();
		} catch (IOException e) {
		}
		System.out.println("c:"+c);
 
		System.out.println("time: "+(System.currentTimeMillis() - time));
	}
}


Note: Once again, not my best effort.