[Haskell-cafe] Substring replacements

Branimir Maksimovic bmaxa at hotmail.com
Mon Dec 12 10:19:45 EST 2005




>From: Daniel Fischer <daniel.is.fischer at web.de>
>To: "Branimir Maksimovic" <bmaxa at hotmail.com>
>CC: Haskell-Cafe at haskell.org
>Subject: Re: [Haskell-cafe] Substring replacements
>Date: Mon, 12 Dec 2005 13:07:29 +0100
>
>Sorry, but
>Prelude SearchRep> searchReplace "abaaba" "##" "abababaaba"
>"abababaaba"
>
>I haven't analyzed the algorithm, so I don't know why exactly this fails.
>I'll take a look sometime soon.

It failed because I didn;t adjusted search string for rollBack when previous 
rollBack is not null.
this is corrected version: (with your changes it looks much better)
-------------------------------------------------------------------------------
searchReplace :: String->String->String -> String
searchReplace "" _ xs  = xs
searchReplace sr rp xs = searchr sr rp xs "" ""
   where
     searchr :: String->String->String->String->String -> String
     searchr _ _ "" _ _ = ""
     searchr sr rp xs retB rollB
        | found     = rp ++ searchr sr rp rema ret roll
	| otherwise = reverse (proc ++ rollB) ++
	              searchr sr rp rema ret roll
	   where
	     (found, proc, rema, ret, roll)
	        = searchr' sr sr (reverse retB ++ xs) "" rollB

     searchr' src@(s:sr) src'@(s':sr') xs soFar rollB
        = searchr'' (drop (length rollB) src) src' xs soFar (not (null 
rollB),"","") s

     searchr'' "" _ xs fnd _ _ = (True,fnd,xs,"","")
     searchr'' _ _ "" fnd (_,ret,roll) _ = (False,ret++roll++fnd,"","","")
     searchr'' src@(s:sr) src'@(s':sr') xxs@(x:xs) soFar (cnt,ret,roll) c
        | s == x = if s' == x && null ret && cnt
	              then searchr'' sr sr' xs soFar (True, "", x:roll) c
		      else
		        if null ret && null roll
			   then searchr'' sr src' xs (x:soFar) (True, "", "") c
			   else searchr'' sr src' xs soFar (True, x:roll++ret, "") c
	| otherwise = if null roll && null ret
	                 then
			    if c == x
			      then (False, soFar, xxs, "", "")
			      else let (from, pre) = break (==c) xs
			           in (False, reverse from ++ x:soFar, pre, "", "")
			  else
			    if s'/=x
                  then if null ret
                       then (False, (x:roll) ++ soFar, xs,"","")
                       else (False, soFar, xxs,ret,"")
                  else if null ret
			           then (False, soFar, xs, "", x:roll)
			           else (False, soFar, xxs, ret, "")
----------------------------------------------------------------------------

However it is significantly slower then previous ugly version:

searchReplace :: String->String->String -> String
searchReplace sr rp xs = searchr sr rp xs "" ""
   where
    searchr :: String->String->String->String->String -> String
    searchr [] _ xs _ _ =  xs
    searchr _ _ [] _ _  = []
    searchr sr rp xs retBack rollBack
                 | isFound $ fnd rollBack = rp
                                      ++ searchr sr rp (remaining $ fnd 
rollBack )
                                                       ( getRetBack $ fnd 
rollBack)
                                                       ( getRollBack $ fnd 
rollBack)
                 | otherwise = reverse ((processed $ fnd rollBack) ++ 
rollBack)
                               ++ searchr sr rp (remaining $ fnd rollBack)
                                                ( getRetBack $ fnd rollBack)
                                                ( getRollBack $ fnd 
rollBack)
                where fnd  = searchr' sr sr (reverse retBack ++ xs) ""

    isFound = fst . fst
    remaining = snd . snd . fst
    getRollBack = snd . snd
    getRetBack = fst . snd
    processed = fst . snd . fst

    searchr' :: String->String->String->String->String
                -> ((Bool,(String,String)),(String,String))
    searchr' srch@(sr:srs) srch'@(sr':srs') xs fndSoFar rollBack =
                           searchr'' (drop (length rollBack) srch) srch' xs 
fndSoFar
                                     (not (isEmpty rollBack),"","") sr

    searchr'' :: String->String->String->String->(Bool,String,String)->Char
             -> ((Bool,(String,String)),(String,String))
    searchr'' [] _ xs fnd _ _  = ((True,(fnd,xs)),("",""))
    searchr'' _ _ [] fnd (_,retBack,rollBack) _ = ((False,(retBack ++ 
rollBack ++ fnd,[])),("",""))
    searchr'' srch@(sr:srs) srch'@(sr':srs') xxs@(x:xs) fndSoFar 
(cnt,retBack,rollBack) s
      | sr == x = if cnt && sr' == x && isEmpty retBack
                     then searchr'' srs srs' xs fndSoFar 
(True,"",x:rollBack) s
                     else if not (isEmpty retBack)  || not (isEmpty 
rollBack)
                             then searchr'' srs srch' xs fndSoFar
                                             (True,(x:rollBack) ++ 
retBack,"") s
                             else searchr'' srs srch' xs (x:fndSoFar) 
(True,"","") s
      | otherwise = if isEmpty rollBack && isEmpty retBack
                       then if s == x
                               then ((False,(fndSoFar,xxs)),("",""))
                               else ((False,searchr''' s xs 
(x:fndSoFar)),("",""))
                       else if sr/=x
                            then if isEmpty retBack
                                 then ((False,((x:rollBack)++fndSoFar, xs)), 
("",""))
                                 else ((False,(fndSoFar, xxs)), 
(retBack,""))
                            else if isEmpty retBack
                                 then ((False,(fndSoFar, xs)), 
("",x:rollBack))
                                 else ((False,(fndSoFar, xxs)), 
(retBack,""))


    searchr''' :: Char->String->String -> (String,String)
    searchr''' sr [] fndSoFar = (fndSoFar,[])
    searchr''' sr xxs@(x:xs) fndSoFar | sr/=x = searchr''' sr xs 
(x:fndSoFar)
                             | otherwise = (fndSoFar,xxs)
    isEmpty [] = True
    isEmpty (a:as) = False
-------------------------------------------------------------------------------
these are timings:

$ time MyBane.exe
Working:seasearch replace  able seaseasearch baker seasearch charlie
True
Done


real    0m19.984s
user    0m0.015s
sys     0m0.016s

bmaxa at MAXA ~/tutorial
$ time searchr.exe
Working:seasearch replace  able seaseasearch baker seasearch charlie
True
Done


real    0m13.719s
user    0m0.015s
sys     0m0.000s

It's 6 seconds difference.
Your KMP is always fastest of all version in any combination on  2gb p4 3ghz
hyperthreaded windows. Same results on linux will be I guess with same 
machine
as I;ve previously tested on linux but some other p4 and results were
proportionally the same.

Greetings, Bane.

_________________________________________________________________
Express yourself instantly with MSN Messenger! Download today it's FREE! 
http://messenger.msn.click-url.com/go/onm00200471ave/direct/01/



More information about the Haskell-Cafe mailing list