我在Haskell中为Euler Problem 54创建了一个解析器。除了我的完整文件解析器之外,我的所有解析器都能正常工作。它是一个ReadP
解析器,它将它解析为[(Hand, Hand)]
,我创建了一个Hand类型。它目前将文件解析为[]
。我有源代码:
import Text.ParserCombinators.ReadP as Par
import qualified Data.List as L
import qualified Control.Monad as M
import qualified Data.Map as D
import qualified Control.Applicative as A
data Suit=C|D|H|S deriving (Show, Read, Eq, Ord)
data Card=Card Int Suit deriving (Show, Eq, Ord)
data Hand=Hand [Card] deriving (Show, Eq)
ranks=D.fromList [('2', 2), ('3', 3), ('4', 4), ('5', 5), ('6', 6), ('7', 7), ('8', 8),
('9', 9), ('T', 10), ('J', 11), ('Q', 12), ('K', 13), ('A', 14)]
allPar=readP_to_S
fstPar s=fst . head . (allPar s)
parCard=do
rank <- M.liftM (ranks D.!) get
suit <- M.liftM (read . (:[])) get
return $ Card rank suit
parHand=do
first <-parCard
rest <-M.replicateM 4 (char ' ' >> parCard)
return $ Hand $ first:rest
parFile=do
r<-sepBy (return (,) `M.ap` parHand `M.ap` (char ' ' >> parHand)) (char '\n')
eof --I have tested with and without this line.
return r
当我尝试它时(有和没有eof
)我得到:
λ <*Main>: fstPar parFile `M.liftM` readFile "poker.txt"
[]
注意:我知道ReadP
效率低下,但它是一个小文件,我只想快点。
更新:建议我通过在初始解析后解析eof来尝试它。我已经更新了我的问题以反映这一点,但无论如何都会给出相同的结果。
答案 0 :(得分:2)
ReadP
正在为您提供多个解析,而您正在选择最简单的解析:根本不解析。给定
KC QD 3S 4H 6S 2D 3D 4D 5D AD
AD 5D 4D 3D 2D 6S 4H 3S QD KC
作为输入,通过解析器运行它会产生三个解析:
[ ([],"KC QD 3S 4H 6S 2D 3D 4D 5D AD\nAD 5D 4D 3D 2D 6S 4H 3S QD KC")
, ([(Hand [Card 13 C,Card 12 D,Card 3 S,Card 4 H,Card 6 S],Hand [Card 2 D,Card 3 D,Card 4 D,Card 5 D,Card 14 D])],"\nAD 5D 4D 3D 2D 6S 4H 3S QD KC")
, ([(Hand [Card 13 C,Card 12 D,Card 3 S,Card 4 H,Card 6 S],Hand [Card 2 D,Card 3 D,Card 4 D,Card 5 D,Card 14 D]),(Hand [Card 14 D,Card 5 D,Card 4 D,Card 3 D,Card 2 D],Hand [Card 6 S,Card 4 H,Card 3 S,Card 12 D,Card 13 C])],"")
]
除此之外,您可能想要最后一个,因为它是没有剩余输入的那个。最简单的方法是让你的解析器失败,如果留下任何剩余的输入。幸运的是,这很简单:
fstPar (parFile A.<* eof) `M.liftM` readFile "poker.txt"
也就是说,最后让它运行eof
。请注意,现在poker.txt
在文件末尾不能有新行。编写更多代码来跳过文件末尾的任何数量的空格应该不会太困难。