Yuki2222
Yuki2222

Reputation: 33

decimal integer to Base4 string Haskell

I'm trying to convert an integer from decimal integer to a string based on base 4, but my unfoldr doesn't work and I'm not sure why or how to replace it. I can't use imports either. Please help me fix this.

dec2Base4 :: Int -> String
dec2Base4 = map i2c . reverse . unfoldr decomp
    where
    decomp n = if n == 0 then Nothing else Just(n `mod` 4, n `div` 4)
    i2c i = if i == 0 then '0' else if i == 1 then '1' else if i == 2 then '2' else '3'

Example: dec2Base4 10-> "22"

Upvotes: 1

Views: 203

Answers (1)

jpmarinier
jpmarinier

Reputation: 4733

Your code is basically OK, but it would need you to import the unfoldr function from the Data.List package.

The fact that you are banned from using import clauses might just mean that the powers that be want you to use plain recursion.

A recursion-based solution:

Unfortunately, recursion will naturally produce the least significant digit (rightmost digit) first, because this rightmost digit is essentially mod n 4. You will have to use the reverse function to correct that, just like in your library-based code.

For example, without the help of any non-Prelude library functions, the dec2Base4 function can be written like this:

dec2Base4 :: Int -> String
dec2Base4 n
    |  (n < 0)    =  '-' : (reverse (auxStr (-n)))
    |  (n == 0)   =  "0"
    |  otherwise  =  reverse (auxStr n)  -- when n > 0
  where
    i2c i     =  "0123" !! i
    auxStr 0  =  ""
    auxStr n  =  let  (q,r) = (divMod n 4)  in  (i2c r) : (auxStr q)

Testing code:

unitTest :: Int -> IO ()
unitTest n = do
    let res = dec2Base4 n
    putStrLn $ "Result for " ++ (show n) ++ " is: " ++ res

main = do
    let  testList = [0,11,2051,-2051]
    mapM_  unitTest  testList

Test program output:

Result for 0 is: 0
Result for 11 is: 23
Result for 2051 is: 200003
Result for -2051 is: -200003

Upvotes: 1

Related Questions