How to read/ add/ print a number string in Haskell - haskell

Below if my code right now. I want to be able to take in user input like the following: "6 1 2 3 4 5 6" and the get the sum and print. it would also be cool to understand how to use the first number entered as the total numbers. SO here the first number is 6 and the total numbers inputted is 6.
Thank you in advance for helping me with this. I have been researching for weeks and cannot figure this out.
main = do
putStrLn "Enter how many numbers:" -- clearer
num<-getLine
putStrLn("Enter a number: ")
numberString <- getLine
let numberInt =(read numberString :: Int)
print (numberInt*4)
main

It seems you either need an auxiliary recursive function for reading num integers, or some helper like replicateM, which makes writing the code a little easier.
replicateM num action runs action exactly num times, and collects all the action results in a list.
main = do
putStrLn "Enter how many numbers:" -- clearer
num<-getLine
numbers <- replicateM num $ do
putStrLn("Enter a number: ")
numberString <- getLine
return (read numberString :: Int)
-- here we have numbers :: [Int]
...
You can then continue from there.
If instead you want to use an auxiliary function, you can write
readInts :: Int -> IO [Int]
readInts 0 = return []
readInts n = do
putStrLn("Enter a number: ")
numberString <- getLine
otherNumbers <- readInts (n-1) -- read the rest
return (read numberString : otherNumbers)
Finally, instead of using getLine and then read, we could directly use readLn which combines both.

Construct a list of integers using
let l = map (\x -> read x::Int) (words "6 1 2 3 4 5 6")
in (numNumbers, numbers)
You tried to read the whole string into a single number.

Related

I need to print the old and sorted list but I am encountering an error

I need help in coding this because I keep getting this error:
practice.hs:44:40: error: parse error on input `='
|
44 | sortedList :: [Integer] sortedList = sort numList
|
I hope someone can help. Here is my source code
import Data.List
listBuilder :: IO()
listBuilder = do
numList []
main = do
listBuilder
putStrLn "Enter 5 Numbers"
num1 <- getLine
num2 <- getLine
num3 <- getLine
num4 <- getLine
num5 <- getLine
num1 :: numList
num2 :: numList
num3 :: numList
num4 :: numList
num5 :: numList
sortedList :: [Integer] sortedList = sort numList
print ("Old List: " ++ numList)
print ("Sorted List: " ++ sortedList)```
First off, there are no "variables" in Haskell - values are immutable!
Secondly, :: Something is a type annotation, so num1 :: numList would mean "num1 is of type numList" - but what is "numList" supposed to be?
Here is a very simple solution:
import Data.List
main = do
putStrLn "Enter 5 Numbers"
line1 <- getLine
let num1 = read line1 :: Int
line2 <- getLine
let num2 = read line2 :: Int
line3 <- getLine
let num3 = read line3 :: Int
line4 <- getLine
let num4 = read line4 :: Int
line5 <- getLine
let num5 = read line5 :: Int
let list = [num1, num2, num3, num4, num5]
let sortedList = sort list
putStr "Old List: "
print list
putStr "Sorted List: "
print sortedList
OK, so I read a line from standard in, using getLine. This has type IO String, so it is an IO action that yields a String.
Using read, which has type Read a => String -> a, we turn the String into an Int. The type means "some 'a' which has an instance of typeclass Read, take a string and spit out an 'a', if possible".
I'm using a type annotation :: Int to signal, that I want that a to be an Int.
Repeating that 5 times, I end up with 5 Ints.
I create a list using the [] list constructor (note: you can use : [read "cons"] to put an element to the front of the linked list).
sort from Data.List will sort the list in ascending order, using the compare operation. (There is also sortOn, so you can provide a function to sort the elements by).
Then I use putStr to print my string (without a newline).
The print function takes an a and calls show on it, to turn it into a string, before printing it. So you don't need to use print with strings (you can use putStrLn (newline at end) or putStr (no newline)).
This is getting into advanced territory, but the solution is not elegant and we can do better!
Basically, we want to repeat the same IO action 5 times and convert a list of strings to a list of Ints:
import Data.List
import Control.Monad
main = do
putStrLn "Enter 5 Numbers"
inputs <- replicateM 5 getLine
let list = map read inputs :: [Int]
let sortedList = sort list
putStr "Old List: "
print list
putStr "Sorted List: "
print sortedList
repeatM repeats a monadic action n times.
The <- means something like "take this value out of the monadic context, so IO [String] and we want the [String] part.
map just applies the provided function (here read) to every element of the list argument.
I'm using a type annotation again, to tell Haskell, that the result of this expression should be a list of Ints (otherwise read would not know what a is supposed to be).

Haskell how can I show function result

I have a question that asks me find 'quadratic equation' and show result and add number of the roots
example:
Main> quadratric 2 2 2
2x^2 + 2x + 2 = 0
Has no real roots.
Main> quadratic 2 5 2
2x^2 + 5x + 2 = 0
Has two real roots:
-2.0 and -0.5
So this is quadratic equation:
quadraticprob a b c
| root < 0 = error "Has no real roots"
| root == 0 = [-b/(2*a)]
| root > 0 = [-b/(2*a) + sqroot/(2*a),
-b/(2*a) - sqroot/(2*a)]
where
root = b*b - 4*a*c
sqroot = sqrt root
I can get the result but I should add how many roots they have so I should use one more function that getLine and show the result.
I made this but it's totally wrong:
readresult :: IO ()
readresult = do
line <- getLine
putStrLn (show (quadraticprob (read line))
Can you help me with my mistake please?
Assume you want get 3 integers from standard input call "getLine" function once.
The expression
line <- getLine
will return a string like (for example)
"2 2 2"
with spaces between each integer. The first thing need to do is to remove the space and convert it from string to Int type. the words and read functions can solve this easily as below:
map read (words line)::[Int]
However, a integers list cannot pass to your quadratic function directly, it need use case get elements from list as below
case map read (words line)::[Int] of
[a, b, c] -> putStrLn $ show $ quadraticprob a b c
If you want read real number instead of integers, just change map..::[Int] to ::[Double].
A few hints:
Use a getLine for each argument
... = do
astr <- getLine
bstr <- getLine
cstr <- getLine
putStrLn (show (quadraticprob (read astr) (read bstr) (read cstr)))
For quadraticprob, it's not clear what your goal actually is. Before writing any code, you should start by writing the intended type.
quadraticprob :: ?? -> ?? -> ?? -> ??
What should that be?

How do I read N lines in a file with Haskell?

I have a file in the form:
3
1 2
3 4
5 7
Where the first line is the number of lines
I know that:
getInt :: IO Int
getInt = readLn
main = do num <- getInt
print (num)
Reads the first line.
Next, I tried:
readInts :: IO [Int]
readInts = fmap (map read.words) getLine
For read a line and get a list: [a,b].
And I tried to use the above in a recursive loop
loop :: Int -> IO()
loop n = if 1 == n then do num <- readInts
print(num)
else loop (n-1)
I'm getting the first line only:
[5,3]
But I need to read the rest of lines, given N
The format of the input file looks a lot like the ones used in programming contests. Here is my standard setup for programming contests like that:
import Control.Monad
import Text.Printf
main :: IO ()
main = do
n <- readLn
forM_ [1 .. n] $ \i -> do
printf "Case %d: " (i :: Int)
solve
An example of solve might be:
solve :: IO ()
solve = do
nums <- map read . words <$> getLine
print (sum nums)
Adding to this helpful answer and comment, for some challenges you'll need to collect n lines and then emit a single result at the end based on an aggregation of the data. An approach for creating a list might use replicateM as follows:
import Control.Monad
toInt :: String -> Int
toInt x = read x :: Int
lineToInts :: String -> [Int]
lineToInts x = map toInt $ words x
main :: IO ()
main = do
n <- readLn
remainingLines <- replicateM n getLine
let list = map lineToInts remainingLines
print list
Sample run:
3
0 1
3 4
6 8
[[0,1],[3,4],[6,8]]
See also Read n lines input with Haskell
Have you looked into the function lines? It takes a string and returns the same string as a list separated by \n. Using this function you don't even have to have the number of lines.

Haskell print map over array [duplicate]

This question already has answers here:
A better way to map a function that requires IO over a list
(4 answers)
Closed 8 years ago.
I'm practicing with a problem that gives text input on stdin and wants output on stdout.
They give an integer T in the first line that I read, and then T lines follow. For the T following lines I have a function that takes an integer and returns an integer that I must print. So my output should be T lines.
I'm stuck at this point:
main = do
strcases <- getLine
map (calculate) [1..(read strcases)]
calculate _ = do
strp <- getLine
print $ addone (read strp)
addone x = x+1
Of course this doesn't work at the moment. Can you show how to print the T lines of output?
You can use readLn, which combines getLine and read, and replicateM_ from Control.Monad to repeat an IO action (or any monad) a given number of times:
import Control.Monad
main :: IO ()
main = do
n <- readLn
replicateM_ n calculate
calculate :: IO ()
calculate = do
x <- readLn
print $ addone x
addone :: Int -> Int
addone x = x+1
Note, the underscore suffix on replicateM_ indicates that the return value of each executed action be discarded. The alternative function without the underscore suffix will return a list containing the return value of each executed action, which we do not want in this case.

Help In Solving Problem Using Guards - UPDATED With CODE

I am using guards inside a function but not immediately after the function signature. The guards are under a do statement inside the body of the function. I get this error:
parse error on input `|'
I thought maybe the error comes from the indentation but i have tried many indentation but still i get the errors. Am asking is it because the guards are not immedaitely after the function signature that is why am getting the errors?
thanks
UPDATE 1
CODE:
The user is suppose to guess a number , and the number will be compared with the random number if they are the same. If it is not correct then the user will guess till the "guess" variable in the function is zero. in every interation that value(guess) is decreased by one.
for instance : puzz 12 5. the user can guess for five times, the random number will be picked between 1 and 12. that is how the function is suppose to do, but it is not working.
puzz :: Int -> Int -> IO ()
puzz boundary guess = do
putStr "Guess"
-- putStr -- I have to print (1 .. guess) here in each iteration
putStr ":"
x <- randomRIO (1, boundary :: Int)
n <- getLine
let
nTo = read n::Int
in print x
| guess == 0 = putStr "You couldn't guess right,the correct answer is" ++ x
| nTo > x = putStr "lower"
| nTo < x = putStr "higer"
| nTo == x = putStr "Congrat, You guess right."
| otherwise raad boundary (guess - 1)
the ouput must be like this:
Main> puzz 50 6
Guess a number betwee 1 en 50.
Guess 1: 49
lower
Guess 2: 25
lower
Guess 3: 12
higher
Guess 4: 18
higher
Guess 5: 21
higher
Guess 6: 23
lower
You couldn't guess correct, the answer was: 22.
thanks for your help
You’re using guards incorrectly. From the report:
Top level patterns in case expressions and the set of top level patterns in function or pattern bindings may have zero or more associated guards.
So they’re only for cases and function bindings. If you just want to concisely introduce a series of true-false tests, while inside a do-notation, perhaps the case () of () trick would work:
main = do
putStrLn "hello world"
n <- getLine
let nTo = read n :: Int
case ()
of () | cond -> putStrLn "foo"
| cond' -> putStrLn "bar"
| otherwise -> putStrLn "baz"
It should be noted that there are several things that are a bit off with your code, in addition to using guards wrong. By default output is buffered in haskell so if you want Guess to be on the same line as input you have to either say that stdOut should not be buffered (hSetBuffering stdOut NoBuffering), or you have to flush output with hFlush. It's not necessary to write boundary :: Int, the compiler knows it is an Int. Here is a bit more complete example, I'm sure it could be done better but atleast it works:
import Control.Monad(liftM,unless)
import System.IO(hFlush,stdout)
import System.Random(randomRIO)
guessMyNumber upper guesses = do
putStrLn $ "Guess a number between 1 and " ++ show upper ++ "!"
randomRIO (1, upper) >>= puzz guesses
puzz 0 number = do
putStrLn $ "Sorry, no more guesses, the number was "
++ show number ++ "."
puzz guesses number = do
putStr "Guess:" >> hFlush stdout
guess <- liftM read getLine
printMessage guess number guesses
printMessage guess number guesses
| number > guess = putStrLn "higer" >> puzz (guesses-1) number
| number < guess = putStrLn "lower" >> puzz (guesses-1) number
| number == guess = putStrLn "Congratulations! You guessed right!"

Resources