気が散りまくり

デコレートのタイミングでトップレベルの関数であるかメソッドであるかどうかを判断できるかとか、RabbitMQとかQ4Mとか云々とか、OCamlとか、suidperlとか、なんかそういう話題ががんがん流れている中で作業に集中するのは難しいからとりあえずブログに書いた。ブログに書くと一応順を追って解説になるので途中でインタラプトが入っても自分がどこまでやったか思い出しやすい。


最小ハッシュ関数ジェネレータの既知のバグの再現コード。5個のマスに4個の駒を置くパターンの最小ハッシュ。

    r = Resource(5, "X")
    koma1 = r.take("koma1")
    koma2 = r.take("koma2")
    koma3 = r.take("koma3")
    koma4 = r.take("koma4")
    All = And(And(And(koma1, koma2), koma3), koma4)
    s = en_decoder.CppRenderer.get_test(All, {"X": []})
    file("tmp.cpp", "w").write(s)

生成されたデコーダ

    and9 = input_value;
    // And(And(And(Take(Resource(X)), Take(Resource(X))), Take(Resource(X))), Take(Resource(X)))
    and8 = and9 / 2;
    take3 = and9 % 2;
    // And(And(Take(Resource(X)), Take(Resource(X))), Take(Resource(X)))
    and7 = and8 / 3;
    take2 = and8 % 3;
    // And(Take(Resource(X)), Take(Resource(X)))
    take0 = and7 / 4;
    take1 = and7 % 4;
    // Take(Resource(X))
    koma1 = take0;
    // Take(Resource(X))
    koma2 = take1;
    if(koma1 <= koma2) koma2++;
    // Take(Resource(X))
    koma3 = take2;
    if(koma1 <= koma3) koma3++;
    if(koma2 <= koma3) koma3++;
    // Take(Resource(X))
    koma4 = take3;
    if(koma1 <= koma4) koma4++;
    if(koma2 <= koma4) koma4++;
    if(koma3 <= koma4) koma4++;

入力が24のとき、まず2で割られて12と0。それを3で割られて4と0、それを4で割られて1と0。(1, 0, 0, 0)で、すでに駒のあるところは詰められているので(1, 0, 2, 3)に復元されるべき。でも実際には(1, 0, 1, 2)になってしまう。なぜならkoma3とkoma1を比較した時点ではkoma3はkoma1と衝突してないからね。koma2との衝突で隣のマスに移動したときにkoma1と衝突する。だから「隣のマスに移動 (koma3++)」ではなく「空いているマスまで移動」になるべき。


デコーダ直した。むー、PythonC++の両方を吐けるようにということでRenderer.assignとか作って砕いて行ったんだけど、結局のところこういうことのために大きなメソッドを足すことになって回り道だった。PythonC++の両方、っていう発想が間違いだったのかなー。

    def take_decoder(arg_name, node_name, resource_name):
        lines = [
            "for(int i=0; ; i++){",
            "  if(!resource_%(resource_name)s[i]){",
            "    if(!%(node_name)s){",
            "      %(arg_name)s = i;",
            "      break;",
            "    }",
            "    %(node_name)s--;",
            "  }",
            "}",
            "resource_%(resource_name)s[%(arg_name)s] = true;"]
        return [line % locals() for line in lines]

forである必要性がないし。。
エンコーダも同じ問題を抱えているので直す必要がある。


つぶしても つぶしてもなお バグがでる じっと手を見る (だいぶじたらず)

設計がおかしいんだろうか。