Where ist the infinity loop? [closed] - haskell

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 13 days ago.
Improve this question
somebody care to tell me where the problem with this function is?
Something is wrong with this complex:
buildBoard :: String -> Board
buildBoard xs = buildBoard' ("+" ++ xs ++ "+") []
buildBoard' :: String -> [Cell] -> Board
buildBoard' [] _ = [[]]
buildBoard' xs result
|head xs == ',' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == 'w' =
buildBoard' (drop (getFirstNonNumber 0) xs) (Piece White intConversion : result)
|head xs == 'b' =
buildBoard' (drop (getFirstNonNumber 0) xs) (Piece White intConversion : result)
|head xs == '/' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == ',' && xs!!1 == '/' = buildBoard' (tail xs) (Empty:result)
|head xs == '+' && xs!!1 == ',' = buildBoard' (tail xs) (Empty:result)
|head xs == '+' && xs!!1 `elem` ['b','w'] = buildBoard' (tail xs) result
|head xs == ',' && xs!!1 == '+' = buildBoard2 (reverse (Empty:result))
|head xs == '+' = buildBoard2 (reverse result)
|otherwise = buildBoard2 (reverse result)
where intConversion = read [xs!!1..xs!!(getFirstNonNumber 0 -1)] :: Int
getFirstNonNumber num = if xs!!num `elem` [',','/'] then num else getFirstNonNumber num+1
separate :: Int -> [a] -> [[a]]
separate _ [] = []
separate n l
| n > 0 = take n l : separate n (drop n l)
| otherwise = []
buildBoard2 :: [Cell] -> Board
buildBoard2 = separate 9
some additional info about what Cell, Board etc is:
data Player = Black | White deriving Show
data Cell = Piece Player Int | Empty deriving Show
data Pos = Pos { col :: Char, row :: Int } deriving Show
type Board = [[Cell]]

Here, at least, is one:
getFirstNonNumber num = if ... then num else getFirstNonNumber num+1
You almost certainly meant that last call to be:
getFirstNonNumber (num+1)

Related

Simplify function for Haskell

I have this code, which in my opinion is too long. And I was wondering if there's a way for me to simplify or shorten it.
I have this helper-function swap which takes in two lists of integers and returns them after swapping a number from on to the other All lists have 5 ints in them, so I fill in with zeroes if there are less than that.
It looks like this:
-- Takes in two lists and moves one non-zero int from one to the other
swap :: [Int] -> [Int] -> [[Int]]
swap xs ys
| xs == ys = [xs, ys] -- If both lists are all zeroes
| all (==0) ys = -- If the second list is all zeroes
let
e = head $ filter (/= 0) xs -- First non-zero element from first list
newX = replicate (length xs - length (filter (/= 0) xs) - 1) 0 ++ tail (filter (/= 0) xs)
newY = tail ys ++ [e]
in
[newX, newY]
| otherwise =
let
e = head $ filter (/= 0) xs -- First non-zero element from first list
newX = replicate (length xs - length (filter (/= 0) xs) + 1) 0 ++ tail (filter (/= 0) xs)
newY = replicate (length (filter (==0) ys) - 1) 0 ++ [e] ++ drop (length xs - length (filter (/= 0) ys)) ys
in
[newX, newY]
I am using it in my function below, which is the function I feel like is too long:
move :: Int -> Int -> [[Int]] -> [[Int]]
move a b ints
| a == b = error "a and b cannot be the same integer"
| a == 1 && b == 2 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[head swapped, last swapped, last ints]
| a == 1 && b == 3 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[head swapped, ints !! 1, last swapped]
| a == 2 && b == 1 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[last swapped, head swapped, last ints]
| a == 2 && b == 3 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[head ints, head swapped, last swapped]
| a == 3 && b == 1 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[last swapped, ints !! 1, head swapped]
| a == 3 && b == 2 =
let
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
in
[head ints, last swapped, head swapped]
| otherwise = error "a and b must be either 1, 2 or 3"
This function takes in two ints and a list consisting of 3 lists of ints, where each list has 5 integers, so a sample input would be f.ex
[[1,2,3,4,5],[0,0,0,0,0],[0,0,0,0,0]] or
[[0,0,0,4,5],[0,0,0,2,3],[0,0,0,0,1]] or
[[0,0,3,4,5],[0,0,0,0,1],[0,0,0,0,2]]
So $a$ and $b$ can only be either 1,2, or 3. Giving me $2^3=6$ different cases to consder. Even If manage to get it down to two cases $a>b$ and $b>a$ I still get too many lines of code compared to what I expect is proper for Haskell. Is there any way of shortening this code?
This is not a full answer yet, but the start of one. Look how I removed all code duplication into where blocks. There are still plenty of opportunities of simplification.
-- Takes in two lists and moves one non-zero int from one to the other
swap :: [Int] -> [Int] -> [[Int]]
swap xs ys
| xs == ys = [xs, ys] -- If both lists are all zeroes
| all (==0) ys = -- If the second list is all zeroes
let
newX = replicate (length xs - length nonZeroXs - 1) 0 ++ tail nonZeroXs
newY = tail ys ++ [e]
in
[newX, newY]
| otherwise =
let
newX = replicate (length xs - length nonZeroXs + 1) 0 ++ tail nonZeroXs
newY = replicate (length (filter (==0) ys) - 1) 0 ++ [e] ++ drop (length xs - length (filter (/= 0) ys)) ys
in
[newX, newY]
where
nonZeroXs = filter (/= 0) xs
e = head $ filter (/= 0) xs -- First non-zero element from first list
The only difference between newXs is the signal of the the final addition. Which suggests that the entire decision block might be not be at it's best place.
move :: Int -> Int -> [[Int]] -> [[Int]]
move a b ints
| a == b = error "a and b cannot be the same integer"
| a == 1 && b == 2 = [head swapped, last swapped, last ints]
| a == 1 && b == 3 = [head swapped, ints !! 1, last swapped]
| a == 2 && b == 1 = [last swapped, head swapped, last ints]
| a == 2 && b == 3 = [head ints, head swapped, last swapped]
| a == 3 && b == 1 = [last swapped, ints !! 1, head swapped]
| a == 3 && b == 2 = [head ints, last swapped, head swapped]
| otherwise = error "a and b must be either 1, 2 or 3"
where
fst = ints !! (a-1)
snd = ints !! (b-1)
swapped = swap fst snd
Have a good look on the above and run some tests. I don't have the time to test it myself right now.

splitting strings in haskell programming

Hi i am trying to do a function input is a list of strings, and the output is again a list of all words occurring in the input.
for example input ["For example,", "love,", "hate."]
output ["For","example","love","hate"]
atm i have this. Any help would be appreciated. Also how can i remove the blank space with just one function and in linear time?
And not using any existing function
split' :: String -> [String]
split' [] = []
split' (x:xs)
| isBlank x = split' xs
| otherwise = waitForBlank (x:xs) : split' (drop (length (waitForBlank (x:xs))) xs)
isBlank :: Char -> Bool
isBlank x = if x == ' ' then True else False
waitForBlank :: String -> String
waitForBlank [] = []
waitForBlank (x:xs)
| isBlank x = []
| otherwise = x : waitForBlank xs
There's a cool one-line to perform what you need
["For example,", "love,", "hate."] >>= words
>>= has type (>>=) :: Monad m => m a -> (a -> m b) -> m b, which takes a function which returns a monadic structure and joins the result into the monadic structure.
If you want to implement words by yourself:
words' xs =
let
waitForBlank (acc, buff) [] = (acc ++ [buff], buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank (acc ++ [buff], []) xs
else
waitForBlank (acc, buff ++ [x]) xs
in
fst (waitForBlank ([], []) xs)
Or with using (:) and reverse the result (for better performance):
words'' xs =
let
waitForBlank (acc, buff) [] = (reverse (buff : acc), buff)
waitForBlank (acc, buff) (x:xs) =
if x == ' ' then
waitForBlank ((reverse buff) : acc, []) xs
else
waitForBlank (acc, x:buff) xs
in
fst (waitForBlank ([], []) xs)

Evaluating arithmetic string in Haskell- debugging

I'm attempting to take in a string, evaluate, and output the answer. For example: if the input is the string "2*(3+10)" then the output should be the int 26
At the moment, It isn't working. I'm having problems with white space. If there is white space in the code input, I get ***Exception: Char.digitToInt: not a digit ' '. If there is NO whitespace in the input i get *** Exception: Prelude.!!: index too large
import Data.Char
parseExpr :: String -> Int
parseExpr str = start(trim (str))
trim :: [Char] -> [Char]
trim xs = [ x | x <- xs, not (isSpace x)]
start :: [Char] -> Int
start xs = expression xs 0
expression :: [Char] -> Int -> Int
expression xs i
|(xs !! (((basic xs i (-1))!! 1)+1)) == '+' = (multiply xs ((basic xs i (-1))!! 1)) + (multiply xs ((basic xs (i+2) (-1))!! 0))
|(xs !! (((basic xs i (-1))!! 1)+1)) == '-' = (multiply xs ((basic xs i (-1))!! 1)) - (multiply xs ((basic xs (i+2) (-1))!! 0))
|otherwise = multiply xs i
multiply :: [Char] -> Int -> Int
multiply xs i
| (xs !! (((basic xs i (-1))!! 1)+1)) == '*' = (power xs ((basic xs i (-1))!! 0)) * (power xs ((basic xs (i+2) (-1))!! 0))
| (xs !! (((basic xs i (-1))!! 1)+1)) == '/' = (power xs ((basic xs i (-1))!! 0)) `div` (power xs ((basic xs (i+2) (-1))!! 0))
|otherwise = power xs i
power :: [Char] -> Int -> Int
power xs i
| (xs !! (((basic xs i (-1))!! 1)+ 1)) == '^' = (((basic xs i (-1))!! 0) ^ ((basic xs (i+2) (-1))!! 0))
|otherwise = (basic xs i (-1)) !! 0
basic :: [Char] -> Int -> Int -> [Int]
basic xs i pnum
| pnum > (-1) && (isDigit(xs !!(i+1))) = basic xs (i+1) (pnum*10 + (digitToInt(xs !! i)))
| isDigit(xs !! i ) && isDigit(xs !!(i+1)) = basic xs (i+1) (digitToInt (xs !! i))
| pnum > (-1) && not (isDigit(xs !!(i+1))) = [pnum, i] -- + digitToInt(xs !! i)
| xs !! i == '-' = [(-(basic xs (i+1)(-1)) !! 0) , i] -- may want to delete if add/sub can handle
| xs !! i == '(' = [(expression xs (i+1)), i]
| xs !! i == ')' = [(expression xs (i+1)), i] --This may not work here
| otherwise = [digitToInt (xs !! i), i]

Haskell string replace

How do I replace a character with multiple characters in a string.
I can replace a character with another character with below:
replaceO [] = []
replaceO (x:xs) =
if x == '('
then '\n' : replaceO xs
else x : replaceO xs
But I want to replace '(' with "\n\t\t", not just '\n'.
---------- UPDATE --------------
Based on the answer below, can I make that a function that accepts a string and returns a string like this:
ReplaceFun str :: String -> String
ReplaceFun str = do
concatMap (\str -> if str == '.' then "foo" else [str])
This doesn't work, can someone point out my mistake? I am very new to Haskell.
Here is what I have for nested indentation:
replaceO (x:xs) n l =
if x == '('
then "\n" ++ (showTabs n "-") ++ replaceO xs (n + 1) 'l'
else
if x == ')'
then "\n" ++ (showTabs n "-") ++ replaceO xs (n - 1) 'l'
else x : replaceO xs n 'l'
Just use concatMap
Prelude> concatMap (\x -> if x == '.' then "foo" else [x]) "example..."
"examplefoofoofoo"
expanding your example, you can substitute "\n\t\t" for "(" by just prepending multiple things to the result of the recursive call
replace1 [] = []
replace1 (x:xs) =
if x == '('
then '\n' : '\t' : '\t' : replace1 xs
else x : replace1 xs
of course, this is equivalent to using "\n\t\t" ++
replace2 [] = []
replace2 (x:xs) =
if x == '('
then "\n\t\t" ++ replace2 xs
else x : replace2 xs
if we note that x : is equivalent to [x] ++
replace3 [] = []
replace3 (x:xs) =
if x == '('
then "\n\t\t" ++ replace3 xs
else [x] ++ replace3 xs
then we can factor out the repeated recursive call
replace4 [] = []
replace4 (x:xs) = (if x == '(' then "\n\t\t" else [x]) ++ replace4 xs
then for clarity, we could filter out the if statement into a function:
replace5 [] = []
replace5 (x:xs) = f x ++ replace5 xs
where f x = if x == '('
then "\n\t\t"
else [x]
we could then reorganize our code - rather than alternately applying f to each x and
appending it to our results, we could apply f to all the xs and then concatenate all the results:
replace6 xs = concat $ map f xs
where f x = if x == '('
then "\n\t\t"
else [x]
But concat $ map f xs is used so often that it has another name:
replace7 xs = concatMap f xs
where f x = if x == '('
then "\n\t\t"
else [x]
Actually, it has another one too, because [] is a monad:
replace8 xs = xs >>= f
where f x = if x == '('
then "\n\t\t"
else [x]
But if we're doing that, we might as well go full Monad:
replace9 xs = do
x <- xs
if x == '('
then "\n\t\t"
else [x]
But I'd probably just stop at replace7, personally.

Haskell Function Returning Empty List

I'm really an absolute newbie at Haskell, so I'm at a total loss as to how to debug some functions I wrote. When I call shuntingYard ["3+4"] I get back [], whereas I want to get back [34+]. Any and all help would be greatly, greatly appreciated.
import Char
isOperator :: Char -> Bool
isOperator x = elem x ['+','-','*','/','%','^','!','=','<','>']
associativityOf :: Char -> String
associativityOf x = if elem x ['+','-','*','/','%']
then "Left"
else "Right"
precedenceOf :: Char -> Int
precedenceOf x
| elem x "=<>" = 1
| elem x "+-" = 2
| elem x "*/%" = 3
| elem x "^!" = 4
| otherwise = 0
operatorActions :: [[Char]] -> [[Char]] -> [[Char]]
operatorActions stmt stack
| ( tokenAssoc == "Left" && tokenPrecedence <= stackPrecedence ) ||
( tokenAssoc == "Right" && tokenPrecedence < stackPrecedence ) =
[stackOper] : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) ((head stmt) : stack)
where tokenAssoc = associativityOf (head (head stmt))
tokenPrecedence = precedenceOf (head (head stmt))
stackOper = if (not (null stack))
then (head (head stack))
else '='
stackPrecedence = precedenceOf stackOper
stackOperations :: [[Char]] -> [[Char]]
stackOperations stack
| ((not (null stack)) && (head (head stack)) == '(') =
error "Unbalanced parens."
| null stack = []
| otherwise = (head stack) : _shuntingYard [] (tail stack)
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack
| null stmt = stackOperations stack
| all isDigit (head stmt) = (head stmt) : _shuntingYard (tail stmt) stack
| isOperator (head (head stmt)) = operatorActions stmt stack
| (head (head stmt)) == '('=
_shuntingYard (tail stmt) ((head stmt) : stack)
| (head (head stmt)) == ')' = if (head (head stack)) == '('
then _shuntingYard (tail stmt) (tail stack)
else (head stack) : _shuntingYard stmt (tail stack)
| otherwise = _shuntingYard (tail stmt) stack
shuntingYard :: [[Char]] -> [[Char]]
shuntingYard stmt = _shuntingYard stmt []
As a general debugging technique, you can use the Debug.Trace module to find out which functions are being called and what their inputs are. Using look at the state of your algorithm after each step.
import Debug.Trace
-- Show arguments each time _shuntingYard is called
_shuntingYard :: [[Char]] -> [[Char]] -> [[Char]]
_shuntingYard stmt stack = traceShow (stmt, stack) $ __shuntingYard stmt stack
__shuntingYard stmt stack
| null stmt = stackOperations stack
{- etcetera -}
This prints:
(["3+4"],[])
([],[])
Hmm, you lost everything after the first call. Looking at the guards in __shuntingYard, it seems that the "otherwise" case gets called.
Maybe you wanted to call shuntingYard ["3", "+", "4"]?
Ok, let's just play through what happens when you call shuntingYard ["3+4"]:
It calls _shuntingYard ["3+4"] []
It goes through the guards of _shuntingYard:
null stmt = null ["3+4"] = false
all isDigit (head stmt) = all isDigit "3+4" = false as + is not a digit
isOperator (head (head stmt)) = isOperator '3' = false
Also false as '3' /= '('
Also false as '3' /= ')'
Since none of the guards matched, so we go into the default case and call _shuntingYard (tail stmt) stack = _shuntingYard [] []
This time the first guard(null stmt = null []) matches, so we call stackOperations [] and get [].

Resources