searchコマンドをByteStringで書き直すと上手く動かない・・・
countコマンドのRuby版アルゴリズムにHaskell/Pythonも合わせてみた+メモ化に関する疑問 - しんちゃんの日記で頂いたツムジさんのByteStringを使うと速くなるというアドバイスを元に、こちらのベンチマークのコードPython vs Ruby vs Haskell(文字列検索deベンチマーク) - しんちゃんの日記もByteStringに書き換えてみたんですが…
コード
import System.Environment import qualified Data.ByteString.Char8 as B search _ _ empty = [] search (y,x) s ns | B.take (B.length s) ns == s = (y,x):search (y,x + 1) s (B.tail ns) search (y,_) s ns | B.head ns == '\n' = search (y + 1,1) s (B.tail ns) search (y,x) s ns = search (y,x + 1) s (B.tail ns) main = getArgs >>= \args -> B.readFile (args!!0) >>= return.search (1,1) (B.pack (args!!1)) >>= \pos -> putStrLn (args!!0) >> print pos
何故か、空リストしか返さなくなっちゃいました…orz
search関数のパターンマッチにも問題があるみたいで、
search3.hs:4:1: Warning: Pattern match(es) are overlapped In an equation for `search': search (y, _) s ns = ... search (y, x) s ns = ... search (y, x) s ns = ... Linking search3.exe ...
と言う警告が出ます…
何で動かないんだろう?謎だ…
2013年2月19日追記
tanakhさんのアドバイスのお蔭で動くようになりました!!
動くようになったコードはこちら!
import System.Environment import qualified Data.ByteString.Char8 as B search _ _ ns | B.null ns = [] search (y,x) s ns | B.take (B.length s) ns == s = (y,x):search (y,x + 1) s (B.tail ns) search (y,_) s ns | B.head ns == '\n' = search (y + 1,1) s (B.tail ns) search (y,x) s ns = search (y,x + 1) s (B.tail ns) main = getArgs >>= \args -> B.readFile (args!!0) >>= return.search (1,1) (B.pack (args!!1)) >>= \pos -> putStrLn (args!!0) >> print pos
私の環境では
>difftime search pi.dat 7777777
pi.dat
[(298906,35),(517833,1),(517833,2),(517833,3)]
1.4843963s
Python/Rubyに勝てないとコメントで書きましたが、オリジナルの方が、改めてベンチ取り直してみたら4秒とかなり遅かったので、現在の環境で今夜にでもまたベンチ取り直してみます。
2013年2月20日追記
Python vs Ruby vs Haskell(文字列検索deベンチマーク) - しんちゃんの日記をベンチ取り直して更新しましたが、Haskellが両言語に肉薄はするものの、順位は変わりませんでした…orz
通りすがりさんのコードをByteStringに直さないと勝てないかも知れません…