Haskell 一副扑克牌的函数(返回手牌值)
Haskell function with deck of playing cards (returning value of hand)
我在复习周,我正在努力为 Haskell 考试准备一份过去的试卷。然而,这个功能是我不太能应付的。
扑克牌的数值表示如下:
'2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A '.
一手牌可以写成字符串,例如“A563Q”。
我需要写一个函数
scoreHand :: [PlayingCardValue] -> Int
这将 return 一手牌的总价值。 'A' 的值为 11。'T'、'J'、'Q' 和 'K' 的值为 10。其他数字有其面值('2' 的值为 2、'3 ' 的值为 3,依此类推)。
所以我应该写这个函数的两个版本。 第一个使用递归,没有库函数或列表理解,第二个相反(a.k.a)使用列表理解,库功能等
我写的是递归的版本,但是我正在纠结另一个
版本.
这是我的递归代码(尽管我使用的是一个库函数,但我最终会弄清楚的)
*
import Data.Char
type PlayingCardValue = Char
scoreHand :: [PlayingCardValue] -> Int
scoreHand [] = 0
scoreHand (x:xs) =
if x > '1' && x < '9'
then digitToInt x + scoreHand (xs)
else if x == 'T' || x == 'J' || x == 'Q' || x == 'K'
then 10 + scoreHand (xs)
else if x == 'A'
then 11 + scoreHand (xs)
else 0 + scoreHand (xs)
*
关于如何不使用递归创建相同的函数有什么想法吗?
首先我认为你可以通过引入一个新函数使代码更优雅:
score :: PlayingCardValue -> Int
score '2' = 2
score '3' = 3
score '4' = 4
score '5' = 5
score '6' = 6
score '7' = 7
score '8' = 8
score '9' = 9
score 'T' = 10
score 'J' = 10
score 'Q' = 10
score 'K' = 10
score 'A' = 11
score _ = 0
现在我们可以计算出单张牌的分数了。如果需要,我们可以使用 digitToInt :: Char -> Int
函数。单卡分数的计算方式也比较干净
接下来我们可以使用递归:
scoreHand :: [PlayingCardValue] -> Int
scoreHand [] = 0
scoreHand (x:xs) = score x + scoreHand xs
如果我们想写一个非递归的,我们可以使用map :: (a -> b) -> [a] -> [b]
, and sum :: Num a => [a] -> a
:
scoreHand :: [PlayingCardValue] -> Int
scoreHand xs = sum (map score xs)
因此,通过使用 map score xs
,我们创建了一个新列表,对于列表 xs
中的每张卡片,我们都有一个包含分数的元素,然后我们 sum
这些值。我们可以通过使用函数组合来更优雅地编写它:
scoreHand :: [PlayingCardValue] -> Int
scoreHand = sum . map score
我在复习周,我正在努力为 Haskell 考试准备一份过去的试卷。然而,这个功能是我不太能应付的。
扑克牌的数值表示如下: '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A '. 一手牌可以写成字符串,例如“A563Q”。
我需要写一个函数 scoreHand :: [PlayingCardValue] -> Int 这将 return 一手牌的总价值。 'A' 的值为 11。'T'、'J'、'Q' 和 'K' 的值为 10。其他数字有其面值('2' 的值为 2、'3 ' 的值为 3,依此类推)。
所以我应该写这个函数的两个版本。 第一个使用递归,没有库函数或列表理解,第二个相反(a.k.a)使用列表理解,库功能等
我写的是递归的版本,但是我正在纠结另一个 版本.
这是我的递归代码(尽管我使用的是一个库函数,但我最终会弄清楚的)
*
import Data.Char
type PlayingCardValue = Char
scoreHand :: [PlayingCardValue] -> Int
scoreHand [] = 0
scoreHand (x:xs) =
if x > '1' && x < '9'
then digitToInt x + scoreHand (xs)
else if x == 'T' || x == 'J' || x == 'Q' || x == 'K'
then 10 + scoreHand (xs)
else if x == 'A'
then 11 + scoreHand (xs)
else 0 + scoreHand (xs)
* 关于如何不使用递归创建相同的函数有什么想法吗?
首先我认为你可以通过引入一个新函数使代码更优雅:
score :: PlayingCardValue -> Int
score '2' = 2
score '3' = 3
score '4' = 4
score '5' = 5
score '6' = 6
score '7' = 7
score '8' = 8
score '9' = 9
score 'T' = 10
score 'J' = 10
score 'Q' = 10
score 'K' = 10
score 'A' = 11
score _ = 0
现在我们可以计算出单张牌的分数了。如果需要,我们可以使用 digitToInt :: Char -> Int
函数。单卡分数的计算方式也比较干净
接下来我们可以使用递归:
scoreHand :: [PlayingCardValue] -> Int
scoreHand [] = 0
scoreHand (x:xs) = score x + scoreHand xs
如果我们想写一个非递归的,我们可以使用map :: (a -> b) -> [a] -> [b]
, and sum :: Num a => [a] -> a
:
scoreHand :: [PlayingCardValue] -> Int
scoreHand xs = sum (map score xs)
因此,通过使用 map score xs
,我们创建了一个新列表,对于列表 xs
中的每张卡片,我们都有一个包含分数的元素,然后我们 sum
这些值。我们可以通过使用函数组合来更优雅地编写它:
scoreHand :: [PlayingCardValue] -> Int
scoreHand = sum . map score