/* http://projecteuler.net/
 *
 * Problem 54
 * The file, poker.txt, contains one-thousand random hands dealt to two
 * players. How many hands does Player 1 win?
 *
 * Solution by Melkor (Filip Niksic, fniksic@gmail.com)
 *
 **/

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <utility>
#include <algorithm>
#include <functional>
#include <cassert>

using namespace std;

class Card {
public:
    enum Suit_t { NONE, SPADES, HEARTS, DIAMONDS, CLUBS };
private:
    int rank;
    Suit_t suit;
public:
    Card(const string &s) {
	assert(s.size() == 2);
	if (s[0] >= '2' && s[0] <= '9')
	    rank = s[0] - '0';
	else if (s[0] == 'T')
	    rank = 10;
	else if (s[0] == 'J')
	    rank = 11;
	else if (s[0] == 'Q')
	    rank = 12;
	else if (s[0] == 'K')
	    rank = 13;
	else if (s[0] == 'A')
	    rank = 14;
	else
	    rank = -1;
	if (s[1] == 'S')
	    suit = SPADES;
	else if (s[1] == 'H')
	    suit = HEARTS;
	else if (s[1] == 'D')
	    suit = DIAMONDS;
	else if (s[1] == 'C')
	    suit = CLUBS;
	else
	    suit = NONE;
    }
    int get_rank() const {
	return rank;
    }
    Suit_t get_suit() const {
	return suit;
    }
    friend bool operator<(const Card &, const Card &);
};

class Hand {
public:
    enum Comb_t {
	HIGH_CARD, PAIR, TWO_PAIRS, THREE, STRAIGHT,
	FLUSH, FULL_HOUSE, FOUR, STRAIGHT_FLUSH
    };
private:
    vector<Card> cards;
public:
    Hand(const vector<Card> &v) : cards(v) {
	assert(cards.size() == 5);
	sort(cards.begin(), cards.end());
    }
    pair<Comb_t, int> combination() const;
    // straight() returns the highest card if there is a straight, 0
    // otherwise
    int straight() const {
	for (int i = 1; i <= 3; ++i)
	    if (cards[0].get_rank() + i != cards[i].get_rank())
		return 0;
	if (cards[4].get_rank() == cards[0].get_rank() + 4)
	    return cards[4].get_rank();
	else if (cards[0].get_rank() == 2 && cards[4].get_rank() == 14)
	    return 5;
	else
	    return 0;
    }
    bool flush() const {
	for (int i = 1; i <= 4; ++i)
	    if (cards[0].get_suit() != cards[i].get_suit())
		return false;
	return true;
    }
    friend bool operator<(const Hand &, const Hand &);
};

pair<Hand::Comb_t, int> Hand::combination() const {
    vector<int> histogram(15, 0);

    for (int i = 0; i < 5; ++i)
	++histogram[cards[i].get_rank()];

    vector<int> sorted(histogram);
    sort(sorted.begin(), sorted.end(), greater<int>());

    int s = straight();
    bool f = flush();

    if (s && f)
	// straight flush
	return make_pair(STRAIGHT_FLUSH, s);
    else if (sorted[0] == 4) {
	// four of a kind
	if (cards[0].get_rank() == cards[1].get_rank())
	    return make_pair(FOUR, 15 * cards[0].get_rank() + cards[4].get_rank());
	else
	    return make_pair(FOUR, 15 * cards[4].get_rank() + cards[0].get_rank());
    }
    else if (sorted[0] == 3 && sorted[1] == 2) {
	// full house
	if (cards[2].get_rank() == cards[1].get_rank())
	    return make_pair(FULL_HOUSE, 15 * cards[2].get_rank() + cards[3].get_rank());
	else
	    return make_pair(FULL_HOUSE, 15 * cards[2].get_rank() + cards[1].get_rank());
    }
    else if (f) {
	// flush
	int return_value = 0;
	for (int i = 4; i >= 0; --i)
	    return_value = return_value * 15 + cards[i].get_rank();
	return make_pair(FLUSH, return_value);
    }
    else if (s)
	// straight
	return make_pair(STRAIGHT, s);
    else if (sorted[0] == 3 && sorted[1] == 1) {
	// three of a kind
	int return_value = 0;
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 3) {
		return_value = cards[i].get_rank();
		break;
	    }
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 1)
		return_value = return_value * 15 + cards[i].get_rank();
	return make_pair(THREE, return_value);
    }
    else if (sorted[0] == 2 && sorted[1] == 2) {
	// two pairs
	int return_value = 0;
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 2) {
		return_value = return_value * 15 + cards[i].get_rank();
		--i;
	    }
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 1) {
		return_value = return_value * 15 + cards[i].get_rank();
		break;
	    }
	return make_pair(TWO_PAIRS, return_value);
    }
    else if (sorted[0] == 2 && sorted[1] == 1) {
	// a pair
	int return_value = 0;
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 2) {
		return_value = cards[i].get_rank();
		break;
	    }
	for (int i = 4; i >= 0; --i)
	    if (histogram[cards[i].get_rank()] == 1)
		return_value = return_value * 15 + cards[i].get_rank();
	return make_pair(PAIR, return_value);
    }
    else {
	// high card
	int return_value = 0;
	for (int i = 4; i >= 0; --i)
	    return_value = return_value * 15 + cards[i].get_rank();
	return make_pair(HIGH_CARD, return_value);
    }
}

inline bool operator<(const Card &l, const Card &r) {
    return l.get_rank() < r.get_rank();
}

bool operator<(const Hand &l, const Hand &r) {
    return l.combination() < r.combination();
}

int main() {
    ifstream in("poker.txt");
    string h;

    int total = 0;
    for (int i = 0; i < 1000; ++i) {
	vector<Card> h1, h2;
	for (int j = 0; j < 5; ++j) {
	    in >> h;
	    h1.push_back(h);
	}
	for (int j = 0; j < 5; ++j) {
	    in >> h;
	    h2.push_back(h);
	}
	Hand player1(h1), player2(h2);
	if (player2 < player1)
	    // player1 wins
	    ++total;
    }

    cout << total << endl;
	    
    return 0;
}

