3

学習の目的で、文字列置換関数を考え出そうとしましたが、今私が持っているものは次のとおりです。

let string_replace where what replacement =
  let wlength = (String.length what - 1) in
  let length = (String.length where - 1) in
  let rec loop i shift =
    let [shift, i] =
      if wlength == shift then
        (String.blit replacement 0 where (i - wlength) (wlength + 1); [0, i])
      else if (String.get where i == String.get what shift) then
        [shift + 1, i]
      else [0, i - shift]
    in if i < length then loop (i + 1) shift
  in loop 0 0; where;;

さて、ここにテストがあります: http://raid6.com.au/~onlyjob/posts/arena/で、私が相対的にどのようにやっているかを知りたかったのです。そして、ここで、私はテストを書きました:

let test =
  let initial = "abcdefgh" ^ "efghefgh" in
  let initial_time = Sys.time() in
  let initial_length = String.length initial in
  let imax = (1024 / (String.length initial)) * 1024 * 4 in
  let rec loop s i =
    if i < imax then
      let ns = string_replace (s ^ initial) "efgh" "____" in
      let sl = initial_length * i in
      if (sl mod 1024) * 256 == 0 then
        Printf.printf "%f s | %d Kb |\n" (Sys.time() -. initial_time) (sl / 1024);
      loop ns (i + 1)
  in loop initial 0;;
test;;

結果を比較できるように、JavaScript テストにできる限り厳密に従おうとしました (ここでいくつかの書式設定を行い、検索を省略します)。

function test() {
    var str = "abcdefgh" + "efghefgh",
    imax = 1024 / str.length * 1024 * 4,
    time = new Date(), gstr = "", i = 0, lngth;

    console.log("exec.tm.sec\tstr.length");

    while (i++ < imax + 1000) {
        gstr += str;
        gstr = gstr.replace(/efgh/g, "____");
        lngth = str.length * i;
        if (lngth % 1024 * 256 === 0) {
            var curdate = new Date();
            console.log((curdate.getTime() - time.getTime()) / 1000 +
                        "sec\t\t" + lngth / 1024 + "kb");
        }
    }
}

これが私が得ている結果です...

| JavaScript | OCaml        | String size |
|------------+--------------+-------------|
| 0.78 s     | 14.576784 s  | 256 Kb      |
| 3.266 s    | 58.468111 s  | 512 Kb      |
| 7.618 s    | 132.954788 s | 768 Kb      |
| 13.849 s   | 238.793697 s | 1024 Kb     |
| 46.243 s   | 379.175356 s | 1280 Kb     |
| 86.046 s   | 550.838260 s | 1536 Kb     |

それで、私の質問: 文字列置換関数に特に問題はありますか? それとも、この速度は期待できるものですか? でコードをコンパイルしましたocamlopt


これが私の別の試みです:

let string_index_of where what =
  let length = (String.length where - 1) in
  let pattern = (1 lsl (String.length what + 1)) - 1 in
  let rec loop i j mask =
    if i == length + 1 then (-1)
    else if mask == pattern then i - j
    else if (where.[i]) == (what.[j]) then
      loop (i + 1) (j + 1) ((mask lsl 1) lor 1)
    else loop (i + 1 - j) 0 1
  in loop 0 0 1;;

let test =
  let initial = "abcdefgh" ^ "efghefgh" in
  let replacement = "____" in
  let replacement_length = String.length replacement in
  let initial_time = Sys.time() in
  let initial_length = String.length initial in
  let imax = (1024 / (String.length initial)) * 1024 * 4 in
  let rec loop s i =
    if i < imax then
      let concatenated = s ^ "efgh" in
      let sl = initial_length * i in
      let rec replace_loop st =
        let index = string_index_of st "efgh" in
        if index >= 0 then
          ((String.blit replacement 0 st index replacement_length);
           replace_loop st)
      in replace_loop concatenated;
      if sl mod (1024 * 256) == 0 then
        Printf.printf "%f s | %d Kb |\n" (Sys.time() -. initial_time) (sl / 1024);
      loop concatenated (i + 1)
  in loop initial 0;;

test;;

より大きな表も作成しました(比較のために他の言語をいくつか含めます):

| JavaScript V8 | ocamlopt     | ocamlopt bitup | SBCL      | C gcc 4 -O3 | String size |
|---------------+--------------+----------------+-----------+-------------+-------------|
| 0.78 s        | 14.576784 s  | 4.615298 s     | 17.463 s  | 1 s         | 256 Kb      |
| 3.266 s       | 58.468111 s  | 18.474191 s    | 68.484 s  | 4 s         | 512 Kb      |
| 7.618 s       | 132.954788 s | 41.673664 s    | 153.99 s  | 10 s        | 768 Kb      |
| 13.849 s      | 238.793697 s | 74.652651 s    | 275.204 s | 17 s        | 1024 Kb     |
| 46.243 s      | 379.175356 s | 116.517287 s   | 431.768 s | 27 s        | 1280 Kb     |
| 86.046 s      | 550.838260 s | 166.662663 s   | 624.559 s | 38 s        | 1536 Kb     |

それでも私はこれよりもうまくやりたいと思っています。

4

2 に答える 2

3

あなたの文字列検索は複雑です。より効率的な文字列検索アルゴリズムを試す必要があります (こちらは list です。KMPをお勧めします) 。

あなたは OCaml を初めて使うようです。そこで、あなたが慣れ親しんでいる言語との違いを以下に示します。

  • 構造的等価性をテストする演算子は、物理的等価性をテストするものでは=ありません(違いはありませんが、他のタイプでは問題が発生するためです)。==int
  • タプルはリスト用の(and)ではなく[and]で作成されるため [shift, i]、ペアである 1 つの要素を含むリストも作成されます。そして、Ocaml はこの非網羅的なパターン マッチングについて文句を言っていると思います。
  • String.get s i書くことができますs.[i]
于 2013-07-12T18:25:54.783 に答える