Skip to content

Instantly share code, notes, and snippets.

@mattsan
Created November 13, 2012 14:10
Show Gist options
  • Save mattsan/4065949 to your computer and use it in GitHub Desktop.
Save mattsan/4065949 to your computer and use it in GitHub Desktop.
第五回オフラインリアルタイムどう書くの回答例(C++) ref: http://qiita.com/items/33651c2c9ec1fe7aa285
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iterator>
#include <functional>
//----------------------------------------------------------------------
const std::string ranks(" 3456789TJQKA2o");
const std::string suits("CDHJS");
int char2rank(int c)
{
std::size_t r = ranks.find(c);
if(r != std::string::npos)
{
return r;
}
else
{
return 0;
}
}
char rank2char(std::size_t r)
{
if((0 <= r) && (r < ranks.size()))
{
return ranks[r];
}
else
{
return '-';
}
}
//----------------------------------------------------------------------
struct Card
{
Card() : suit(0), rank(0) {}
Card(int suit, int rank) : suit(suit), rank(char2rank(rank)) {}
bool isValid() const { return (suits.find(suit) != std::string::npos) && (0 <= rank) && (rank < ranks.size()); }
bool operator == (const Card& other) const { return (suit == other.suit) && (rank == other.rank); }
bool operator != (const Card& other) const { return ! (*this == other); }
bool operator < (const Card& other) const { return (suit < other.suit); }
char suit;
std::size_t rank;
};
std::istream& operator >> (std::istream& in, Card& card)
{
char s;
char r;
if((in >> s).good() && (suits.find(s) == std::string::npos))
{
in.putback(s);
card = Card();
return in;
}
if((in >> r).good() && (ranks.find(r) == std::string::npos))
{
in.putback(r);
card = Card();
return in;
}
if(in.good())
{
card = Card(s, r);
}
return in;
}
std::ostream& operator << (std::ostream& out, const Card& card)
{
return out << card.suit << rank2char(card.rank);
}
//----------------------------------------------------------------------
typedef std::vector<Card> Cards;
bool operator == (const Cards& lhs, const Cards& rhs)
{
return std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
bool operator != (const Cards& lhs, const Cards& rhs)
{
return ! (lhs == rhs);
}
std::size_t getRank(const Cards& cards)
{
if(cards.empty())
{
return 0;
}
std::vector<Card>::const_iterator i = cards.begin();
std::size_t rank = i->rank;
++i;
for(; i != cards.end(); ++i)
{
if(rank == (ranks.size() - 1))
{
rank = i->rank;
}
else if((i->rank != (ranks.size() - 1)) && (i->rank != rank))
{
return 0;
}
}
return rank;
}
std::istream& operator >> (std::istream& in, Cards& cards)
{
for(;;)
{
Card card;
in >> card;
if( ! card.isValid())
{
break;
}
cards.push_back(card);
}
return in;
}
std::ostream& operator << (std::ostream& out, const Cards& cards)
{
std::copy(cards.begin(), cards.end(), std::ostream_iterator<Card>(out, ""));
return out;
}
//----------------------------------------------------------------------
struct Combination
{
Combination(const Cards& cards, int n)
{
std::vector<int> v(n);
combination(0, cards.size(), n, cards, 0, v);
}
void combination(int begin, int size, int n, const Cards& cards, int index, std::vector<int>& v)
{
if(n == 0)
{
v[index] = begin;
Cards subset;
for(std::vector<int>::iterator i = v.begin(); i != v.end(); ++i)
{
subset.push_back(cards[*i]);
}
values.push_back(subset);
return;
}
for(int i = 0; i < size - n + 1; ++i)
{
v[index] = begin + i;
combination(begin + i + 1, size - i - 1, n - 1, cards, index + 1, v);
}
}
std::vector<Cards> values;
};
struct Invalid : std::unary_function<Cards, bool>
{
Invalid(std::size_t rank) : rank(rank) {}
bool operator () (const Cards& cards)
{
return getRank(cards) <= rank;
}
std::size_t rank;
};
void filter(int rank, std::vector<Cards>& piles)
{
piles.erase(std::remove_if(piles.begin(), piles.end(), Invalid(rank)), piles.end());
}
//----------------------------------------------------------------------
std::string solve(const std::string& input)
{
std::istringstream iss(input);
Cards field;
Cards hands;
char c;
iss >> field >> c >> hands;
if(hands.empty())
{
return "-";
}
Combination pile(hands, field.size());
filter(getRank(field), pile.values);
if(pile.values.empty())
{
return "-";
}
std::ostringstream oss;
std::vector<Cards>::iterator itr = pile.values.begin();
oss << *itr++;
for(; itr < pile.values.end(); ++itr)
{
oss << ',' << *itr;
}
return oss.str();
}
//----------------------------------------------------------------------
struct Pattern
{
Pattern(const std::string& s) : name(), input(), expected()
{
std::size_t d1 = s.find('¥t');
std::size_t d2 = s.find('¥t', d1 + 1);
if((d1 != std::string::npos) && (d2 != std::string::npos))
{
name = s.substr(0, d1);
input = s.substr(d1 + 1, d2 - d1 - 1);
expected = s.substr(d2 + 1);
}
}
std::string name;
std::string input;
std::string expected;
};
std::vector<std::string> str2VectorOfCards(const std::string& s)
{
std::vector<std::string> result;
if(s == "-")
{
return result;
}
std::istringstream iss(s);
while(iss.good())
{
Cards cards;
iss >> cards;
std::sort(cards.begin(), cards.end());
std::ostringstream oss;
oss << cards;
result.push_back(oss.str());
char c;
iss >> c;
}
std::sort(result.begin(), result.end());
return result;
}
int main(int, char* [])
{
std::ifstream patterns("patterns.tsv");
int count_cases = 0;
int count_failures = 0;
std::string s;
while(std::getline(patterns, s).good())
{
++count_cases;
Pattern pattern(s);
std::string actual = solve(pattern.input);
std::vector<std::string> actuals = str2VectorOfCards(actual);
std::vector<std::string> expecteds = str2VectorOfCards(pattern.expected);
if( ! std::equal(actuals.begin(), actuals.end(), expecteds.begin()))
{
++count_failures;
std::cout << "Failure in " << pattern.name << "¥n"
<< "expected: ¥"" << pattern.expected << "¥"¥n"
<< " actual: ¥"" << actual << "¥"¥n";
}
}
std::cout << "¥nCases: " << count_cases << " Failures: " << count_failures << "¥n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment