0

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?

2 Answers 2

2

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 js such that f i j > 0, I stored the actual function value. This does no more work due to laziness.

Sign up to request clarification or add additional context in comments.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.