десятичное целое число в строку Base4 Haskell

Я пытаюсь преобразовать целое число из десятичного целого числа в строку на основе 4, но мой unfoldr не работает, и я не уверен, почему и как его заменить. Я тоже не могу использовать импорт. Пожалуйста, помогите мне исправить это.

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'

Пример: dec2Base4 10-> "22"


person Yuki2222    schedule 20.04.2021    source источник
comment
Работает на меня. Что идет не так для вас?   -  person Daniel Wagner    schedule 20.04.2021
comment
вам разрешено использовать iterate? scanl? unfoldr может быть реализован с точки зрения обоих (или с прямой рекурсией). scanl можно реализовать с точки зрения zip и map...   -  person Will Ness    schedule 20.04.2021
comment
meta: если у вас несколько аккаунтов, вы можете попросить модераторов объединить аккаунты в один. (Я не уверен в точной процедуре).   -  person Will Ness    schedule 20.04.2021
comment
Вы можете начать с вспомогательной строки, полученной с помощью рекурсии: let { auxStr 0 = "" ; auxStr n = let (q,r) = divMod n 4 in (i2c r) : (auxStr q) }   -  person jpmarinier    schedule 20.04.2021


Ответы (1)


Ваш код в основном в порядке, но вам потребуется импортировать ссылку unfoldr из пакета Data.List.

Тот факт, что вам запрещено использовать пункты import, может просто означать, что сильные мира сего хотят, чтобы вы использовали простую рекурсию.

Решение на основе рекурсии:

К сожалению, рекурсия естественным образом сначала выдает наименее значащую цифру (самую правую цифру), потому что эта самая правая цифра по существу mod n 4. Вам нужно будет использовать функцию reverse, чтобы исправить это, как и в вашем библиотечном коде.

Например, без помощи каких-либо библиотечных функций, отличных от Prelude, функцию dec2Base4 можно записать так:

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)

Тестовый код:

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

Вывод тестовой программы:

Result for 0 is: 0
Result for 11 is: 23
Result for 2051 is: 200003
Result for -2051 is: -200003
person jpmarinier    schedule 20.04.2021
comment
с хвостовой рекурсией нет необходимости реверсировать. рассмотреть auxStr n acc = let (q,r) = (divMod n 4) in auxStr q (i2c r : acc). :) - person Will Ness; 21.04.2021