I tried to minimise the code as glennsl suggested. It turns out, I don't know how to read inputs from multiple lines in OCaml.
For example, pretend, stdin contains the following pattern
5
1 2 3 4 5
3
6 7 8
I need to read this and print to stdout. I'm using the "%d %d %d %d %d\n" format specifier as if I know the number of inputs is 5 in advance, just to illustrate my problem.
Now the following code fails with the same error Fatal error: exception End_of_file (I have tried to reproduce the same problem with fewer lines of code) if I uncomment the bottom part.
let number_of_inputs1 = read_int () in
let input_arr1 = Scanf.scanf "%d %d %d %d %d\n" (fun a b c d e -> [a]#[b]#[c]#[d]#[e]) in
let rec print_test_case inputs =
match inputs with
|[] ->(print_newline ();print_string "done test case"; print_newline ();)
|hd::tl -> (print_int hd; print_string " "; print_test_case tl)
in print_int number_of_inputs1; print_newline (); print_test_case input_arr1;
(*
let number_of_inputs2 = read_int () in
let input_arr2 = Scanf.scanf "%d %d %d\n" (fun a b c -> [a]#[b]#[c]) in
print_int number_of_inputs2; print_newline (); print_test_case input_arr2;
*)
It prints the following now,
5
1 2 3 4 5
done test case
I need to print something like
5
1 2 3 4 5
done test case
3
6 7 8
done test case
How should I read such formatted input in multiple lines from stdin correctly ?
The original problem I faced is what follows.
I have a problem where the number of test cases t is specified in the first line of the input. The t test cases follow. Each test case is comprised of two lines
line#1: number of inputs n, for this particular test case
line#2: the n input numbers separated by space
I need to do some computation for each test case. Let's assume I just need to print them back to the console with a message "done test case" after each test case output.
For example if the input was the following,
5
3
1 2 3
3
2 1 3
6
3 2 1 5 4 6
4
1 3 4 2
5
3 4 5 1 2
Observe that there are 5 test cases in this problem. The first test case for example, has 3 inputs 1 2 3, and the third one has 6, 3 2 1 5 4 6.
I need to print
1 2 3
done test case
2 1 3
done test case
3 2 1 5 4 6
done test case
1 3 4 2
done test case
3 4 5 1 2
done test case
So far, I have tried the following,
let test_cases = read_int () in (*read the number of test cases*)
let rec print_all_test_cases tc = (*define a function that will call the individual test cases*)
if (tc > 0) (*check if there are more test cases left*)
then
let num_of_inputs = read_int() in (*read the number of inputs*)
let rec read_inputs_for_test_case n arr = (*function to recursively read all inputs for the test case*)
if (n == 0)
then arr (*if everthing is read return the accumulated array*)
else
let i = Scanf.scanf "%d " (fun i -> i) in (*else read the input*)
read_inputs_for_test_case (n-1) (arr # [i]) (*recurse for the remaining inputs, accumulating current input to the argument*)
in
let rec print_test_case inputs = (*print inputs for the test case*)
match inputs with
|[] ->(print_newline ();print_string "done test case"; print_newline ();)
|hd::tl -> (print_int hd; print_string " "; print_test_case tl)
in
print_test_case (read_inputs_for_test_case num_of_inputs []); (*call to read and print inputs*)
print_all_test_cases (tc-1) (*recursively do the remaining test cases*)
else ()
in print_all_test_cases test_cases
It prints the following to stdout
1 2 3
done test case
and fails with the following error on stderr
Fatal error: exception End_of_file
How do read everything correctly and print as required ?
There is no error in your simplified code extract, uncommenting the second part should work if the stdin had the right data.
You should probably test your code with a fixed string data first:
let text = "5
1 2 3 4 5
3
6 7 8
"
let source = Scanf.Scanning.from_string text
let number_of_inputs1 = Scanf.bscanf source "%d\n" (fun n -> n)
let input_arr1 =
Scanf.bscanf source "%d %d %d %d %d\n" (fun a b c d e -> [a;b;c;d;e])
Related
like consider the following python code,
n = 4
if n>3 :
n = 5
if n>2 :
n = 6
if n>1 :
n = 4
How to achieve this in haskell??
let n = 4
main :: IO()
main = do
if n>3 then let n = 5
if n>2 then let n = 6
if n>1 then let n = 4
Tried this but gives an error, looking for some modifications
As I commented there are some points of your program you should checkout
else must be used after if
You don't use let for top level declarations (as in let n = 4).
When you write if n>3 then let n=5 you are not changing the value of n because values are inmutables in Haskell
There are a few "idiomatic" ways you can rewrite your program
Use a chained if then else with prints. This is the closest to your code
n = 4 -- no let in top level binding
main :: IO()
main = do
if n>3 then print 5 -- do not use let n=5 because n can't be mutated
else if n>2 then print 6
else if n>1 then print 4
else print ()
Use an external function and guards. This is the most idiomatic
f :: Int -> Int
f x | x > 3 = 5
| x > 2 = 6
| x > 1 = 4
n = 4
main = do
print (f n)
As #davidflecher commented, you can use guards within a let binding
n = 4
main :: IO()
main = do
let x | n > 3 = 5
| n > 2 = 6
| n > 1 = 4
print x
Use MultyWayIf extension (This is more advance as it needs extensions to the language)
{-# LANGUAGE MultiWayIf #-}
n = 4
main :: IO()
main = do
let x = if | n > 3 -> 5
| n > 2 -> 6
| n > 1 -> 4
print x
While the example is a bit contrived, the usual way to encode an if with multiple branches is to use a case-of with () as the scrutinee as follows:
main :: IO()
main = do
case () of
_ | n > 3 -> ...
| n > 2 -> ...
| otherwise -> ...
or when part of a binding, by use of a guarded let
let x | n > 3 = ...
| n > 2 = ...
| otherwise = ...
Alternatively, this may also be encoded as guards of a helper function
f :: Int -> Int
f n | n > 3 = 5
| n > 2 = 6
| otherwise = 4
Updated to include #Iceland_jack's comment
I need to print a list of integers in Haskell in one line only separated by space...
Like , I would want to print
[6,5,4,7,3,9]
in this manner
6 5 4 7 3 9
I used the Map_ function but that prints all the elements in different lines.
You can try this
main = putStrLn . unwords . map show $ [1,2,3,4]
Instead of unwords you could also use intercalate " " for a more generic function.
You can define a customized print function, which accepts a parameter of separator:
type Separator = String
cPrint :: Show a => Separator -> a -> IO ()
cPrint sep v = putStr $ show v ++ sep
ghci> mapM_ (cPrint " ") [6,5,4,7,3,9]
6 5 4 7 3 9 ghci>
I am working in OCaml and have to do the following problem
7.1 Problem 1 – Number of values less than average
Input: An integer, listlen, followed by listlen number of integer values.
Output: The list of values, number of items on the list, and the number of input values that are less than the average of all the values
Sample input:
Enter the count and the corresponding integer values:
7 10 60 3 55 15 45 40
Corresponding output:
The list:
10 60 3 55 15 45 40
The average:
32.57
Number of values less than average:
3
The idea is to use user input, get a length of numbers to be averaged, get the numbers to be averaged, average them and then tell which numbers from the list are less than the average. My issue comes in trying to add the values given from the user into the array. I was able to create the array but can't figure out what code to use to add the values.
The code I have currently...
(* Prompts the user to enter the number of values they want to average
then gets that number and prints it *)
print_string "Enter The Number of Values You Want To Average:\n";;
let n_values = Scanf.scanf "%d" (fun n -> n);;
Printf.printf "%d\n" n_values;;
(* Prompts the user to enter the numbers they want averaged then
adds those values to an array and prints the numbers *)
print_string "Enter The Values To Be Averaged:\n";;
let a = Array.make n_values 0;;
for i = 0 to Array.length a - 1 do
(*let values = Scanf.scanf "%d" (fun n -> n)*)
a.(i) <- i
done;;
for i = 0 to Array.length a - 1 do
Printf.printf "%i" a.(i);
done;;
(* Adds each of the values of the array together, stores it in sum and then divides by the n_values initialized above and stores in average, then prints this value *)
print_string "\nThe Average:\n";;
let sum = Array.fold_left (+) 0 a;;
let average = sum / n_values;;
Printf.printf "%d\n" average;;
(* Checks which numbers in the array are less than the computed average and increments a counter if it is less*)
print_string "The Number of Values Less Than The Average:\n";;
let counter = ref 0;;
for i = 0 to Array.length a - 1 do
if a.(i) < average then incr counter;
done;;
Printf.printf "%d\n" !counter;;
The code in question is...
let a = Array.make n_values 0;;
for i = 0 to Array.length a - 1 do
(*let values = Scanf.scanf "%d" (fun n -> n)*)
a.(i) <- i
done;;
for i = 0 to Array.length a - 1 do
Printf.printf "%i" a.(i);
done;;
I have tried what is currently commented out w/ adding a.(i) <- values but that did not work and it gave me an error of
Fatal error: exception Scanf.Scan_failure("scanf: bad input at char number 1: character ' ' is not a decimal digit")
If you include the commented out code you have this:
let values = Scanf.scanf "%d" (fun n -> n)
a.(i) <- i
This isn't syntactically valid because it has a let with no in. Your description of the problem isn't specific enough to tell whether that was your problem. If so, you need add in after the right parenthesis in the first line.
If this wasn't your problem, you might note that the second line of code here doesn't use values even though that's pretty much what I would expect it to do. The code as it stands reads a value from stdin, then ignores the value that it read.
If neither of these is your problem, you need to describe your problem more carefully. It's difficult to help if all you say is "it did not work."
I have to write a recursive function the calculates the product of the digits of a number. What I wrote down is:
let rec digits_product x = if x = 0 then 0 else let n = x mod 10 in n * digits_product (x/10)
The problem is that it always returns me 0. I am sure there is something I miss out but I can not find out. Can you help me solve the problem? The code should calculate the product of the digits of a number, for example if I enter 12345 it should return 12345 which is equal to 120.
UPDATE
I changed the code to this:
let rec digits_product x = match x with | 0 -> 0
| 1 -> 1
| 2 -> 2
| 3 -> 3
| 4 -> 4
| 5 -> 5
| 6 -> 6
| 7 -> 7
| 8 -> 8
| 9 -> 9
| _ -> (x mod 10) * digits_product (x/10)
It works right now, but I have another question: is there a more efficient way to do it?
Your code always makes a recursive call unless the parameter x is 0. Since it doesn't show signs of infinite recursion, you know that it is returning 0 at least once. This should be enough to show what is wrong.
Update
You are checking the input for 0 because the answer is obvious in that case. But there are other inputs where the answer is obvious. I.e., where you don't need to do any multiplications to get the result. Why not check for all of these? You can check for all of these values with just one test.
IMO, the syntax would look cleaner like so:
let rec produsul_cifrelor x =
match x with
| n when n < 10 -> n
| _ -> (x mod 10) * produsul_cifrelor (x/10)
Then running produsul_cifrelor 12345 will return 120.
I'm new to haskell and I want to sort list of strings. For example I have a list that is in my variable ff that contain three strings ["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"] and I want to sort them so my result should look like ["1 5 6 8 8", "1 2 3 4", "4 5 7 9 9 9"] Here's my code that perfectly works
import System.IO
import Control.Monad
import Data.List
import Data.Function
import Data.Array
import Data.Char
sortNumeric = sortBy (compare `on` (read :: String -> Int))
wordsWhen :: (Char -> Bool) -> String -> [String]
wordsWhen p s = case dropWhile p s of
"" -> []
s' -> w : wordsWhen p s''
where (w, s'') = break p s'
main = do
file <- readFile "test.txt"
let ff = map ((!!) (lines file)) [1,3..(length (lines file) - 1)]
let splitString = wordsWhen (==' ') (ff!!0)
let sortedResult = sortNumeric (splitString)
print sortedResult
Problem is with this line let splitString = wordsWhen (==' ') (ff!!0) I always get first element of the list, so only first element is sorted. How can I pass all values of a list? Here's what I tryied to do let splitString = wordsWhen (==' ') (ff!![0..(length(ff)-1)]) unfortunately this doesn't work. Any ideas how to solve this problem?
You can do it easily with map and a niftry trick to use words, sort and then unwords (to restore the whitespace).
Prelude> let ff=["1 8 8 5 6", "1 4 2 3", "5 4 9 7 9 9"]
Prelude> import Data.List
Prelude Data.List> map (unwords . sort . words) ff
["1 5 6 8 8","1 2 3 4","4 5 7 9 9 9"]
Edit: Improvement to correctly sort numeric values:
import Data.List
let ff=["11 8 8 5 6", "11 4 2 3", "5 4 9 7 99 9"]
let sortNumeric = (map show) . sort . (map (read :: String -> Int))
map (unwords . sortNumeric . words) ff
result:
["5 6 8 8 11","2 3 4 11","4 5 7 9 9 99"]