多项式解析器的子问题需要帮助(Haskell)

btxsgosb  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(182)

我目前正在做一个大学作业,我们要在Haskell中实现一个多项式计算器。作业的第一部分是做多边形运算,这已经完成了。如果我们实现一个多项式的解析器,我们会得到额外的学分,我目前正在做的是把一个字符串转换成一个元组[(factor,[(variable,exponent)])]。
这意味着"-10y^4 - 5z^5”=〉“[(-10,[('y ',4)]),(-5,[('z',5)].我遇到的子问题是当我遇到像“5xy^2z^3”这样的多项式时,它们应该存储为[(5,[('x',1),('y',2),('z',3)]]**,我不知道怎么解析它。
有什么建议我可以如何处理这一点?提前感谢您的帮助!

-- Slipts lists by chosen Char, only used with '+' in this project
split :: Char -> String -> [String]
split _ "" = []
split c s = firstWord : (split c rest)
    where firstWord = takeWhile (/=c) s
          rest = drop (length firstWord + 1) s

-- Remove all spaces from a string, for easier parsing
formatSpace :: String -> String
formatSpace = filter (not . isSpace)

-- Clever way to parse the polynomial, add an extra '+' before every '-'
-- so after we split the string by '+', it helps us keep the '-'
simplify_minus :: String -> String
simplify_minus [] = ""
simplify_minus (x:xs)
        | x == '^' = x : head xs : simplify_minus (tail xs)
        | x == '-' = "+-" ++ simplify_minus xs
        | otherwise =  x : simplify_minus xs

-- Splits an String by occurrences of '+' and creates a list of those sub-strings
remove_plus :: String -> [String]
remove_plus s =  split '+' s

-- Removes multiplication on substrings
remove_mult :: [String] -> [[String]]
remove_mult [] = []
remove_mult (x:xs) =  (remove_power (split '*' x)) : remove_mult xs

-- Function used to separate a variable that has an power. This translates ["y^2] to [["y", "2"]] 
remove_power :: [String] -> [String]
remove_power  [] = []
remove_power (x:xs) = (split '^' x) ++ remove_power xs

-- Wrapper function for all the functions necessary to the parser
parse_poly :: String -> [(Integer, String, Integer)]
parse_poly [] = []
parse_poly s = map (tuplify) (rem_m (remove_plus (simplify_minus (formatSpace s))))

rem_m :: [String] -> [String]
rem_m l = map (filter (not . (=='*'))) l 

helper_int :: String -> Integer
helper_int s 
    | s == "" = 1
    | s == "-" = -1
    | otherwise = read s :: Integer

helper_char :: String -> String
helper_char s
    | s == [] = " "
    | otherwise = s

tuplify :: String -> (Integer, String, Integer)
tuplify l = (helper_int t1, helper_char t3, helper_int (drop 1 t4))
    where (t1, t2)  = (break (isAlpha) l)
          (t3, t4) = (break (=='^') t2)

main :: IO() 
main = do
    putStr("\nRANDOM TESTING ON THE WAE\n")
    
    putStr("--------------\n")

    print(parse_poly "5*xyz^3 - 10*y^4 - 5*z^5 - x^2 - 5 - x")
    -- [(5,"xyz",3),(-10,"y",4),(-5,"z",5),(-1,"x",2),(-5," ",1),(-1,"x",1)]

``
wqlqzqxt

wqlqzqxt1#

这里已经有了几乎所有的东西,但是你需要递归地使用break来获取下一个变量之前的所有东西,你可能还应该使用类似的span来首先获取系数。

parsePositiveMonomial :: String -> (Integer, [(Char, Integer)])
parsePositiveMonomial s = case span isDigit s of
        ([], varPows) -> (1, parseUnitMonomial varPows)
        (coef, varPows) -> (read coef, parseUnitMonomial varPows)
 where parseUnitMonomial [] = []
       parseUnitMonomial (var:s') = case break isAlpha s' of
          ...

相关问题