$30 off During Our Annual Pro Sale. View Details »

needful thing for marriage

needful thing for marriage

Avatar for wonderful-panda

wonderful-panda

May 21, 2014
Tweet

Other Decks in Programming

Transcript

  1. Patience Diff • Bazaar の Diff アルゴリズム • Bram Cohen

    によって書かれた • “Patience” is ソリティア •なんか賢いらしい
  2. Python implementation in Bazaar _patiencediff_py.py http://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/view /head:/bzrlib/_patiencediff_py.py •実質 200 行弱

    •Python 知らなくても割と読める •bzrlib 内には、 C による実装もあり ( たいてい 実際に使われるのはこっち )
  3. // 会場を計算する int Fact(int n) { if (n == 1)

    return 1; else return Fact(n-1)*n; } // フィボナッチを計算する int Fib(int n) { if (n == 0 || n == 1) return 1; else return Fib(n-1)+Fib(n-2); } // 階乗を計算する int Fact(int n) { Assert(n >= 0); if (n>0) return Fact(n-1)*n; return 1; } この2つのテキストを比較してみる
  4. // 会場を計算する int Fact(int n) { if (n == 1)

    return 1; else return Fact(n-1)*n; } // フィボナッチを計算する int Fib(int n) { if (n == 0 || n == 1) return 1; else return Fib(n-1)+Fib(n-2); } // 階乗を計算する int Fact(int n) { Assert(n >= 0); if (n>0) return Fact(n-1)*n; return 1; } まず、同じ行同士をマッチング ただし 2回以上出現する行は 無視する 繰り返し出現するパターンを無視することで、 { や } などのノイズが意図せずマッチして おかしな Diff になることを防ぐことができる
  5. // 会場を計算する int Fact(int n) { if (n == 1)

    return 1; else return Fact(n-1)*n; } // フィボナッチを計算する int Fib(int n) { if (n == 0 || n == 1) return 1; else return Fib(n-1)+Fib(n-2); } // 階乗を計算する int Fact(int n) { Assert(n >= 0); if (n>0) return Fact(n-1)*n; return 1; } マッチング結果から、互いに交差しないもの同士でなる 最大の部分集合を選ぶ → 今回の場合はこの3本 これを導くための手順がソリティア っぽいということで、 Patience Diff と呼ぶ
  6. 1 2 3 4 5 6 7 8 0 1

    2 3 4 5 6 7 8 9 10 11 12 13 14 15 ソリティアっぽいってどういうこと? 重ならない線の組み合わせを選ぶとは、 右側の行番号を左側の順に並べたリスト [9, 4, 5, 13] から、最長の単調増加部分列 [4, 5, 13] を 抽出するということ ( 部分列は連続している必要 はない ) ソリティアっぽいってどういうこと?
  7. その処理を適当な数列に対して実施してみる。 3 5 2 7 1 6 9 4 8

    0 これをカードの束に見立てて、以下の通りに左から順に場に出していき、いくつ かのカードの山を作る。 3 5 1.まず [3] を出して、場に山を一つ作る。 2.次に [5] を出す。場に山がある場合は、各山のてっぺんのカードとこ れから出すカードを比べて、これから出すカードが一番大きければ右 端に新しい山を作り、より大きい数字の山があればその山に乗せる ( 該当する山が複数ある場合は、その中で数字が最小のものを選ぶ ) 今回は場に [3] の山しかないので、 [5] は新しい山になる。 3.場に新しいカードを出した場合は、その時点で左隣の山が何番だった か憶えておく ( 今回は [5]→[3]) 4.次に [2] を出す。山は [3][5] なので、 [3] の山に乗せる。 5.次は [7] を出す。 [7] は新しい山になり、 [7]→[5] の関係が記憶 される。 6.この要領で最後までカードを出すと、右図のような4つの山ができ る。一番右の山のてっぺん [8] からリンクをたどると、 [8, 6, 5, 3] という数列が得られる。 7.得られた数列をひっくり返して、 [3, 5, 6, 8] が求める答え。 2 7 4 1 9 6 8 0
  8. // 会場を計算する int Fact(int n) { if (n == 1)

    return 1; else return Fact(n-1)*n; } // フィボナッチを計算する int Fib(int n) { if (n == 0 || n == 1) return 1; else return Fib(n-1)+Fib(n-2); } // 階乗を計算する int Fact(int n) { Assert(n >= 0); if (n>0) return Fact(n-1)*n; return 1; } これでこの3行が同一行としてマークされたので
  9. // 会場を計算する int Fact(int n) { if (n == 1)

    return 1; else return Fact(n-1)*n; } // フィボナッチを計算する int Fib(int n) { if (n == 0 || n == 1) return 1; else return Fib(n-1)+Fib(n-2); } // 階乗を計算する int Fact(int n) { Assert(n >= 0); if (n>0) return Fact(n-1)*n; return 1; } 残った各ブロックに対して、再帰的に同様の処理を していく
  10. 参考 bramcohen: Patience Diff Advantages http://bramcohen.livejournal.com/73318.html Journal of a Programmer:

    Patience Diff http://bryanpendleton.blogspot.jp/2010/05/patience-diff.html alfedenzo: Patience Diff, a brief summary http://alfedenzo.livejournal.com/170301.html