【问题标题】:Converting from any base(1-61) to any(1-61) in Haskell在 Haskell 中从任何 base(1-61) 转换为 any(1-61)
【发布时间】:2021-10-22 15:29:08
【问题描述】:

我需要编写一个代码,它将从任何基础转换为任何基础(对于 1 个基础,它是图灵机)。我应该只使用基本库来实现 3 个功能: 1)toDecimal base snumber - 将字符串数字转换为字符串十进制数 2)fromDecimal toBase snumber - 从字符串十进制转换为字符串 1-61 基数 3)convertFromTo fromBase toBase snumber snumber 我做了一些东西,但我不知道如何使用字符串(这是我的第一个问题,如果我做错了什么,抱歉) 这是我写的代码

fromDecimal :: Int ->Int-> String
fromDecimal _ 0 = "" 
fromDecimal toBase snumber = fromDecimal toBase (snumber `div` toBase) ++ ["0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" !! k]  
            where k = snumber `mod` toBase
toDecimal :: Int -> String -> Int
toDecimal base []  = 0
toDecimal base _| base<0 = error "Use positeve base"
toDecimal base snumber = letters (last snumber) + base * toDecimal base (init snumber) 
    where letters :: Char -> Int 
          letters ch
                    | ch == '0' = 0
                    | ch == '1' = 1
                    | ch == '2' = 2
                    | ch == '3' = 3
                    | ch == '4' = 4
                    | ch == '5' = 5
                    | ch == '6' = 6
                    | ch == '7' = 7
                    | ch == '8' = 8
                    | ch == '9' = 9
                    | ch == 'a' = 10
                    | ch == 'b' = 11
                    | ch == 'c' = 12
                    | ch == 'd' = 13
                    | ch == 'e' = 14
                    | ch == 'f' = 15
                    | ch == 'g' = 16
                    | ch == 'h' = 17
                    | ch == 'i' = 18
                    | ch == 'j' = 19
                    | ch == 'k' = 20
                    | ch == 'l' = 21
                    | ch == 'm' = 22
                    | ch == 'n' = 23
                    | ch == 'o' = 24
                    | ch == 'p' = 25
                    | ch == 'q' = 26
                    | ch == 'r' = 27
                    | ch == 's' = 28
                    | ch == 't' = 29
                    | ch == 'u' = 30
                    | ch == 'v' = 31
                    | ch == 'w' = 32
                    | ch == 'x' = 33
                    | ch == 'y' = 34
                    | ch == 'z' = 35
                    | ch == 'A' = 36
                    | ch == 'B' = 37
                    | ch == 'C' = 38
                    | ch == 'D' = 39
                    | ch == 'E' = 40
                    | ch == 'F' = 41
                    | ch == 'G' = 42
                    | ch == 'H' = 43
                    | ch == 'I' = 44
                    | ch == 'J' = 45
                    | ch == 'K' = 46
                    | ch == 'L' = 47
                    | ch == 'M' = 48
                    | ch == 'N' = 49
                    | ch == 'O' = 50
                    | ch == 'P' = 51
                    | ch == 'Q' = 52
                    | ch == 'R' = 53
                    | ch == 'S' = 54
                    | ch == 'T' = 55
                    | ch == 'U' = 56
                    | ch == 'V' = 57
                    | ch == 'W' = 58
                    | ch == 'X' = 59
                    | ch == 'Y' = 60
                    | ch == 'Z' = 61
                    | otherwise = error "Wrong number"

【问题讨论】:

  • 您对“但我不知道如何使用字符串(这是我的第一个问题,如果我做错了什么,抱歉)”到底是什么意思?你到底错过了什么?
  • 另见Haskell functions to extract and reverse integers hiding in strings。 (我在这里和那里有同样的命名抱怨:你的“toDecimal”实际上是“fromDecimal”,反之亦然!(当然,你打算支持的不仅仅是十进制。)
  • “对于 1 个基地,它是图灵机”是什么意思?

标签: haskell base-conversion


【解决方案1】:

StringChars 的列表。您使用了一些函数,如 (++)last,它们在处理列表时效率不高:(++) 在第一个列表的大小上以线性时间工作,last 将在列表。

通常在处理列表时,基本情况是空列表[],以及(x:xs)x 列表的headxs 尾的模式 个列表与 非空 列表匹配。

我们可以定义一个辅助函数go 来枚举列表,并使用一个参数(通常称为累加器)来跟踪迄今为止构造的数字。

对于列表中的每个元素,我们首先将累加器与base 相乘,然后将给定字符的值相加。我们一直这样做,直到到达列表的末尾,在这种情况下,我们返回累加器:

toInt :: Int -> String -> Int
toInt base
    | base <= 0 = error "Invalid base"
    | otherwise = go 0
  where go n [] = n
        go n (x:xs) = go (n * base + letter x) xs

letter :: Char -> Int
letter c
    | '0' <= c && c <= '9' = ord c - ord '0'
    | 'A' <= c && c <= 'Z' = ord c - ord 'A' + 10
    | 'a' <= c && c <= 'z' = ord c - ord 'a' + 36
    | otherwise = error "Invalid character"

对于fromDecimal(也许将其重命名为fromInt),您也可以使用累加器:在这种情况下,您可以使用一个列表,每次都在前面加上一个字符,当您到达0 时该值,您可以返回该累加器。我把它留作练习。

【讨论】:

  • 我会考虑做一个 toLower 或 toUpper 并在分支上消除
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 2021-04-23
  • 2011-01-09
  • 2016-07-07
  • 1970-01-01
  • 2011-05-18
相关资源
最近更新 更多