下面我定义了一个函数,它将base-3数字列表转换为相应的数值。例如:
f "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0) = 19
f "12" = 5
f "1202" = 47
f "120221" = 430
这是一个使用理解的定义:
f :: String -> Int
f str = sum (listToFinal (stringToTuples str))
助手功能:
- 1)转换" 201"到" 102"
reverse "str"
- 2)转换" 102"到102
stringToInt :: String -> Int
stringToInt str = read str :: Int
- 3)将102转换为[' 1',' 0',' 2']
intToList :: Int -> [Int]
intToList 0 = []
intToList x = intToList (x `div` 10) ++ [x `mod` 10]
- 4)转换" 201"到[(1,0),(0,1),(2,2)]使用reverse,stringToInt,intToList
stringToTuples :: String -> [(Int,Int)]
stringToTuples str = zip (intToList (stringToInt (reverse str))) [0..]
- 5)将[(1,0),(0,1),(2,2)]转换为[1 * 3 ^ 0,0 * 3 ^ 1,2 * 3 ^ 2]
listToFinal :: [(Int,Int)] -> [Int]
listToFinal list = [ x * (3^y) | (x,y) <- list ]
现在我只想用递归来做(当然,使用基本和库函数)。
一个想法:我正在考虑将列表中的每个元素的头部简单地乘以3 ^(字符串的长度-1)。唯一的问题是,每次递归调用时,三次幂必须减少1,例如给出:
recursive_version "201" = (2 * 3^2) + (0 * 3^1) + (1 * 3^0)
如何实现?
答案 0 :(得分:1)
这是一种更简单的方法;请注意,通过使用foldl
,它只是“隐式”递归。有关信息,digitToInt
将导出Data.Char
。
import Data.Char
import Data.List ( foldl' )
--- horner x xs : the value of polynomial 'xs' at point 'x'
horner :: Int -> [Int] -> Int
horner x = foldl' (\c1 c0 -> c1 * x + c0) 0
-- f s : the integer whose representation in base 3 is string 's'
f :: String -> Int
f = horner 3 . map digitToInt
答案 1 :(得分:0)
当你递归地定义它时,减少长度的自然方法是从头部修剪数组。例如:
base3 x = base3' x 0 where
base3' (d:ds) v = base3' ds $ v + d * 3 ^ length ds
base3' [] v = v