3 ms·
> for (int i =0;i<len;i++){ if(lines[i] == "a"){ i+=2; } } I think you made a typo. This doesn't do anything. If that's the case, a functional formulation woul
by wyager 10y ago
> for (int i =0;i<len;i++){ if(lines[i] == "a"){ i+=2; } }
I think you made a typo. This doesn't do anything. If that's the case, a functional formulation would have actually made it quite obvious.
But here's a way to do it in Haskell assuming you didn't make a typo.
f i xs
| i >= len xs = i
| xs ! i == 'a' = f (i+2) xs
| otherwise = f (i+1) xs
There is almost certainly a more elegant way to write your algorithm if I understood what you were trying to do, but here's sort of a "worst case" direct translation.
EDIT:
In response to your edit, a substantially more elegant functional approach looks like
map parse . filter (not . startsWith "a")
I think you ironically chose a task that functional programming is particularly better for.
- hskl 10y ago> map parse . filter (not . startsWith "a") Almost! You have to skip two lines.
- wyager 10y agoTrue. OK, let's start with the OP's goal, not his code (which appears to have been consistently incorrect, conveniently and humorously contradicting his intended point). > The goal is to skip the line after a line starting with the letter "a". OK, so we want the following: ["x", "y", "a", "skip", "z"] -> ["x", "y", "a", "z"] Here's a non-clever but still more elegant (and correct) way: f (x:y:zs) | ('a':_) <- x = x : f zs | otherwise = x : f (y : zs) f zs = zs I guarantee you that there are multiple zippy one-liners that do the same thing, but I'll leave it at that for now. It's already a huge improvement, and does what it purports to!
- uryga 10y ago('a':_) <- x = x : f zs What's the `<- x`for? I know some Haskell and I've never seen that syntax. And `('a':_) = x : f zs` should be enough I think. Also I'm pretty sure each line is supposed to be a string, so it should be `("a":_) = x : f zs` :)
- dllthomas 10y agoThat's pattern-guard syntax. The bits between | and = ("the guard") are tried in turn, and the stuff to the right of the = is done for the first that succeeds. This can also introduce new bindings, although it doesn't here. To do this directly without guards, it'd be: f (x@('a':_):_:zs) = x : f zs f (x:ys) = x : f ys f [] = [] Not obviously better, not obviously worse.
- uryga 10y agoThanks, I get it now! I know how guards work, I've just never seen a construct like `('a':_) <- x` (and misunderstood the task a bit :). My understanding is, that's basically inline do-notation, is that correct?. On a sidenote. I've seen code like `f (x:ys) = x : f ys` many times, for example in definitions of map or filter. It always seemed to me like we're wasting a lot of breath typing that - deconstructing the list with pattern matching, then reassembling it again, slightly changed. I feel like there's a general pattern here that could be factored out, do you know of anything like that?
- dllthomas 10y ago> My understanding is, that's basically inline do-notation, is that correct?. Not really. They're superficially similar, but translate differently. Do-notation desugars `x <- y` to `y >>= \ x -> ...`, whereas the pattern guard is more like 'case y of x -> ...; _ -> ...'. Most importantly, there is not necessarily any monad involved for pattern guards - `5 <- 5` is legitimate. `5 <- 5` is nonsensical in do notation (without some awfully weird instance of `Num`). > On a sidenote. I've seen code like `f (x:ys) = x : f ys` many times, for example in definitions of map or filter. It always seemed to me like we're wasting a lot of breath typing that - deconstructing the list with pattern matching, then reassembling it again, slightly changed. I feel like there's a general pattern here that could be factored out, do you know of anything like that? The general pattern, for map and filter, is a fold. Prelude Test.QuickCheck> let map' f = foldr (\ x -> (f x:)) [] Prelude Test.QuickCheck> let filter' f = foldr (\ x -> if f x then (x:) else id) [] Prelude Test.QuickCheck> quickCheck $ \ (Blind f, xs) -> map f xs == map' f xs +++ OK, passed 100 tests. Prelude Test.QuickCheck> Prelude Test.QuickCheck> quickCheck $ \ (Blind f, xs) -> filter f xs == filter' f xs +++ OK, passed 100 tests.