【问题标题】:I am stuck on haskell input我被困在haskell输入上
【发布时间】:2014-03-09 17:41:10
【问题描述】:

我是 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)

【问题讨论】:

  • 首先,您应该使用一些(可能是简化的)代码来展示您的问题。
  • 您是在告诉我们您一次性解析了该字符串吗?当然,您有一些顶级功能,您可以在其中使用ex1 并将其或其中的一部分传递给其他功能?给我们看看这个吧。

标签: haskell input io


【解决方案1】:

我将使用一个小玩具示例来传达这个想法。

你的代码中是否经常引用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 -&gt; SomethingOrOther 类型的函数。这是一个如何与用户交互的示例:

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

这是一个相当简短的示例,但希望至少能让您入门。

了解更多

有关此主题的更多帮助,请阅读Input and Output ChapterLearn You a Haskell for Great Good

【讨论】:

  • 我想问题不在于很多函数专门依赖于输入,而是我有 50 个函数依赖于使用输入的函数的输出。我试图开始将用户输入作为函数的参数来解决我的问题,但是有 160 行凌乱的代码和像 50 个函数一样,它只是失控了,无论我多么努力,我什至无法得到它当我尝试这样做时编译。我希望有某种方法可以将用户输入转换为全局变量或其他东西——即使这破坏了 haskell 的纯度。
【解决方案2】:

下次,记住,当你有类似的东西时

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

那么你的直接开始就是写:

assignment :: String -> Tree

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

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

您已准备好进行第一次测试运行:

main = interact (show . assignment)

现在,您需要做的就是完善您的assignment 函数!

【讨论】:

    【解决方案3】:

    感谢您的回复。 我通过将结构更改为更加模块化来修复我的程序(上图)。 以前,它基本上只是一个函数链调用函数调用函数等等。我已对其进行了更改,以便代码的不同部分负责创建解决方案的不同步骤,然后将其用作下一部分的参数。 归根结底,程序是一样的,只是分解得更多。

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 2015-02-02
      • 2012-11-25
      相关资源
      最近更新 更多