The objective of this code is to given a number realise multiple operations until the number is equal to 42. I'm not being able to make let rec read read_int
let n = read_int ()
let rec check n =
if n < 42 then begin Printf.printf "bad luck" end
else if n = 42 then begin Printf.printf "u win" end
else if n mod 5 = 0 then begin check (n - 42) end
you don't need to have begin/end when you only have a single expression
if you want to call read_int each time you call check, then:
check does not need to accept a parameter n
you have to call read_int () inside the body of check
if however you want to call check with a value initially read from standard input, then passed by recursive invocations of check, then you need:
a purely functional (recursive) function check accepting a parameter n
another function check_input that reads standard input and pass the value to check
Related
I have been trying to create a cycle to call an changing function i-times , but for some reason the cycle itself always spits out an error. I have also tried an recursive function to call itself but didn't work either.
Is it even possible to make it work with for`s.
r is a list of lists.
a and b are two immutable variables.
(List.nth (r) (i)) gives an list.
let rec changing (lista: 'a zlista) (a:int) (b:int) =
match lista with
| Vazio -> failwith "NO"
| Nodo (n, l, r) ->
if a <= n && n <= b then n
else if a < n && b < n then changing l a b
else changing r a b
let rec call_changing (a: int) (b: int) =
for i=0 to ort do
changing (List.nth (r) (i)) (a) (b)
done;;
Changing returns an int, in order to call it in a for loop you have to ignore the result of the function :
for i = 0 to ort do
let _ = changing .... in ()
done
(* Or *)
for i = 0 to ort do
ignore (changing ....)
done
EDIT :
If you want to print the result you can do :
for i = 0 to ort do
Printf.printf "Result for %d iteration : %d\n" i (changing ....)
done
See the Printf documentation for more information
To perhaps generalize on Butanium's answer, OCaml is not a pure functional programming language. It does contain imperative features. Imperative features are all about side-effects. Functions which exist for the purpose of their side-effects on the system (like Printf.printf) by convention return () (the literal for the unit type).
A for loop is an imperative feature. As such, it expects that any expression (or expessions chained with ;) contained within will return unit. If they do not, you will receive warnings.
The for loop expression itself (for ... = ... to ... do ... done) returns unit so the warning can clue you in that any code in the loop which does not have side-effects is inconsequential, and while your code will compile and run, it may not do what you expect.
As a side note, I believe you may be a little overzealous with the parentheses, likely making your code harder to read.
let rec call_changing (a: int) (b: int) =
for i=0 to ort do
changing (List.nth (r) (i)) (a) (b)
done;;
Properly indented and with extraneous parens removed:
let rec call_changing (a: int) (b: int) =
for i=0 to ort do
changing (List.nth r i) a b
done;;
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
Suppose I am writing an OCaml program and my input will be a large stream of integers separated by spaces i.e.
let string = input_line stdin;;
will return a string which looks like e.g. "2 4 34 765 5 ..." Now, the program itself will take a further two values i and j which specify a small subsequence of this input on which the main procedure will take place (let's say that the main procedure is the find the maximum of this sublist). In other words, the whole stream will be inputted into the program but the program will only end up acting on a small subset of the input.
My question is: what is the best way to translate the relevant part of the input stream into something usable i.e. a string of ints? One option would be to convert the whole input string into a list of ints using
let list = List.map int_of_string(Str.split (Str.regexp_string " ") string;;
and then once the bounds i and j have been entered one easily locates the relevant sublist and its maximum. The problem is that the initial pre-processing of the large stream is immensely time-consuming.
Is there an efficient way of locating the small sublist directly from the large stream i.e. processing the input along with the main procedure?
OCaml's standard library is rather small. It provides necessary and sufficient set of orthogonal features, as should do any good standard library. But, usually, this is not enough for a casual user. That's why there exist libraries, that do the stuff, that is rather common.
I would like to mention two the most prominent libraries: Jane Street's Core library and Batteries included (aka Core and Batteries).
Both libraries provides a bunch of high-level I/O functions, but there exists a little problem. It is not possible or even reasonable to try to address any use case in a library. Otherwise the library's interface wont be terse and comprehensible. And your case is non-standard. There is a convention, a tacit agreement between data engineers, to represent a set of things with a set of lines in a file. And to represent one "thing" (or a feature) with a line. So, if you have a dataset where each element is a scalar, you should represent it as a sequence of scalars separated by a newline. Several elements on a single line is only for multidimensional features.
So, with a proper representation, your problem can be solve as simple as (with Core):
open Core.Std
let () =
let filename = "data" in
let max_number =
let open In_channel in
with_file filename
~f:(fold_lines ~init:0
~f:(fun m s -> Int.(max m ## of_string s))) in
printf "Max number is %s is %d\n" filename max_number
You can compile and run this program with corebuild test.byte -- assuming that code is in a file name test.byte and core library is installed (with opam install core if you're using opam).
Also, there exists an excellent library Lwt, that provides a monadic high-level interface to the I/O. With this library, you can parse a set of scalars in a following way:
open Lwt
let program =
let filename = "data" in
let lines = Lwt_io.lines_of_file filename in
Lwt_stream.fold (fun s m -> max m ## int_of_string s) lines 0 >>=
Lwt_io.printf "Max number is %s is %d\n" filename
let () = Lwt_main.run program
This program can be compiled and run with ocamlbuild -package lwt.unix test.byte --, if lwt library is installed on your system (opam install lwt).
So, that is not to say, that your problem cannot be solved (or is hard to be solved) in OCaml, it is just to mention, that you should start with a proper representation. But, suppose, you do not own the representation, and cannot change it. Let's look, how this can be solved efficiently with OCaml. As previous examples represent, in general your problem can be described as a channel folding, i.e. an consequential application of a function f to each value in a file. So, we can define a function fold_channel, that will read an integer value from a channel and apply a function to it and the previously read value. Of course, this function can be further abstracted, by lifting the format argument, but for the demonstration purpose, I suppose, this will be enough.
let rec fold_channel f init ic =
try Scanf.fscanf ic "%u " (fun s -> fold_channel f (f s init) ic)
with End_of_file -> init
let () =
let max_value = open_in "atad" |> fold_channel max 0 in
Printf.printf "max value is %u\n" max_value
Although, I should note that this implementation is not for a heavy duty work. It is even not tail-recursive. If you need really efficient lexer, you can use ocaml's lexer generator, for example.
Update 1
Since there is a word "efficient" in the title, and everybody likes benchmarks, I've decided to compare this three implementations. Of course, since pure OCaml implementation is not tail-recursive it is not comparable to others. You may wonder, why it is not tail-recursive, as all calls to fold_channel is in a tail position. The problem is with exception handler - on each call to the fold channel, we need to remember the init value, since we're going to return it. This is a common issue with recursion and exceptions, you may google it for more examples and explanations.
So, at first we need to fix the third implementation. We will use a common trick with option value.
let id x = x
let read_int ic =
try Some (Scanf.fscanf ic "%u " id) with End_of_file -> None
let rec fold_channel f init ic =
match read_int ic with
| Some s -> fold_channel f (f s init) ic
| None -> init
let () =
let max_value = open_in "atad" |> fold_channel max 0 in
Printf.printf "max value is %u\n" max_value
So, with a new tail-recursive implementation, let's try them all on a big-data. 100_000_000 numbers is a big data for my 7 years old laptop. I've also added a C implementations as a baseline, and an OCaml clone of the C implementation:
let () =
let m = ref 0 in
try
let ic = open_in "atad" in
while true do
let n = Scanf.fscanf ic "%d " (fun x -> x) in
m := max n !m;
done
with End_of_file ->
Printf.printf "max value is %u\n" !m;
close_in ic
Update 2
Yet another implementation, that uses ocamllex. It consists of two files, a lexer specification lex_int.mll
{}
let digit = ['0'-'9']
let space = [' ' '\t' '\n']*
rule next = parse
| eof {None}
| space {next lexbuf}
| digit+ as n {Some (int_of_string n)}
{}
And the implementation:
let rec fold_channel f init buf =
match Lex_int.next buf with
| Some s -> fold_channel f (f s init) buf
| None -> init
let () =
let max_value = open_in "atad" |>
Lexing.from_channel |>
fold_channel max 0 in
Printf.printf "max value is %u\n" max_value
And here are the results:
implementation time ratio rate (MB/s)
plain C 22 s 1.0 12.5
ocamllex 33 s 1.5 8.4
Core 62 s 2.8 4.5
C-like OCaml 83 s 3.7 3.3
fold_channel 84 s 3.8 3.3
Lwt 143 s 6.5 1.9
P.S. You can see, that in this particular case Lwt is an outlier. This doesn't mean that Lwt is slow, it is just not its granularity. And I would like to assure you, that to my experience Lwt is a well suited tool for a HPC. For example, in one of my programs it processes a 30 MB/s network stream in a real-time.
Update 3
By the way, I've tried to address the problem in an abstract way, and I didn't provide a solution for your particular example (with j and k). Since, folding is a generalization of the iteration, it can be easily solved by extending the state (parameter init) to hold a counter and check whether it is contained in a range, that was specified by a user. But, this leads to an interesting consequence: what to do, when you have outran the range? Of course, you can continue to the end, just ignoring the output. Or you can non-locally exit from a function with an exception, something like raise (Done m). Core library provides such facility with a with_return function, that allows you to break out of your computation at any point.
open Core.Std
let () =
let filename = "data" in
let b1,b2 = Int.(of_string Sys.argv.(1), of_string Sys.argv.(2)) in
let range = Interval.Int.create b1 b2 in
let _,max_number =
let open In_channel in
with_return begin fun call ->
with_file filename
~f:(fold_lines ~init:(0,0)
~f:(fun (i,m) s ->
match Interval.Int.compare_value range i with
| `Below -> i+1,m
| `Within -> i+1, Int.(max m ## of_string s)
| `Above -> call.return (i,m)
| `Interval_is_empty -> failwith "empty interval"))
end in
printf "Max number is %s is %d\n" filename max_number
You may use the Scanf module family of functions. For instance, Scanf.fscanf let you read tokens from a channel according to a string format (which is a special type in OCaml).
Your program can be decomposed in two functions:
one which skip a number i of tokens from the input channel,
one which extract the maximum integer out of a number j from a channel
Let's write these:
let rec skip_tokens c i =
match i with
| i when i > 0 -> Scanf.fscanf c "%s " (fun _ -> skip_tokens c ## pred i)
| _ -> ()
let rec get_max c j m =
match j with
| j when j > 0 -> Scanf.fscanf c "%d " (fun x -> max m x |> get_max c (pred j))
| _ -> m
Note the space after the token format indicator in the string which tells the scanner to also swallow all the spaces and carriage returns in between tokens.
All you need to do now is to combine them. Here's a small program you can run from the CLI which takes the i and j parameters, expects a stream of tokens, and print out the maximum value as wanted:
let _ =
let i = int_of_string Sys.argv.(1)
and j = int_of_string Sys.argv.(2) in
skip_tokens stdin (pred i);
get_max stdin j min_int |> print_int;
print_newline ()
You could probably write more flexible combinators by extracting the recursive part out. I'll leave this as an exercise for the reader.
I am trying to achieve the following: Finding the element at a specific index.
So if I had a list of [5; 2; 3; 6] and ask for the element at index 2, it would return 3.
let counter = 0;;
let increase_counter c = c + 1;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (counter = n) then
h
else
increase_counter counter ; get_val t n
;;
But this code is giving me a bug saying that -1 is not of type 'unit'?
As Jeffrey Scofield said, you should write let counter = ref 0 to make counter mutable. Now, you can use the built in incr function to increment it (equivalent to counter := !counter + 1), and you'll get its value with !counter.
There is also a problem in your algorithm : if the counter is equal to n, you return the head of the list... you mean : if the head of the list is equal to n, you return the counter.
Your program is then :
let counter = ref 0;;
let rec get_val x n = match x with
[] -> -1
| (h::t) ->
if (h = n) then
!counter
else
begin incr counter ; get_val t n end
;;
Note that I've added begin and end around the else block so it can be interpreted as a sequence of instructions.
Your program now works, but it is not the best way to solve this problem with ocaml.
You should write something like
let get_val x n =
let rec get_val_aux x n counter = match x with
| [] -> -1
| h :: _ when h = n -> counter
| _ :: t -> get_val_aux t n (succ counter)
in
get_val_aux x n 0
;;
Here, we add a parameter to the get_val_aux function which we increment at each call. This function is nested within the get_val function to hide this additional parameter which is initialized with 0 on the first call.
Instead of using an if statement, we use the when condition to know when the element has been found, and add a new case to match the last case (not found). Note the use of the _ wildcard to avoid an unused variable.
The succ function (for successor) only adds 1 to its parameter. It is equivalent to counter + 1.
There are many problems with this code. If you ignore your immediate problem for a moment, you are treating OCaml variables like the variables of an imperative language. However, OCaml variables are immutable. This function
let increase_counter c = c + 1
Doesn't change the value of any variable. It just returns a number 1 bigger than what you give it.
The only error I get from the toplevel when I enter your code is for this expression:
increase_counter counter ; get_val t n
The compiler is warning you that the expression before ; is supposed to be executed for its side effects. I.e., it should almost always have type unit. Since (as I say) your function increase_counter returns an int, the compiler is warning you about this.
getChar :: Int -> IO Char
getChar n = do
c <- getLine
return (c !! n)
The program must needs a number and a line and it will return char, but how do I catch exception, if the number is too big?
I tried like this but it doesnt seem to work
getChar n
= do
c <-getLine
| n>=0 && n < b
= return c !! n
| otherwise
= error "Too big number"
where
b = length c
This is not a homework, im trying to involve myself. Google didint give me useful answers
Couldn't implement catch in there. Examples?
You probably want to restructure things a bit as you've got IO mixed up in something it doesn't have to be. What about changing the signature to something like this?
getChar :: Int -> String -> Maybe Char
getChar n x | n < length x = Just (x !! n)
| otherwise = Nothing
Data.Maybe allows you to indicate that you are either going to return something (e.g. the length is within range) or Nothing (the length isn't within range). The function that calls getChar can then decide what to do with things. Data.Either provides a way of returning an error message with an error instead. From what I've seen (and I'm by no means an expert) exceptions are rarely used in Haskell, and choice types such as Either or Maybe are much more commonly used.
Now in the code that calls this, you can use pattern matching to see what happened e.g.
main :: IO ()
main = do
x <- getLine
let z = getChar' 5 x
case z of
(Just z) -> print $ "The 5th character is " ++ show z
Nothing -> print $ "The 5th character is out of range"
You can use the drop function to drop the first n characters of the line (drop will just give an empty result if there are fewer than n chars), and the listToMaybe function to turn a list to a Maybe (either Just c where c is the first element of the list, or Nothing if the list is empty):
import Data.Maybe (listToMaybe)
getchar :: Int -> IO (Maybe Char)
getchar n = do
line <- getLine
return . listToMaybe . drop n $ line
getChar' :: Int -> IO Char
getChar' n =
do
c <- getLine
if (n < length c)
then
return (c !! n)
else
getChar' n
You can do something like above. This is just an example though. But, since you are a beginner, it is strongly recommended not to play with IO and Monads. You can come to it after you get familiarized with pure functional concepts.