# Evil ScienceA whole load of stuff

31Aug/130

## Project Euler Problem 54

Here's my solution to Project Euler Problem 54, it's written in C Sharp and outputs the winner of each hand and how they won. It can optimised, but is still very fast.

```using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace Euler54b
{
class Program
{
static List<string> Ranks = new List<string>() { "High Card", "One Pair", "Two Pairs", "Three of a Kind", "Straight", "Flush", "Full House", "Four of a Kind", "Straight Flush", "Royal Flush" };

/// <summary>
/// Start Here
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{

int p1HighestCard;
int p2HighestCard;
int p1Hand;
int p2Hand;

int p1win = 0;
int p2win = 0;

string hand;

{
while (!sr.EndOfStream)
{

ProcessHands(hand, out p1Hand, out p2Hand, out  p1HighestCard, out p2HighestCard);

if (p1Hand > p2Hand)
{
p1win++;
Console.WriteLine("    Player 1: {0}", Ranks[p1Hand]);
}
else if (p2Hand > p1Hand | p2HighestCard > p1HighestCard)
{
p2win++;
Console.WriteLine("    Player 1: {0}", Ranks[p2Hand]);
}
else
{
if ( p1HighestCard > p2HighestCard)
{
Console.WriteLine("    Player 1 highest card {0}", GetCard(p1HighestCard));
p1win++;
}
else
{
Console.WriteLine("    Player 2 highest card {0}", GetCard(p2HighestCard));
p2win++;
}
}

Console.WriteLine();

}
}

Console.WriteLine();
Console.WriteLine("Player 1 win: {0} Player 2 win: {1}", p1win, p2win);
}

/// <summary>
/// Build the hand and sort it by rank
/// </summary>
/// <param name="pHand">String containing hand</param>
/// <returns>Generic list of hand</returns>
static List<string> GetHand(string pHand)
{
return pHand.Split(new string[] { " " }, StringSplitOptions.None).OrderBy(c => GetCardValue(c)).ToList();
}

/// <summary>
/// Return a numeric value representing the provided card
/// </summary>
/// <param name="pCard">Card to examine</param>
/// <returns>Numeric value</returns>
static int GetCardValue(string pCard)
{
int result;
int.TryParse(pCard.Substring(0, 1), out result);

if (result == 0)
{
switch (pCard.Substring(0, 1))
{
case "T":
return 9;
case "J":
return 10;
case "Q":
return 11;
case "K":
return 12;
case "A":
return 13;

}
}

return result;
}

/// <summary>
/// Get a string representing a card value from its numeric value
/// </summary>
/// <param name="pValue">Numeric value of card</param>
/// <returns>String value</returns>
static string GetCard(int pValue)
{
if (pValue < 9)
return pValue.ToString();
else
{
switch (pValue)
{
case 9:
return "T";
case 10:
return "J";
case 11:
return "Q";
case 12:
return "K";
case 13:
return "A";
}
}

return "";
}

/// <summary>
/// Process the player hands
/// </summary>
/// <param name="pHands">String representing the player hands</param>
/// <param name="p1Hand">Out variable: the rank of hand 1</param>
/// <param name="p2Hand">Out variable: the rank of hand 2</param>
/// <param name="p1HighestCard">Out variable: highest card in hand 1</param>
/// <param name="p2HighestCard">Out variable: highest card in hand 2</param>
static void ProcessHands(string pHands, out int p1Hand, out int p2Hand, out int p1HighestCard, out int p2HighestCard)
{

List<string> Player1 = GetHand(pHands.Substring(0, 14));
List<string> Player2 = GetHand(pHands.Substring(15, 14));

Console.WriteLine("Player 1: {0}", string.Join(" ", Player1.ToArray()));
Console.WriteLine("Player 2: {0}", string.Join(" ", Player2.ToArray()));

p1Hand = RankHand(Player1, out p1HighestCard);
p2Hand = RankHand(Player2, out p2HighestCard);

if ((p1Hand == p2Hand))
{
while (p1HighestCard == p2HighestCard)
{
p1HighestCard = GetHighestValue(Player1, p1HighestCard);
p2HighestCard = GetHighestValue(Player2, p2HighestCard);
};
}
}

/// <summary>
/// Get the highest value in the hand that occurs before the current highest card
/// </summary>
/// <param name="hand">Hand to examine</param>
/// <param name="pHighestCardIndex">Current highest card</param>
/// <returns></returns>
static int GetHighestValue(List<string> hand, int pHighestCardIndex)
{
//create a list of the cards with an accompanying index of it's value
var vals = from h in hand
select new { card = h, index = GetCardValue(h) };

//if the current highest card is the lowest in the list, then return that.
if (pHighestCardIndex == vals.First().index)
return pHighestCardIndex;
else
//get the last value in the above list that is lower that current highest card
return (from v in vals
where v.index < pHighestCardIndex
select v.index).Last();
}

/// <summary>
/// Rank the provided hand
/// </summary>
/// <param name="pHand">Hand to rank</param>
/// <param name="pHighestValue">Highest value in the hand</param>
/// <returns>The rank of hand</returns>
static int RankHand(List<string> pHand, out int pHighestValue)
{
//check for consecutive values
bool straight = true;
for (int i = 1; i < pHand.Count(); i++)
if (GetCardValue(pHand[i]) - 1 != GetCardValue(pHand[i - 1]))
straight = false;

//check for same suit
bool samesuit = pHand.Select(h => h.Substring(1, 1)).Distinct().Count() == 1;

//is it royal
bool royal = String.Join("", pHand.Select(h => h.Substring(1, 1)).ToArray()) == "TJQKA";

//the current haighest value is the last
pHighestValue = GetCardValue(pHand.Last());

if (samesuit &amp; royal)
return 9;//royal flush
else if (samesuit &amp; straight)
return 8;//straight flush
else if (samesuit)
return 5;//flush
else if (straight)
return 4; //straight

//count the occurences of cards
var c = from h in pHand
group h by h.Substring(0, 1) into g
orderby g.Count()
select new { card = g.Key, cnt = g.Count() };

pHighestValue = GetCardValue(c.Last().card);

if (c.Count() == 5) //all values different
{
pHighestValue = GetCardValue(pHand.Last());
return 0;
}
else if (c.Count() == 4)
{
return 1; //one pair
}
else if (c.Count() == 3)
{
if (c.Last().cnt == 3)
return 3; //three of a kind
else
return 2;//two pairs
}
else
{
if (c.Last().cnt == 4)
return 7;//four of kind
else
return 6;//full house (three of a kind and a pair)
}

}
}
}
```