haskell 有“继续”吗?

ddrv8njm  于 2023-01-05  发布在  其他
关注(0)|答案(2)|浏览(150)

我最近开始学习Haskell,目前正在尝试编写基本的Haskell函数。
我写了一个名为intToRoman的函数,它可以将整数转换为罗马数字,它将整数列表中的数字(1,4,0,0-〉[1,4,0,0])进行除法运算,并将每个数字转换为罗马数字,同时考虑列表的长度,以确定何时是1000或100。
但是,它不会停止并检查零,例如,数字1400将返回:

MCD** Exception: Map.!: given key is not an element in the map
 CallStack (from HasCallStack)

下面是代码本身:

mapInttoRoman:: M.Map Int String
mapInttoRoman = M.fromList
          [(1,"I"),(4,"IV"),(5,"V"),(9,"IX"),(10,"X"),(40,"XL")
          ,(50,"L"),(100,"C"),(400,"CD"),(900,"CM"),(500,"D"),(1000,"M")]

listOfInt :: Int -> [Int]
listOfInt 0 = [ ]
listOfInt c = listOfInt(c`div`10) ++ [c`mod`10]

duplicate :: String -> Int -> String
duplicate string n = concat $ replicate n string

intToRoman :: Int -> String
intToRoman 0 = ""
intToRoman c = createInt x (len-1)
 where x = listOfInt c
       len = length x
       createInt y xz = findRoman (head y) xz ++ createInt(drop 1 y)(xz-1)
        where findRoman b l
               | l < 1      = mapInttoRoman M.! b
               | b == 0     = " "
               | l == 3     = duplicate (mapInttoRoman M.! (10^l)) b
               | b == 1     = mapInttoRoman M.! (10^l)
               | otherwise  = mapInttoRoman M.! (b*10^l)
5fjcxozz

5fjcxozz1#

我认为你使用的算法是不正确的,你使它比它需要的更复杂。
此外,该列表不完整,我添加了90和900例。
看看这个代码..我认为它非常简单,你会很容易得到它。

import qualified Data.Map as M

    mapInttoRoman:: M.Map Int String
    mapInttoRoman = M.fromList
              [(1,"I"),(4,"IV"),(5,"V"),(9,"IX"),(10,"X"),(40,"XL")
              ,(50,"L"),(90,"XC"),(100,"C"),(400,"CD"),(500,"D"),(900,"CM"),(1000,"M")]

    intToRoman :: Int -> String
    intToRoman 0 = ""
    intToRoman n | M.member n mapInttoRoman = mapInttoRoman M.! n
                 | otherwise = val ++ intToRoman (n-key) 
                 where
                    keys = reverse (M.keys mapInttoRoman)
                    key  = maxValidKey n keys
                    val  = mapInttoRoman M.! key
                    maxValidKey n (k:ks) 
                      | n >= k = k
                      | otherwise = maxValidKey n ks

试验:

gkl3eglg

gkl3eglg2#

这个怎么样?解释内嵌。

import qualified Data.List as L

{-
1. Find the floor of 'n' in the mapping, i.e. the highest
   decimal value 'v' that is less than or equal to 'n'.
2. Add the corresponding string to the answer, and subtract
   'v' from 'n'.
3. Repeat until n = 0.

<$> from Functor, fmap
(<$>) :: Functor f => (a -> b) -> f a -> f b

<> from Monoid, mappend
(<>) :: Monoid m => m -> m -> m

>>= from Monad, bind
(>>=) :: m a -> (a -> m b) -> m b
-}
numerals :: Integer -> Maybe String
numerals n
  | n > 3000 || n <= 0 = Nothing
  | otherwise = (snd <$> x) <> (x >>= (\y -> numerals (n - fst y)))
  where
    x = L.find (\(i, _) -> i <= n) xs
    xs =
      [ (1000, "M"),
        (900, "CM"),
        (500, "D"),
        (400, "CD"),
        (100, "C"),
        (90, "XC"),
        (50, "L"),
        (40, "XL"),
        (10, "X"),
        (9, "IX"),
        (5, "V"),
        (4, "IV"),
        (1, "I")
      ]

相关问题