Skip to content

Instantly share code, notes, and snippets.

@mattsan
Created November 16, 2012 10:07
Show Gist options
  • Save mattsan/4086135 to your computer and use it in GitHub Desktop.
Save mattsan/4086135 to your computer and use it in GitHub Desktop.
第五回オフラインリアルタイムどう書くの回答例(C++ その2) ref: http://qiita.com/items/aeec54980c454c3719ef
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
// 札の強さ(1〜14)、出せる札の条件を満たしていない場合は0
std::size_t getRank(const std::string& s)
{
static const std::string ranks = " 3456789TJQKA2o";
if((s.size() % 2) != 0)
{
return 0;
}
std::size_t rank = ranks.find(s[1]);
for(std::size_t pos = 3; pos < s.size(); pos += 2)
{
std::size_t r = ranks.find(s[pos]);
if(rank == (ranks.size() - 1))
{
rank = r;
}
else if((r != (ranks.size() - 1)) && (r != rank))
{
return 0;
}
}
return rank;
}
// sの全サブシーケンスをssに格納
void subsequences(const std::string& s, std::vector<std::string>& ss)
{
std::vector<std::string> result;
result.push_back("");
for(std::size_t pos = 0; pos < s.size(); pos += 2)
{
int n = result.size();
for(int i = 0; i < n; ++i)
{
result.push_back(result[i] + s.substr(pos, 2));
}
}
ss.swap(result);
}
// 不適合組み合わせ検出器
struct IsInvalid
{
const std::size_t rank;
const std::size_t size;
IsInvalid(const std::string& s) : rank(getRank(s)), size(s.size()) {}
bool operator () (const std::string& s) const
{
// サイズ(枚数)があってない or 強さが場の札以下
return (s.size() != size) || (getRank(s) <= rank);
}
};
// derimiterで文字列を分割して、分割した個々の文字列をssに格納
void split(const std::string& s, char derimiter, std::vector<std::string>& ss)
{
std::vector<std::string> result;
std::size_t pos;
std::size_t head = 0;
do
{
pos = s.find(derimiter, head);
result.push_back(s.substr(head, pos - head));
head = pos + 1;
} while(pos != std::string::npos);
ss.swap(result);
}
// 文字列の列ssをderimiterを挟んだひとつの文字列に連結、ssが空のばあいは"-"を返す
std::string join(const std::vector<std::string>& ss, const std::string& derimiter)
{
if(ss.size() == 0)
{
return "-";
}
std::vector<std::string>::const_iterator i = ss.begin();
std::string result = *i;
++i;
for(; i != ss.end(); ++i)
{
result += derimiter;
result += *i;
}
return result;
}
// 問題をときます
std::string solve(const std::string& input)
{
std::size_t comma_pos = input.find(',');
// 場と手札に分割
std::string field = input.substr(0, comma_pos);
std::string hands = input.substr(comma_pos + 1);
std::vector<std::string> ss;
subsequences(hands, ss); // 手札でできる組み合わせを全部挙げる
ss.erase(std::remove_if(ss.begin(), ss.end(), IsInvalid(field)), ss.end()); // 不適な組み合わせを削除する
return join(ss, ","); // 連結する
}
// 以下、テストコード
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::string sort_cards(const std::string& s)
{
if(s == "-")
{
return s;
}
std::vector<std::string> ss;
split(s, ',', ss);
for(std::vector<std::string>::iterator i = ss.begin(); i != ss.end(); ++i)
{
std::vector<std::string> sss;
for(std::size_t pos = 0; pos < i->size(); pos += 2)
{
sss.push_back(i->substr(pos, 2));
}
std::sort(sss.begin(), sss.end());
*i = join(sss, "");
}
std::sort(ss.begin(), ss.end());
return join(ss, ",");
}
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);
if(sort_cards(actual) != sort_cards(pattern.expected))
{
++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