Convert string to ints. Haskell - haskell

Because of the fact I am a beginner when it comes to Haskell and generally functional programmer I would like to someone tell me how to improve my solution. The task is convert string to ints. For example:
"sada21321" -> []
"d123 32 4 123.3 32 " -> [32, 4, 32]
"FFFFFFFFFF" -> []
" " -> []
Solution:
import Data.Char
readInts :: String -> [Int]
readInts s = (( map convertStringToInt ) . (filter (\ elem -> (all isDigit elem))) . getSubstrings)s
getSubstrings :: String -> [String]
getSubstrings s = getSubstrings' s [] [] where
getSubstrings' (h:t) curr res
| h == ' ' && (length curr ) > 0 = getSubstrings' t [] ( res ++ [curr])
| h /= ' ' = getSubstrings' t (curr ++ [h]) res
| otherwise = getSubstrings' t curr res
getSubstrings' [] curr res = if (length curr ) > 0 then ( res ++ [curr] ) else res
reverseList :: [a] -> [a]
reverseList [] = []
reverseList (h:t) = (reverseList t) ++ [h]
convertStringToInt :: String -> Int
convertStringToInt s = convertStringToInt' (reverseList s) 1 0
where
convertStringToInt' [] _ res = res
convertStringToInt' (h:t) m res = convertStringToInt' t (m*10) (res + (((ord h) - 48)*m))

You should take a look at the words and read functions.
(because this is an assignment, I'll let you fill in the details)

Use read ("Your string here.") :: Integer and also check for read. You can convert string to mostly any types you want to.

Related

Haskell function to check if substring "100" is present in the binary expansion of a decimal number

Define a function nohundred :: Int -> Int such that for a positive number n nohundred n is the nth positive number such that "100" does not occur as a substring in its binary expansion.
decToBin :: Int -> [Int]
decToBin x = reverse $ decToBin' x
where
decToBin' :: Int -> [Int]
decToBin' 0 = []
decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a
check :: [Int] -> Bool
check (z:zs)
|((z == 1) && (head (zs) == 0) && (head (tail zs) == 0)) = True
| otherwise = check zs
binToDec :: [Int] -> Int
binToDec l = sumlist (zipWith (*) (iterate f 1) (reverse l))
where
sumlist :: [Int] -> Int
sumlist [] = 0
sumlist (x:xs) = x + (sumlist xs)
f :: Int -> Int
f j = (2 * j)
nohundred :: Int -> Int
nohundred n = if ((check fun) == True) then (binToDec (fun)) else (nohundred (n+1))
where
fun = decToBin n
The above code gives error :-
*Main> nohundred 10
*** Exception: Prelude.head: empty list...
The desired output is 14.
*Main> nohundred 100
100
The desired output is 367...
Can anyone suggest the cause of error?
This function is partial:
check (z:zs)
|((z == 1) && (head (zs) == 0) && (head (tail zs) == 0)) = True
| otherwise = check zs
When called with a one- or two-element list, the first check will call head on an empty list. Additionally, it does not cover the empty-list case. The idiomatic way to write this is:
check (1:0:0:zs) = True
check (z:zs) = check zs
check [] = False
Additionally, your nohundred function takes a number and finds the next higher non-hundred number; but you want the nth non-hundred number, which is a very different thing.

Valid Parenthese in a string (Haskell implementation)

the problem is to check whether parentheses in a string is properly closed or not. For Haskell implementation, so far I have following. It looks quite awkward. I am looking for a more "Haskell-style" or more elegant implementation.
import Data.List
isValidParentheses :: String -> Bool
isValidParentheses = isValidHelper . (filter isParenthese)
getIndex :: (Eq a) => a -> [a] -> Int
getIndex c xs = getOut (elemIndex c xs)
where getOut (Just x) = x
getOut Nothing = -1
isLeftParenthese :: Char -> Bool
isLeftParenthese c = (getIndex c "{[(") /= -1
isRightParenthese :: Char -> Bool
isRightParenthese c = (getIndex c "}])") /= -1
isParenthese :: Char -> Bool
isParenthese c = isLeftParenthese c || isRightParenthese c
isValidHelper :: String -> Bool
isValidHelper xs = helper xs []
where helper (x:xs) [] | isRightParenthese x = False
| otherwise = helper xs [x]
helper [] st = null st
helper (x:xs) (s:ss) | isLeftParenthese x = helper xs (x:s:ss)
| ((getIndex x "}])") /= (getIndex s "{[(")) = False
| otherwise = helper xs ss
Thanks
Loop through the string
Store opening parentheses in stack
Pop matching parentheses out of the stack
Check if stack is empty at the end
isValid = loop []
where
match '(' ')' = True
match '{' '}' = True
match '[' ']' = True
match _ _ = False
loop st [] = null st
loop st (x:xs)
| x `elem` "([{" = loop (x:st) xs
| x `elem` ")]}" = case st of
open : st' | match open x -> loop st' xs
_ -> False -- unmatched close
| otherwise = loop st xs

How can I extract list of similar elements from a haskell list

Given a list such as [1,0,0,0,3,0,0,0,0,2,4,0,0] and an index, how can I extract consecutive patterns of 0 in Haskell. For example if the given index is between 1 and 3 inclusive, the result is [0,0,0] if it is between 5 and 8 [0,0,0,0] and so on
First, build a list where run lengths are stored for each number:
runs :: (Eq a) => [a] -> [(a, Int)]
runs = map (head &&& length) . group
so e.g.
runs [1,0,0,0,1,0,0,0,0,1,1,0,0] == [(1,1),(0,3),(1,1),(0,4),(1,2),(0,2)]
Then, index into this list by walking it in run length-sized steps:
indexRuns :: Int -> [(a, Int)] -> [a]
indexRuns i [] = error "Index out of bounds"
indexRuns i ((x, l):rs)
| i < l = replicate l x
| otherwise = indexRuns (i - l) rs
You can do this in O(n) time:
extract :: Eq a => Int -> [a] -> [a]
extract _ [] = []
extract idx (x:xs) = extract' x [x] 1 xs
where
extract' _ _ _ [] = [] -- Index out of bounds
extract' v vs n (r : rest)
| idx == n = vs ++ (takeWhile (== v) rest)
| (v == r) = extract' v (r:vs) (n+1) rest
| otherwise = extract' r [r] (n+1) rest
This will count the number of zeros around the index
numZeros::Int->[Int]->Int
numZeros 0 (1:_) = 0
numZeros i (1:rest) = numZeros (i-1) rest
numZeros i theList
| i < zeroLen = zeroLen
| otherwise = numZeros (i-zeroLen) $ drop zeroLen theList
where
zeroLen = length (takeWhile (==0) theList)
You can replicate 0 the appropriate number of times to get the final list.
f = f' (takeWhile (== 0)) where
f' c n xs | n < 0 || null xs = []
f' c n (1:xs) = f (n - 1) xs
f' c 0 xs = c xs
f' c n (0:xs) = f' ((0:) . c) (n - 1) xs
Or even more obfuscated
f n xs = g (splitAt n xs) >>= takeWhile (== 0) where
g (xs, ys#(0:_)) = [reverse xs, ys]
g _ = []
Some tests:
main = mapM_ (\i -> print $ (i, f i [1,0,0,0,1,0,0,0,0,1,1,0,0])) [-1..13]
prints
(-1,[])
(0,[])
(1,[0,0,0])
(2,[0,0,0])
(3,[0,0,0])
(4,[])
(5,[0,0,0,0])
(6,[0,0,0,0])
(7,[0,0,0,0])
(8,[0,0,0,0])
(9,[])
(10,[])
(11,[0,0])
(12,[0,0])
(13,[])

How to use divide and conquer in parallel to calculate a/b as return for this list

implementing getReturnList and getReturnList2
getReturnList is for calculating return a/b in once
getReturnList2 is for advanced version using divide and conquer in parallel to increase
the speed to calculate return a/b that means it want to calculate in parallel in different
sublist of whole list
First error I do not understand that i pass x : [] to parameter [String]
compiler return this error
error for getReturnList
readcsv.hs:108:20:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
In the return type of a call of `getClose'
In the first argument of `(:)', namely `(getClose (x : []))'
In the expression:
(getClose (x : [])) : getReturnList (n - 1) total xs
readcsv.hs:108:30:
Couldn't match type `[Char]' with `Char'
Expected type: String
Actual type: [String]
In the first argument of `(:)', namely `x'
In the first argument of `getClose', namely `(x : [])'
In the first argument of `(:)', namely `(getClose (x : []))'
code:
import Control.Monad.Par
import Text.ParserCombinators.Parsec
import Data.Either.Unwrap
import System.IO
{- A CSV file contains 0 or more lines, each of which is terminated
by the end-of-line character (eol). -}
csvFile :: GenParser Char st [[String]]
csvFile =
do result <- many line
eof
return result
-- Each line contains 1 or more cells, separated by a comma
line :: GenParser Char st [String]
line =
do result <- cells
eol -- end of line
return result
-- Build up a list of cells. Try to parse the first cell, then figure out
-- what ends the cell.
cells :: GenParser Char st [String]
cells =
do first <- cellContent
next <- remainingCells
return (first : next)
-- The cell either ends with a comma, indicating that 1 or more cells follow,
-- or it doesn't, indicating that we're at the end of the cells for this line
remainingCells :: GenParser Char st [String]
remainingCells =
(char ',' >> cells) -- Found comma? More cells coming
<|> (return []) -- No comma? Return [], no more cells
-- Each cell contains 0 or more characters, which must not be a comma or
-- EOL
cellContent :: GenParser Char st String
cellContent =
many (noneOf ",\n")
-- The end of line character is \n
eol :: GenParser Char st Char
eol = char '\n'
parseCSV :: String -> Either ParseError [[String]]
--parseCSV :: String -> [[String]]
--parseCSV input = parse csvFile input
parseCSV input = parse csvFile "(unknown)" input
take3 :: Int ->[[String]] -> [String]
take3 0 _ = []
take3 _ [] = []
take3 n (x:xs)
| n == 1 = x
| n > 0 = take3 (n-1) xs
take3 _ _ = error "preludelist.take: negative argument"
returnlimiters = ['\n']
realtake2 :: Int -> [[String]] -> [String]
realtake2 x y = take3 x y
takeelem3 :: Int -> [String] -> String
takeelem3 0 _ = []
takeelem3 _ [] = []
takeelem3 n (x:xs)
| n == 1 = x
| n > 0 = takeelem3 (n-1) xs
takeelem3 _ _ = error "preludelist.take: negative argument"
realtakeelem2 :: Int -> [String] -> String
realtakeelem2 x y = takeelem3 x y
getOpen :: [String] -> String
getOpen x = realtakeelem2 2 x
getHigh :: [String] -> String
getHigh x = realtakeelem2 3 x
getLow :: [String] -> String
getLow x = realtakeelem2 4 x
getClose :: [String] -> String
getClose x = realtakeelem2 5 x
whitespace :: String
whitespace = ['\n','\t',' ']
forloop3 0 f = return()
forloop3 n f =
do
f n
forloop3 (n-1) f
getReturnList :: Int -> Int -> [[String]] -> [[String]]
getReturnList 0 _ _ = []
getReturnList _ _ [] = []
getReturnList n total (x:xs)
| n == total = getReturnList (n-1) total xs
| n > 0 = (getClose (x : [])) : getReturnList (n-1) total xs
getReturnList _ _ _ = error "preludelist.take: negative argument"
getReturnList2 :: Int -> Int -> [[String]] -> [[String]]
getReturnList2 0 _ _ = []
getReturnList2 _ _ [] = []
getReturnList2 n total (x:xs)
| n == total = getReturnList2 (n-1) total xs
| n > 0 =
do
p1 <- spawn (getReturnList2 n-1 total (filter (<x) xs))
p2 <- spawn (getReturnList2 n-1 total (filter (>=x) xs))
left <- get p1
right <- get p2
return $ left ++ (x:right)
getReturnList2 _ _ _ = error "preludelist.take: negative argument"
main = do
csvstring <- readFile "C:\\Users\\martin.lee\\Downloads\\0388.HK.csv"
let afterparse = parseCSV csvstring
let afterparse2 = fromRight afterparse
--putStrLn(show afterparse2)
let getline3 = realtake2 3 afterparse2
putStrLn(show getline3)
--putStrLn(getOpen getline3)
--putStrLn(getHigh getline3)
--putStrLn(getLow getline3)
putStrLn(getClose getline3)
--forloop3 5 (\c -> putStrLn(show (5-c)))
--putStrLn(show (take2b 3 2 3 afterparse2))
--let (as,bs) = splitAt (length grids `div` 2) afterparse2
let num = 5
putStrLn("begin getReturnList")
putStrLn(show ( "a" : []))
putStrLn(show (getReturnList 3 3 afterparse2))
putStrLn("end getReturnList")
--putStrLn(show (1 :: Float))
--putStrLn(show (getlines2 csvstring))
--putStrLn(show (take 1 (getlines2 csvstring)))
putStrLn("a")
update:
F# non-parallel version
let rec test2(xs : float list) =
if xs.Length > 3 then
let (list1, list2) = split1 (xs.Length/2) xs
let (list3, list4) = split1 (xs.Length/2-1) xs
let b1 = test2(list1) // would like to parallel these two function
let b2 = test2(list4) // would like to parallel these two function
b1 # b2
else
let b1 = xs |> Seq.windowed 2
|> PSeq.map (fun x -> x.[0]/x.[1])
|> PSeq.toList
b1

Haskell, return a tuple

i have this code, it's the formulae of combination without repetitions:
combinaciones :: Int ->[Int]->[[Int]]
combinaciones 0 _ = [[]]
combinaciones _ [] = []
combinaciones k (x:xs) = [x:ys | ys <- combinaciones (k - 1) xs] ++ combinaciones k xs
combinationsN :: Int ->Int->[[Int]]
combinationsN n k = combinaciones k [1..n]
My problem is that i want return a list of lists with the number of lists in the list, a couple: ([[Int]], Int). How can i do that?
Here is the simple version - it's probably possible to do it more efficiently by counting along, but this is what I can come up with at 1am.
combinationsWithCount :: Int -> [Int] -> ([[Int]], Int)
combinationsWithCount n xs = let cs = combinaciones n xs
in (cs, length cs)
Edit: OK, let me try to write the smart version too.
combinaciones :: Int -> [Int] -> ([[Int]], Int)
combinaciones 0 _ = ([[]], 1)
combinaciones _ [] = ([], 0)
combinaciones k (x:xs) =
let (first, firstN) = combinaciones (k - 1) xs
(second, secondN) = combinaciones k xs
in ([x:ys | ys <- first] ++ second, firstN + secondN)
Absolutely no guarantees that this does the right thing, I'm half-asleep. ;-)

Resources