我坚持使用haskell输入

时间:2014-03-09 17:41:10

标签: haskell input io

我是haskell的新手,我有一个任务,包括将一个字符串解析成一个树并用它做一些垃圾。 我刚刚完成(现在一切都功能正常)但是当我完成开发时,我一直在使用静态字符串定义,而不是每次输入输入。

这是一个示例输入。 ex1 =“C1,8R1 + 4; R3-4C2C7 + 4; R5R2-3C1-6 + 3; R2-3C6 + 2;”

我需要做的最后一件事是处理用户输入(输入应该来自标准输入,而不是某些定义)。 我不仅不知道如何获得输入,而是因为haskell的本质,我开始认为我已经被王室搞砸了。我的意思是,似乎整个语言只是嵌套语句中的嵌套语句,具有递归嵌套语句,依此类推。这对我来说是一个混乱的混乱。我甚至不确定要问什么...到目前为止,我尝试获取用户输入意味着我需要开始将输入作为参数投入整个程序中的每个函数,以便进行编译。 有什么办法可以将用户输入转换为如上所述的定义吗?或者甚至只是用全局字符串变量作弊?我很绝望:(谢谢。

我知道发布我的整个节目可能很糟糕,但我觉得我需要这样才能展示这一切是如何交织在一起的,让我们很难弄清楚如何继续。

实际使用ex1定义的函数createNodeContentList(靠近底部)。

import Text.Regex.Posix
import Data.List.Split

ex1 = "C1,8R1+4;R3-4C2C7+4;R5R2-3C1-6+3;R2-3C6+2;"

treePat = "(([RC][0-9]*[,-]?[0-9]*)*[+][0-9]*;)"
rangePat = "([RC][0-9]*[-][0-9]*)"
nodePat = "([RC][0-9,-]*)"

breakIntoInputTrees x = endBy ";" x
breakIntoInputNodes x = getAllTextMatches $ x =~ nodePat :: [String]

data NodeContent = NodeContent { idy::Char, vals::[Int] } deriving (Show)
data Tree = Node { content::NodeContent, children::[Tree]} deriving (Show)
data GridMod = GridMod { rows::[Int], cols::[Int], mod::[Int] } deriving (Show)
data Path = Path { pathSum::Int, corner::[Char] } deriving (Show, Eq, Ord)

go = printCornerNames $ maxOfMinPaths (maxOfMinValues 0 listOfMinPaths) listOfMinPaths

printCornerNames pathList = putStrLn $ unwords [ corner path | path <- pathList ]

maxOfMinPaths max [] = []
maxOfMinPaths max (h:t) = if (pathSum h == max) 
                            then h:maxOfMinPaths max t
                            else maxOfMinPaths max t

maxOfMinValues max [] = max
maxOfMinValues max (h:t) = if (pathSum h > max) 
                            then maxOfMinValues (pathSum h) t 
                            else maxOfMinValues max t 

listOfMinPaths = findMinimums finalArray

findMinimums array = [quadMinPath array center 0 rMod cMod | rMod <- [-1,1], cMod <- [-1,1]] 

quadMinPath array (r,c) sum rMod cMod
    | isCorner (r,c)    = Path (sum + (posVal array r c)) (cornerName (r,c))
    | otherwise         = decidePaths array (r,c) sum rMod cMod

decidePaths array (r,c) sum rMod cMod
    | (validRow (r + rMod) && validCol (c + cMod)) =
        minimum     [   
                        quadMinPath array (r + rMod, c) (sum + (posVal array r c)) rMod cMod,
                        quadMinPath array (r, c + cMod) (sum + (posVal array r c)) rMod cMod
                    ]
    | (validRow (r + rMod)) = quadMinPath array (r + rMod, c) (sum + (posVal array r c)) rMod cMod
    | otherwise = quadMinPath array (r, c + cMod) (sum + (posVal array r c)) rMod cMod

posVal array r c = array !! (toIndex r c)

isCorner x = elem x [(1,1), (1,cMax), (rMax,1), (rMax,cMax)]

cornerName x    | x == (1,1) = "TOP-LEFT" | x == (1,cMax) = "TOP-RIGHT" 
                | x == (rMax,1) = "BOTTOM-LEFT" | x == (rMax,cMax) = "BOTTOM-RIGHT"

validRow r = if (r >= 1 && r <= rMax) then True else False
validCol c = if (c >= 1 && c <= cMax) then True else False

rMax = fst findMaximums
cMax = snd findMaximums

center = (quot (fst findMaximums) 2 + 1, quot (snd findMaximums) 2 + 1)

finalArray = modifyArray (createArray findMaximums) (toModifiers createGridModders)

modifyArray array [] = array
modifyArray array ((r,c,m):t) = modifyArray (addToArray array (toIndex r c) m) t

addToArray array index mod = (take index array) ++ [(mod + array !! index)] ++ (drop (index + 1) array)

toIndex r c = (r - 1) * (snd findMaximums) + c - 1

createArray (maxR,maxC) = (take (maxR * maxC)) (repeat 0)

printArray array =  mapM_ putStrLn [ printRow row | row <- (chunksOf (snd findMaximums) array)]
printRow row = unwords (map show row)

toModifiers gridModders = flat [ toModifier gw | gw <- gridModders ]

toModifier (GridMod r c m) = [ (x,y,head m) | x <- r, y <- c]

createGridModders = adjustForMaximums (treeWalk (GridMod [] [] []) buildAllTrees)

adjustForMaximums gridMods = [ fillMax gm findMaximums | gm <- gridMods ] 

fillMax (GridMod [] [] m) (maxR,maxC) = (GridMod [1..maxR] [1..maxC] m)
fillMax (GridMod [] c m) (maxR,maxC) = (GridMod [1..maxR] c m)
fillMax (GridMod r [] m) (maxR,maxC) = (GridMod r [1..maxC] m)
fillMax (GridMod r c m) (maxR,maxC) = (GridMod r c m)

treeWalk (GridMod r c m) (Node (NodeContent 'R' v) []) = [(GridMod v c m)]
treeWalk (GridMod r c m) (Node (NodeContent 'C' v) []) = [(GridMod r v m)]
treeWalk (GridMod r c m) (Node (NodeContent 'M' v) []) = [(GridMod r c v)]
treeWalk (GridMod r c m) (Node (NodeContent 'R' v) ch) =  flat [ (treeWalk (GridMod v c m) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'C' v) ch) =  flat [ (treeWalk (GridMod r v m) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'M' v) ch) =  flat [ (treeWalk (GridMod r c v) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'Z' v) ch) =  flat [ (treeWalk (GridMod r c m) tree) | tree <- ch ]

flat [] = []
flat (h:t) = h ++ flat t

findMaximums = (oddify(findMaxRows buildAllTrees), oddify(findMaxCols buildAllTrees))

oddify num = num + ((Prelude.mod num 2) - 1) * (-1)

findMaxRows (Node (NodeContent 'R' v) []) = maximum v
findMaxRows (Node (NodeContent _ _) []) = 0
findMaxRows (Node (NodeContent 'R' v) c) = maximum (v ++ [ findMaxRows x | x <- c ])
findMaxRows (Node (NodeContent _ _) c) = maximum [ findMaxRows x | x <- c ]

findMaxCols (Node (NodeContent 'C' v) []) = maximum v
findMaxCols (Node (NodeContent _ _) []) = 0
findMaxCols (Node (NodeContent 'C' v) c) = maximum (v ++ [ findMaxCols x | x <- c ])
findMaxCols (Node (NodeContent _ _) c) = maximum [ findMaxCols x | x <- c ]

buildAllTrees = Node (NodeContent 'Z' []) (buildIntoTrees (createNodeContentList))

buildIntoTrees x = [ buildIntoTree treeNodeContentList | treeNodeContentList <- x ]

buildIntoTree (h:t) = Node h [ buildSubTree subList | subList <- (easyList t) ]

buildSubTree (h:t) = Node h [ Node content [] | content <- t ]

easyList nodeContentList = tail (simplifyNodeList (idy (head nodeContentList)) nodeContentList [] [])

simplifyNodeList identity [] fullList nextList = fullList ++ [nextList]
simplifyNodeList identity (h:t) fullList nextList = if (idy h == identity)
                                                        then simplifyNodeList identity t (fullList ++ [nextList]) [h]
                                                        else simplifyNodeList identity t fullList (nextList ++ [h])

createNodeContentList = [ tupleTreeToNodeContentList tupleTree | tupleTree <- (parseToListOfTupleTrees ex1)]

parseToListOfTupleTrees input = [ toTupleTree x | x <- breakIntoInputTrees input]

toTupleTree x = ('M', [modifier x]):[ createTupleNode y | y <- breakIntoInputNodes x]

modifier x = read (last (splitOn "+" x )) :: Int

createTupleNode nodeStr = (head nodeStr, getNodeNumbers nodeStr)

getNodeNumbers nodeStr = if (nodeStr =~ rangePat :: Bool)
                    then extractRange (onlyNumbers nodeStr)
                    else onlyNumbers nodeStr

onlyNumbers str = toInt (words (replaceNonDigit str))

extractRange numList = [head numList .. last numList]

replaceNonDigit [] = []
replaceNonDigit ('R':t) = ' ':replaceNonDigit t
replaceNonDigit ('C':t) = ' ':replaceNonDigit t
replaceNonDigit ('-':t) = ' ':replaceNonDigit t
replaceNonDigit (',':t) = ' ':replaceNonDigit t
replaceNonDigit (h:t) = h:replaceNonDigit t

toInt :: [String] -> [Int]
toInt = map read

tupleTreeToNodeContentList x = [ tupleNodeToNodeContent tupleNode | tupleNode <- x ]

tupleNodeToNodeContent x = NodeContent (fst x) (snd x)

3 个答案:

答案 0 :(得分:3)

我将使用一个小小的玩具示例来了解这个想法。

您的代码中是否引用了ex1?改为使用参数。

如果您的代码中充斥着对ex1的引用,那么还有一些工作要做。例如,如果你有

ex1 = "some sample input"
theWords = words ex1
wordLengths = [length word| word <- thewords]

然后你需要为每个函数添加一个额外的参数,这样你就可以在任何输入中使用它,而不仅仅是ex1

ex1 = "some sample input"
getWords input = words input
wordLengths thewords = [length word | word <- thewords]

您可能会发现这样做会稍微简化代码:

getWordLengths input = [length word | word <- words input]

如何通过功能有用地使用用户输入

假设您已经创建了一个对用户输入进行操作的函数,因此函数类型为String -> SomethingOrOther。以下是如何与用户进行交互的示例:

main = do
   putStrLn "Please enter your thingumybob"
   input <- getLine
   putStrLn "Your answer is"
   print (getWordLengths input)

这是一个相当简短的例子,但希望能够让你至少开始。

了解更多

有关此主题的更多帮助,请阅读Input and Output Chapter

Learn You a Haskell for Great Good

答案 1 :(得分:3)

下次,请记住,当你有像

这样的东西时
  

我的作业涉及将字符串解析为树

然后你立即开始写:

assignment :: String -> Tree

您可以从一个将任何字符串映射到空树的函数开始:

assignment input = empty   -- or whatever produces an empty tree

你准备好第一次试运行了:

main = interact (show . assignment)

现在,您需要做的就是优化assignment功能!

答案 2 :(得分:0)

感谢您的回复。 我通过将结构更改为稍微模块化来修复我的程序(上面)。 以前,它基本上只是一个函数链调用函数调用函数等等。我已经改变它,以便代码的不同部分负责创建解决方案的不同步骤,然后将其用作下一部分的参数。 最终,该计划是相同的,只是分解更多。

import Text.Regex.Posix
import Data.List.Split

main = do
    putStrLn "Enter the string representation of a tree:"
    input <- getLine
    let nodeContentList = createNodeContentList input
    let finalTree = buildAllTrees nodeContentList
    let maximums = findMaximums finalTree
    let gridModders = createGridModders finalTree maximums
    let finalArray = buildArray gridModders maximums
    let listOfPaths = findListOfMinPaths finalArray maximums
    showMaxOfMins listOfPaths

treePat = "(([RC][0-9]*[,-]?[0-9]*)*[+][0-9]*;)"
rangePat = "([RC][0-9]*[-][0-9]*)"
nodePat = "([RC][0-9,-]*)"

breakIntoInputTrees x = endBy ";" x
breakIntoInputNodes x = getAllTextMatches $ x =~ nodePat :: [String]

data NodeContent = NodeContent { idy::Char, vals::[Int] } deriving (Show)
data Tree = Node { content::NodeContent, children::[Tree]} deriving (Show)
data GridMod = GridMod { rows::[Int], cols::[Int], mod::[Int] } deriving (Show)
data Path = Path { pathSum::Int, corner::[Char] } deriving (Show, Eq, Ord)

showMaxOfMins listOfPaths = printCornerNames $ maxOfMinPaths (maxOfMinValues 0 listOfPaths) listOfPaths

printCornerNames pathList = putStrLn $ unwords [ corner path | path <- pathList ]

maxOfMinPaths max [] = []
maxOfMinPaths max (h:t) = if (pathSum h == max) 
                            then h:maxOfMinPaths max t
                            else maxOfMinPaths max t

maxOfMinValues max [] = max
maxOfMinValues max (h:t) = if (pathSum h > max) 
                            then maxOfMinValues (pathSum h) t 
                            else maxOfMinValues max t 

findListOfMinPaths array maximums = findMinimums array maximums

findMinimums array maximums = [quadMinPath array (center maximums) 0 rMod cMod maximums | rMod <- [-1,1], cMod <- [-1,1]] 

quadMinPath array (r,c) sum rMod cMod maximums
    | isCorner (r,c) maximums   = Path (sum + (posVal array r c maximums)) (cornerName (r,c) maximums)
    | otherwise                 = decidePaths array (r,c) sum rMod cMod maximums

decidePaths array (r,c) sum rMod cMod maximums
    | (validRow (r + rMod) maximums && validCol (c + cMod) maximums) =
        minimum     [   
                        quadMinPath array (r + rMod, c) (sum + (posVal array r c maximums)) rMod cMod maximums,
                        quadMinPath array (r, c + cMod) (sum + (posVal array r c maximums)) rMod cMod maximums
                    ]
    | (validRow (r + rMod) maximums) = quadMinPath array (r + rMod, c) (sum + (posVal array r c maximums)) rMod cMod maximums
    | otherwise = quadMinPath array (r, c + cMod) (sum + (posVal array r c maximums)) rMod cMod maximums

posVal array r c maximums = array !! (toIndex r c maximums)

isCorner x maximums = elem x [(1,1), (1,cMax maximums), (rMax maximums,1), (rMax maximums,cMax maximums)]

cornerName x maximums   | x == (1,1) = "TOP-LEFT" | x == (1,cMax maximums) = "TOP-RIGHT" 
                        | x == (rMax maximums,1) = "BOTTOM-LEFT" | x == (rMax maximums,cMax maximums) = "BOTTOM-RIGHT"

validRow r maximums = if (r >= 1 && r <= (rMax maximums)) then True else False
validCol c maximums = if (c >= 1 && c <= (cMax maximums)) then True else False

rMax maximums = fst maximums
cMax maximums = snd maximums

center maximums = (quot (fst maximums) 2 + 1, quot (snd maximums) 2 + 1)

buildArray gridModders maximums = modifyArray (createArray maximums) (toModifiers gridModders) maximums

modifyArray array [] maximums = array
modifyArray array ((r,c,m):t) maximums = modifyArray (addToArray array (toIndex r c maximums) m) t maximums

addToArray array index mod = (take index array) ++ [(mod + array !! index)] ++ (drop (index + 1) array)

toIndex r c maximums = (r - 1) * (snd maximums) + c - 1

createArray (maxR,maxC) = (take (maxR * maxC)) (repeat 0)

toModifiers gridModders = flat [ toModifier gw | gw <- gridModders ]

toModifier (GridMod r c m) = [ (x,y,head m) | x <- r, y <- c]

createGridModders finalTree maximums = adjustForMaximums (treeWalk (GridMod [] [] []) finalTree) maximums

adjustForMaximums gridMods maximums = [ fillMax gm maximums | gm <- gridMods ] 

fillMax (GridMod [] [] m) (maxR,maxC) = (GridMod [1..maxR] [1..maxC] m)
fillMax (GridMod [] c m) (maxR,maxC) = (GridMod [1..maxR] c m)
fillMax (GridMod r [] m) (maxR,maxC) = (GridMod r [1..maxC] m)
fillMax (GridMod r c m) (maxR,maxC) = (GridMod r c m)

treeWalk (GridMod r c m) (Node (NodeContent 'R' v) []) = [(GridMod v c m)]
treeWalk (GridMod r c m) (Node (NodeContent 'C' v) []) = [(GridMod r v m)]
treeWalk (GridMod r c m) (Node (NodeContent 'M' v) []) = [(GridMod r c v)]
treeWalk (GridMod r c m) (Node (NodeContent 'R' v) ch) =  flat [ (treeWalk (GridMod v c m) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'C' v) ch) =  flat [ (treeWalk (GridMod r v m) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'M' v) ch) =  flat [ (treeWalk (GridMod r c v) tree) | tree <- ch ]
treeWalk (GridMod r c m) (Node (NodeContent 'Z' v) ch) =  flat [ (treeWalk (GridMod r c m) tree) | tree <- ch ]

flat [] = []
flat (h:t) = h ++ flat t

findMaximums finalTree = (oddify(findMaxRows finalTree), oddify(findMaxCols finalTree))

oddify num = num + ((Prelude.mod num 2) - 1) * (-1)

findMaxRows (Node (NodeContent 'R' v) []) = maximum v
findMaxRows (Node (NodeContent _ _) []) = 0
findMaxRows (Node (NodeContent 'R' v) c) = maximum (v ++ [ findMaxRows x | x <- c ])
findMaxRows (Node (NodeContent _ _) c) = maximum [ findMaxRows x | x <- c ]

findMaxCols (Node (NodeContent 'C' v) []) = maximum v
findMaxCols (Node (NodeContent _ _) []) = 0
findMaxCols (Node (NodeContent 'C' v) c) = maximum (v ++ [ findMaxCols x | x <- c ])
findMaxCols (Node (NodeContent _ _) c) = maximum [ findMaxCols x | x <- c ]

buildAllTrees nodeContentList = Node (NodeContent 'Z' []) (buildIntoTrees nodeContentList)

buildIntoTrees x = [ buildIntoTree treeNodeContentList | treeNodeContentList <- x ]

buildIntoTree (h:t) = Node h [ buildSubTree subList | subList <- (easyList t) ]

buildSubTree (h:t) = Node h [ Node content [] | content <- t ]

easyList nodeContentList = tail (simplifyNodeList (idy (head nodeContentList)) nodeContentList [] [])

simplifyNodeList identity [] fullList nextList = fullList ++ [nextList]
simplifyNodeList identity (h:t) fullList nextList = if (idy h == identity)
                                                        then simplifyNodeList identity t (fullList ++ [nextList]) [h]
                                                        else simplifyNodeList identity t fullList (nextList ++ [h])

createNodeContentList input = [ tupleTreeToNodeContentList tupleTree | tupleTree <- (parseToListOfTupleTrees input)]

parseToListOfTupleTrees input = [ toTupleTree x | x <- breakIntoInputTrees input]

toTupleTree x = ('M', [modifier x]):[ createTupleNode y | y <- breakIntoInputNodes x]

modifier x = read (last (splitOn "+" x )) :: Int

createTupleNode nodeStr = (head nodeStr, getNodeNumbers nodeStr)

getNodeNumbers nodeStr = if (nodeStr =~ rangePat :: Bool)
                    then extractRange (onlyNumbers nodeStr)
                    else onlyNumbers nodeStr

onlyNumbers str = toInt (words (replaceNonDigit str))

extractRange numList = [head numList .. last numList]

replaceNonDigit [] = []
replaceNonDigit ('R':t) = ' ':replaceNonDigit t
replaceNonDigit ('C':t) = ' ':replaceNonDigit t
replaceNonDigit ('-':t) = ' ':replaceNonDigit t
replaceNonDigit (',':t) = ' ':replaceNonDigit t
replaceNonDigit (h:t) = h:replaceNonDigit t

toInt :: [String] -> [Int]
toInt = map read

tupleTreeToNodeContentList x = [ tupleNodeToNodeContent tupleNode | tupleNode <- x ]

tupleNodeToNodeContent x = NodeContent (fst x) (snd x)