Reputation: 629
How to code the following pseudo-code in Haskell?
x=0
for (i from 0 to 100):
j=0
while ( f(i,j) >0 ):
x+= f(i,j)
j+=1
(f
some unimportant function.)
I came up with something like this:
a= [x| i<-[0..100], let s = takeWhile (\k-> (f i k > 0)) [0..],
j<- s, let x = f i j ]
Then Sum a
does the work, but I need to compute f i j
two times which is a little bit redundant.
Can this be done with f
computed only once or some better codes that run faster?
Upvotes: 0
Views: 206
Reputation: 4540
For fun the most direct translation I could come up with was:
f i j = 100 - i - j
test x =
foldr (\i ->
foldr (\j g ->
let y = f i j in
if y > 0 then g . (+ y) else id
) id [0..]
) x [0..100]
x = test 0
Or with some helpers:
f i j = 100 - i - j
for :: (Enum i) => i -> i -> (i -> a -> a) -> a -> a
for i1 i2 f x = foldr f x [i1..i2]
while :: i -> (i -> i) -> (i -> Bool) -> (i -> a -> a) -> a -> a
while i s p f x =
foldr (\i g x ->
if p i then g (f i x) else x
) id (iterate s i) x
test =
for 0 100 $ \i ->
while 0 (+ 1) (\j -> f i j > 0) $ \j x ->
x + f i j
x = test 0
Upvotes: 0
Reputation: 21811
Here's a way that only computes f
once for each pair:
inner i = sum $ takeWhile (> 0) $ map (f i) [0..]
x= sum $ map inner [0..100]
I dislike list comprehensions, especially for more complex expressions, so I found your solution difficult to read. The primary difference is that instead of storing a list of j
s such that f i j > 0
, I stored the actual function value. This does no more work due to laziness.
Upvotes: 2