第四回オフラインリアルタイムどう書くの解答例(C++)

今回も事後参加。
問題はこちら : http://nabetani.sakura.ne.jp/hena/ord4tetroid/

今回も力技。
けっこう時間かけちゃいました。あり得るパターンを定数で用意しておいてそれらにマッチするかどうかでタイプを識別してます。
`operator <<`はデバッグ用（判定には使ってません）。`operator >>`の実装はかなりテキトーです。

```c++:

#include <string>
#include <sstream>
#include <algorithm>

struct Tetromino
{
    int a, b, c, d;

    void normalize()
    {
        struct Pos
        {
            int x, y;
            Pos(int n) : x(n / 10), y(n % 10) {}
            operator int () const { return x * 10 + y; }
        };
        Pos ap(a), bp(b), cp(c), dp(d);

        int minx = std::min(std::min(ap.x, bp.x), std::min(cp.x, dp.x));
        int miny = std::min(std::min(ap.y, bp.y), std::min(cp.y, dp.y));
        ap.x -= minx; bp.x -= minx; cp.x -= minx; dp.x -= minx;
        ap.y -= miny; bp.y -= miny; cp.y -= miny; dp.y -= miny;
        a = ap; b = bp; c = cp; d = dp;
    }

    bool operator == (const Tetromino& other) const
    {
        return a == other.a && b == other.b && c == other.c && d == other.d;
    }

    bool operator != (const Tetromino& other) const
    {
        return ! (*this == other);
    }
};

std::istream& operator >> (std::istream& in, Tetromino& t)
{
    char c;
    int  p[4];
    in >> p[0] >> c >> p[1] >> c >> p[2] >> c >> p[3];
    std::sort(p, p + 4);
    t.a = p[0]; t.b = p[1]; t.c = p[2]; t.d = p[3];
    return in;
}

std::ostream& operator << (std::ostream& out, const Tetromino& t)
{
    return out << t.a << ", " << t.b << ", " << t.c << ", " << t.d;
}

Tetromino Ls[] = { {00, 01, 02, 12}, {00, 01, 10, 20}, {00, 10, 11, 12}, {01, 11, 20, 21},
                   {00, 01, 11, 21}, {00, 01, 02, 10}, {00, 10, 20, 21}, {02, 10, 11, 12} };
Tetromino Is[] = { {00, 10, 20, 30}, {00, 01, 02, 03} };
Tetromino Ts[] = { {00, 10, 11, 20}, {00, 01, 02, 11}, {01, 10, 11, 21}, {01, 10, 11, 12} };
Tetromino Os[] = { {00, 01, 10, 11} };
Tetromino Ss[] = { {00, 01, 11, 12}, {01, 02, 10, 11}, {01, 10, 11, 20}, {00, 10, 11, 21} };

Tetromino* LsEnd = Ls + 8;
Tetromino* IsEnd = Is + 2;
Tetromino* TsEnd = Ts + 4;
Tetromino* OsEnd = Os + 1;
Tetromino* SsEnd = Ss + 4;

std::string getTetrominoType(const std::string& s)
{
    Tetromino          t;
    std::istringstream iss(s);
    iss >> t;
    t.normalize();

    if(std::find(Ls, LsEnd, t) != LsEnd) return "L";
    if(std::find(Is, IsEnd, t) != IsEnd) return "I";
    if(std::find(Ts, TsEnd, t) != TsEnd) return "T";
    if(std::find(Os, OsEnd, t) != OsEnd) return "O";
    if(std::find(Ss, SsEnd, t) != SsEnd) return "S";

    return "-";
}
```


テスト。いつものようにGoogle Test使ってます。

```c++:


#include <gtest/gtest.h>
#include <string>

std::string getTetrominoType(const std::string& s);

#define test(A, E) ASSERT_EQ(std::string(E), getTetrominoType(A))

TEST(TetrominoTest, test1)
{
    /* #1*/ test("55, 55, 55, 55", "-");
    /* #2*/ test("07, 17, 06, 05", "L");
    /* #3*/ test("21, 41, 31, 40", "L");
    /* #4*/ test("62, 74, 73, 72", "L");
    /* #5*/ test("84, 94, 74, 75", "L");
    /* #6*/ test("48, 49, 57, 47", "L");
    /* #7*/ test("69, 89, 79, 68", "L");
    /* #8*/ test("90, 82, 91, 92", "L");
    /* #9*/ test("13, 23, 03, 24", "L");
    /*#10*/ test("24, 22, 25, 23", "I");
    /*#11*/ test("51, 41, 21, 31", "I");
    /*#12*/ test("64, 63, 62, 65", "I");
    /*#13*/ test("49, 69, 59, 79", "I");
    /*#14*/ test("12, 10, 21, 11", "T");
    /*#15*/ test("89, 99, 79, 88", "T");
    /*#16*/ test("32, 41, 43, 42", "T");
    /*#17*/ test("27, 16, 36, 26", "T");
    /*#18*/ test("68, 57, 58, 67", "O");
    /*#19*/ test("72, 62, 61, 71", "O");
    /*#20*/ test("25, 24, 15, 14", "O");
    /*#21*/ test("43, 54, 53, 42", "S");
    /*#22*/ test("95, 86, 76, 85", "S");
    /*#23*/ test("72, 73, 84, 83", "S");
    /*#24*/ test("42, 33, 32, 23", "S");
    /*#25*/ test("66, 57, 67, 58", "S");
    /*#26*/ test("63, 73, 52, 62", "S");
    /*#27*/ test("76, 68, 77, 67", "S");
    /*#28*/ test("12, 11, 22, 01", "S");
    /*#29*/ test("05, 26, 06, 25", "-");
    /*#30*/ test("03, 11, 13, 01", "-");
    /*#31*/ test("11, 20, 00, 21", "-");
    /*#32*/ test("84, 95, 94, 86", "-");
    /*#33*/ test("36, 56, 45, 35", "-");
    /*#34*/ test("41, 33, 32, 43", "-");
    /*#35*/ test("75, 94, 84, 95", "-");
    /*#36*/ test("27, 39, 28, 37", "-");
    /*#37*/ test("45, 34, 54, 35", "-");
    /*#38*/ test("24, 36, 35, 26", "-");
    /*#39*/ test("27, 27, 27, 27", "-");
    /*#40*/ test("55, 44, 44, 45", "-");
    /*#41*/ test("70, 73, 71, 71", "-");
    /*#42*/ test("67, 37, 47, 47", "-");
    /*#43*/ test("43, 45, 41, 42", "-");
    /*#44*/ test("87, 57, 97, 67", "-");
    /*#45*/ test("49, 45, 46, 48", "-");
    /*#46*/ test("63, 63, 52, 72", "-");
    /*#47*/ test("84, 86, 84, 95", "-");
    /*#48*/ test("61, 60, 62, 73", "-");
    /*#49*/ test("59, 79, 69, 48", "-");
    /*#50*/ test("55, 57, 77, 75", "-");
}
```