1

I solve different problems in some judging systems. Today I want to calculate Fibonacci numbers with State Monad. My code works well and it pass all my tests. But there is some error (one test is failed), which I can not determine.

My code is:

fib :: Int -> Integer
fib n = fst $ execState (replicateM n fibStep) (0,1)

fibStep :: State (Integer,Integer) ()
fibStep = do modify (\(a, b) -> (b, a + b))

Can you help me to find the error? I don't know, where error is.

Denis
  • 3,595
  • 12
  • 52
  • 86
  • 3
    Well, _what_ is the error? What test fails and in which way? – leftaroundabout Apr 17 '15 at 20:49
  • @leftaroundabout, this judging system does not give me test, which is failed. My code calculate wrong fib number for some `n`. I brute many `n`, but I can not find error. – Denis Apr 17 '15 at 20:51
  • 1
    With this implementation, `fib 1 = 1`. If you need `fib 1 = 0` then you need to `replicateM (n-1) fibStep`. Otherwise this code looks fine. – Mokosha Apr 17 '15 at 20:52
  • Can you link to the description of the problem you are solving, please? (Or include the problem statement from the judge word-for-word here.) – Daniel Wagner Apr 17 '15 at 20:55
  • @Mokosha, `fib 1 = 1` according to definition of fib numbers of this system. – Denis Apr 17 '15 at 20:55
  • @DanielWagner, this is a private system (you do not have access to it). The full task is: "Write a function that computes Fibonacci numbers using State monad.". Also, first 3 lines of my code given from system. Also, there is one test: `fib 7 = 13`. – Denis Apr 17 '15 at 20:57
  • What does the system expect when `fib` is given a negative number as input? – G Philip Apr 17 '15 at 21:05
  • @GPhilip, the system expect `0` in this case. – Denis Apr 17 '15 at 21:06
  • @Denis Perhaps you should correspond with whoever is in charge of the judge. There is not much room to hide a problem in such short code! – Daniel Wagner Apr 17 '15 at 21:07
  • @DanielWagner, I thought about this step. Therefore I created this topic as last chance before contacting with support. – Denis Apr 17 '15 at 21:09
  • The do syntax isn't necessary if you only have one monadic statement :) – Jxek Apr 18 '15 at 12:32

1 Answers1

4

I think your code IS correct, tested using a naive implementation fib0 from here

import Control.Monad.State

fib :: Int -> Integer
fib n = fst $ execState (replicateM n fibStep) (0,1)

fibStep :: State (Integer,Integer) ()
fibStep = do modify (\(a, b) -> (b, a + b))

fib0 0 = 0
fib0 1 = 1
fib0 n = fib0 (n-1) + fib0 (n-2)

I tried:

*Main> map (\x -> fib x - fib0 x) [1..25]

and got

[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

Your function seems to give identical results as expected ones.

thor
  • 21,418
  • 31
  • 87
  • 173