第19回オフラインリアルタイムどう書くの参考問題をC++で解く

思いついた解法のうち、短時間で実現可能そうなものを検討しているうちに1時間が経過してしまいました。
[ハイゼンバグ](http://en.wikipedia.org/wiki/Unusual_software_bug)と、条件の勘違いに捕まって実装で2時間ほど。
合計3時間ほどかかりました。

最初に辞書を作っておいて、入力と突き合わせるという乱暴な方法をとっています。


お題は[こちら](http://nabetani.sakura.ne.jp/hena/ord19sanwa/)

```cpp
#include <iostream>
#include <sstream>
#include <vector>
#include <bitset>
#include <algorithm>
#include <iterator>
class Sanwa
{
public:
    static const int UPPER_LIMIT = 120;
    static const int u[][3];

    struct Element
    {
        int e1;
        int e2;
        int e3;
        Element(int e1, int e2, int e3) : e1(e1), e2(e2), e3(e3) {}
    };

    static Sanwa& get()
    {
        static Sanwa sanwa;
        return sanwa;
    }

    const std::vector<Element>& getElements() const
    {
        return elements_;
    }

    const std::vector<std::bitset<400> >& getValues() const
    {
        return values_;
    }

    static std::bitset<400> getValueSet(const Element& e)
    {
        std::bitset<400> result;
        for(int i = 0; i < 19; ++i)
        {
            result.set(e.e1 * u[i][0] + e.e2 * u[i][1] + e.e3 * u[i][2]);
        }
        return result;
    }

private:
    Sanwa()
    {
        for(int e1 = 1; e1 < UPPER_LIMIT; ++e1)
        {
            for(int e2 = e1 + 1; e2 < UPPER_LIMIT; ++e2)
            {
//                この条件要らなかった
//                if((e2 == e1*2) || (e2 == e1*3))
//                {
//                    continue;
//                }
                for(int e3 = e2 + 1; e3 < UPPER_LIMIT; ++e3)
                {
//                    この条件要らなかった
//                    if((e3 == e1*2) || (e3 == e1*3) || (e3 == e2*2) || (e3 == e2*3) || (e3  == e1+e2))
//                    {
//                        continue;
//                    }
                    Element e(e1, e2, e3);
                    elements_.push_back(e);
                    values_.push_back(getValueSet(e));
                }
            }
        }
    }

    Sanwa(const Sanwa&);
    Sanwa& operator = (const Sanwa&);

    std::vector<Element>           elements_;
    std::vector<std::bitset<400> > values_;
};

const int Sanwa::u[19][3] =
{
    { 0,0,1 }, { 0,1,0 }, { 1,0,0 },
    { 0,0,2 }, { 0,2,0 }, { 2,0,0 },
    { 0,1,1 }, { 1,0,1 }, { 1,1,0 },
    { 0,0,3 }, { 0,3,0 }, { 3,0,0 },
    { 0,1,2 }, { 1,0,2 }, { 1,2,0 },
    { 0,2,1 }, { 2,0,1 }, { 2,1,0 },
    { 1,1,1 }
};

std::ostream& operator << (std::ostream& out, const Sanwa::Element& e)
{
    return out << e.e1 << "," << e.e2 << "," << e.e3;
}

struct Includes
{
    const std::bitset<400>& source;

    Includes(const std::bitset<400>& source) : source(source) {}

    bool operator() (const std::bitset<400>& other) const
    {
        return (other & source) == source;
    }
};

static Sanwa& sanwa = Sanwa::get();

std::string solve(const std::string& s)
{
    std::bitset<400> source;
    std::istringstream iss(s);
    while(iss.good())
    {
        int i;
        char separator;
        iss >> i;
        source.set(i);
        iss >> separator;
    }

    std::vector<std::bitset<400> >::const_iterator i = std::find_if(sanwa.getValues().begin(), sanwa.getValues().end(), Includes(source));

    if(i == sanwa.getValues().end())
    {
        return "none";
    }

    if(std::find_if(std::next(i), sanwa.getValues().end(), Includes(source)) != sanwa.getValues().end())
    {
        return "many";
    }

    std::ostringstream oss;
    oss << sanwa.getElements()[std::distance(sanwa.getValues().begin(), i)];
    return oss.str();
}

void test(const std::string& source, const std::string& expected)
{
    std::cout << "source: " << source << ", expected: " << expected << std::flush;

    std::string actual = solve(source);

    if(expected == actual)
    {
        std::cout << " => o" << std::endl;
    }
    else
    {
        std::cout << ", actual: " << actual << " => x" << std::endl;
    }
}

int main(int, char* [])
{
    /*0*/ test( "3,11,12,102,111,120", "1,10,100" );
    /*1*/ test( "10,20,30,35,70", "many" );
    /*2*/ test( "1,5,20,80", "none" );
    /*3*/ test( "1,2,3,4,5,6,7,8,9,10,11,12,13,14", "many" );
    /*4*/ test( "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15", "1,4,5" );
    /*5*/ test( "1,2,3,4,5,6,7,8,9,10,11,12,13,14,17", "none" );
    /*6*/ test( "1,2,3,4,5,6,7,8,9,10,11,12,13,14,18", "1,4,6" );
    /*7*/ test( "5,6,7,8,9,10,11,12,13,14,15,16", "2,5,6" );
    /*8*/ test( "9,10,11,12,13,14,15,16,17,18,19", "4,5,7" );
    /*9*/ test( "11,36,37,45,55,70,71", "1,10,35" );
    /*10*/ test( "92,93,94,95,96,97,98,99", "30,32,33" );
    /*11*/ test( "95,96,97,98,99,100", "many" );
    /*12*/ test( "27,30,34,37,43,44,46,51,57", "10,17,23" );
    /*13*/ test( "6,10,13,17,65,73,76,80", "none" );
    /*14*/ test( "12,19,21,29,85", "none" );
    /*15*/ test( "1,2,8,10,14,23,58,62,64", "none" );
    /*16*/ test( "4,22,25,31,44,50,58,69,71,72,73,77", "none" );
    /*17*/ test( "8,16,26,27,42,53,65,69,81,83,88,99", "none" );
    /*18*/ test( "9,10,23,24,28,33,38,39,58,68,84", "none" );
    /*19*/ test( "11,16,24,26,88", "none" );
    /*20*/ test( "24,33,47,56,63,66,75,78,89,93", "none" );
    /*21*/ test( "7,26,72,77", "many" );
    /*22*/ test( "69,88,95,97", "many" );
    /*23*/ test( "9,14,48,89", "many" );
    /*24*/ test( "69,76,77,83", "many" );
    /*25*/ test( "11,14,24", "many" );
    /*26*/ test( "8,25,75,93", "many" );
    /*27*/ test( "11,55,93,98,99", "many" );
    /*28*/ test( "71,83,87", "many" );
    /*29*/ test( "22,76,77,92", "7,15,62" );
    /*30*/ test( "33,61,66,83,95", "17,33,61" );
    /*31*/ test( "6,16,49,55,72", "6,16,33" );
    /*32*/ test( "62,85,97,98", "12,25,73" );
    /*33*/ test( "54,60,67,70,72", "20,25,27" );
    /*34*/ test( "54,61,68,84,87", "27,30,34" );
    /*35*/ test( "65,67,69,75,79,89,99", "21,23,33" );
    /*36*/ test( "69,72,80,81,89", "23,24,33" );
    /*37*/ test( "1,2,3", "many" );

    return 0;
}
```