How to add user input values to an array in Ocaml - ocaml

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."

Related

Display the Two Maximum Numbers in a List in Oz Programming language

I need to make a program that displays the two maximum numbers in a list using Oz programming language. I have the code for printing the maximum number in a list, but I need the two biggest numbers. Here is what I have so far:
fun {Max L1}
case L1
of nil then 0
[] X|Xr then
if X>{Max Xr} then X
else {Max Xr}
end
end
end
{Browse {Max [1 2 3 4 5 6 7 8 9]}}
This will display the biggest number in the list, but only one and I need the two biggest numbers to display. What do I need to do?
There are many ways in Mozart-Oz to solve that problem. This is one possible solution which is extended to a list of size (length) N; however, only works for possitive numbers.
proc {LengL Ls N R}
case Ls
of nil then N = R
[] L|Lr then {LengL Lr N+1 R}
end
end
proc {Drop1 L Y R}
R=case L
of nil then nil
[] X|Xr then
if X\=Y then X|{Drop1 Xr Y}
else {Drop1 Xr Y}
end
end
end
proc {MaxN L1 N R1}
proc {Max1 L R}
R=case L
of nil then 0
[] X|Xr then
if X>{Max1 Xr} then X
else {Max1 Xr}
end
end
end
R2={Max1 L1} Lg={LengL L1 0} in
R1={proc {$ R}
R=if N==0 then nil
elseif N>Lg then R2|{MaxN {Drop1 L1 R2} Lg-1}
else R2|{MaxN {Drop1 L1 R2} N-1}
end
end}
end
{Browse {MaxN [~11 2 3 4 15 6 7 8 9] 12}}
Notice the behavior of MaxN, when N is greater than the length of the list of numbers L1, the browser displays a list of length L1 with the first N biggest numbers. Negative numbers are replaced by zero. I hope this is still useful.

How to print unsigned 64 bit integer

I'm tackling this smallest multiple problem on Kattis.
I've solved it in Python and C++, but now I want to do OCaml.
Here's my code:
open Printf;;
let rec gcd (a : int64) (b : int64) : int64 =
if not (Int64.unsigned_compare b 0L > 0) then
a
else
gcd b (Int64.unsigned_rem a b);;
try
while true;
do
let line = read_line ()
in
if String.length line > 0 then
let (nums : int64 list) = List.map (fun (s:string) : (int64) ->
(Int64.of_string (Char.escaped '0' ^ Char.escaped 'u' ^ s ))) (String.split_on_char ' ' line)
in
let rec reduce (li : int64 list) (init : int64) : (int64) =
match li with
| [] -> init
| head :: tail -> reduce tail ( Int64.unsigned_div (Int64.mul head init) (gcd head init) )
in
print_string ( Int64.to_string (reduce nums 1L) ^ "\n")
else
raise End_of_file
done;
with End_of_file -> ();;
I can get the first case to pass, but the second (and final) case results in a wrong answer. This is weird since my logic is the same in my two earlier submissions of different languages.
My guess is that I'm incorrectly printing unsigned 64 bit integers:
print_string ( Int64.to_string (reduce nums 1L) ^ "\n")
Earlier, I've tried:
printf "%Lu\n" (reduce nums 1L)
But the Printf documentation says
u, n, l, L, or N: convert an integer argument to unsigned decimal. Warning: n, l, L, and N are used for scanf, and should not be used for printf.
and I actually don't think this warning is relevant in my case, but I'm still weary.
Any thoughts? Thanks for reading!
Your code works for me. You might consider restarting OCaml from scratch, then copy/pasting the above code. That's what I did, and it worked for me.
. . .
with End_of_file -> ();;
2 3 5
30
1 2 3 4
12
399 772 163 959 242
832307365428
- : unit = ()
#
I have a 64-bit system, for what it's worth. I.e., max_int is 4611686018427387903 for me.
466941151233371166 isn't a multiple of any of the inputs so that is clearly wrong. The input numbers are rather large so my guess is you simply have an integer overflow. On the other hand your C++ code says 1, which also isn't a multiple of any of the numebrs and also clearly wrong.
I can see one spot that is likely the problem:
( Int64.unsigned_div (Int64.mul head init) (gcd head init) )
As you process the input the init gets larger and larger and you multiply it by the next number. Only after you divide it by th GCD. It temporarily exceeds 64bit in that step and you loose bits.
By the definition of the GCD both head and init are divisible by it. So why not divide one of them by the GCD before the multiplication:
(Int64.mul init (Int64.unsigned_div head (gcd head init)))
That way you never have an intermediate number larger than the result and results that come close to the 64bit limit still produce the right result.

Trim an infinite list of random numbers

I'm trying to trim a list of random numbers so that sum of the numbers in [0,1] in the resulting smaller list accumultates to a value under 1.
This is interesting in a sense that average of these list prefix lengths is e, somehow.
While getting the length of prefix I encountered a problem - I managed to get the program to work on a determined infinite list, or a slice of random list, but the program hangs on infinite random list. What am I doing wrong?
import System.Random
-- Count list items that accumulate to 1.
count :: (Num a, Ord a) => [a] -> Int
count xs = 1 + length xs'
where xs'= takeWhile (< 1) $ scanl1 (+) xs
-- Works of infinite list
a = (return (repeat 0.015)) :: IO [Double]
fa = fmap count a
--67
-- Works on trimmed list of randoms
rio = randomRIO (0::Double, 1)
b = sequence $ take 10 (repeat rio)
fb = fmap count b
-- fb is usually 2 to 5
-- Hangs on infinite list of randoms
c = sequence (repeat rio)
fc = fmap count c
-- fc hangs... ;(
You can define an IO action to create an infinite stream of ranged random numbers like so:
import System.Random
randomRIOs :: (Random a) => (a, a) -> IO [a]
randomRIOs (a, b) = randomRs (a, b) <$> newStdGen
After which, the following works fine with your definition of count:
main = do
n <- count <$> randomRIOs (0::Double, 1)
print n
You can't really have an infinite list of random numbers, because randomness is too strict. So, you can't have the call to sequence outside of your call to count. One obvious thing you could try would be a partial reimplementation of sequence inside of count itself:
count :: (Num a, Ord a, Monad m) => [m a] -> m (Maybe Int)
count = go 0 0
where go n total [] = pure Nothing
go n total (x:xs) = do
num <- x
let total' = total + num
n' = succ n
if total' >= 1
then pure $ Just n'
else go n' total' xs
I've also amended the result to return a Maybe, because it seems wrong to return 1 for an empty list (as yours did), or return the length of a list even if its elements sum to something less than 1.
Another reasonable change would be to not accept [m a], but just a single m a, which can reliably produce a value any number of times. Then we don't have to worry about the input running out, and so no Maybe is needed:
count :: (Num a, Ord a, Monad m) => m a -> m Int
count m = go 0 0
where go n total = do
num <- m
let total' = total + num
n' = succ n
if total' >= 1
then pure n'
else go n' total'
Then you can simply call count $ randomRIO (0::Double, 1), and it will produce as many random numbers as are needed.

Reading formatted input test cases from stdin :: OCaml

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])

Syntax Error In OCaml Multiply Function

I wrote a function that is giving me a syntax error, not exactly sure why. You can skip to the bottom of this and read the code and error, the rest of the stuff in here is just more information that might not be needed.
I have to make a multiply numbers function that multiplies two lists of numbers and returns the result as a list.
let bigMul l1 l2 =
let f a x = failwith "to be implemented" in
let base = failwith "to be implemented" in
let args = failwith "to be implemented" in
let (_, res) = List.fold_left f base args in
res
It multiplies by pretending representing big ints as lists so 1234x24 is [1;2;3;4] x[2;4] It uses several functions that I already wrote and tested. One is mulByDigit which multiplies each int in a list by an int and returns a list such as [2;3;4;5] 1 would return [2;3;4;5]. It also uses padZero which takes 2 lists of ints and makes them equal in length by adding zeroes to the shorter one and returns a tuple with both lists ex [1;2;3] and [1] would return a tuple with ([1;2;3],[0;0;1]). The last function bigAdd takes 2 lists and adds them and returns the result so like for [1;2;3] [1;2;3] it would give [2;4;6]. All of those functions have been tested and work correctly so Im not gonna provide the code for them.
I wrote a function which follows the logic of taking list l1, multiplying it by every digit of l2 with trailing zeroes depending on the digit and maintaining the sum. Ex if list 1 is [1;2;3;4] and l2 is [2;4] i take the second list and reverse it first of all to get [4;2] and then i multiply 1234 by 4 and get the result. I add this result to the current value in the accumulator which is nothing at first and increment the i to let me know to have a trailing zero for the next one. Then i take the 2 remaining and multiply it by 1234 and have a trailing zero so 24680. I add this to my old accumulator to get the final value and return the value when there are no more numbers left in l2. So 1234+24680=25914. Here is the function that I wrote. a is the accumulator in it, i is for keeping track of how many zeroes I need
let bigMul l1 l2 =
let f (i,a) x =
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with
| (y,z)->(y,z) in
( i+1, ( bigAdd first second ) ) in
let base = (0,[]) in
let args = List.rev ( l2 ) in
let (_, res) = List.fold_left f base args in
res
im getting a syntax error when i run it that says unbound value l2. Not sure why so any thoughts.
Here's what I see:
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with
There are two in keywords in a row there.
For what it's worth, this:
let (first,second) = match sum with
| (y,z)->(y,z)
in
Is equivalent to:
let (first, second) = sum in
Found it : I wrote in twice
let sum = padZero ( (mulByDigit x l1)#(clone 0 i) ) a in
in let (first,second) = match sum with