searching an element in list in ocaml - ocaml

(* function for union of two ordered sets*)
let rec search n list1 = match list1 with
[] -> false
| head :: tail when head = n -> true
| head :: tail when head != n -> search n tail
;;
(* function calls and output *)
Printf.printf("\nList = {");;
open Printf
let list1=[3;1;2;4];; (* Input first set here *)
let () = List.iter (printf " %d ") list1;;
printf("}");;
n=2;;
let u = search n list1;;
I am getting an error:
File "search.ml", line 15, characters 0-1:
Error: Unbound value n
Line 15 => "n=2;;"
Kindly inform whether it is a syntactic error or otherwise and possible remedy as well. Implementation is done on linux.

Expression n=2 compares n to 2, however n is not defined yet, so you get an error. You should use let n = 2 to bind values to names.

in OCaml to bound a value with a name one should use len name = value syntax

Related

How to count the number of recurring character repetitions in a char list?

My goal is to take a char list like:
['a'; 'a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'b'; 'a'; 'd'; 'd'; 'd'; 'd']
Count the number of repeated characters and transform it into a (int * char) list like this:
[(5, 'a'); (3, 'b'); (1, 'a'); (4, 'd')]
I am completely lost and also am very very new to OCaml. Here is the code I have rn:
let to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
let count = int 0 in
while t <> [] do
if h = t then
count := count + 1;
done;
I am struggling on how to check the list like you would an array in C or Python. I am not allowed to use fold functions or map or anything like that.
Edit: Updated code, yielding an exception on List.nth:
let rec to_run_length (lst : char list) : (int * char) list =
let n = ref 0 in
match lst with
| [] -> []
| h :: t ->
if h = List.nth t 0 then n := !n + 1 ;
(!n, h) :: to_run_length t ;;
Edit: Added nested match resulting in a function that doesn't work... but no errors!
let rec to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
match to_run_length t with
| [] -> []
| (n, c) :: tail ->
if h <> c then to_run_length t
else (n + 1, c) :: tail ;;
Final Edit: Finally got the code running perfect!
let rec to_run_length (lst : char list) : (int * char) list =
match lst with
| [] -> []
| h :: t ->
match to_run_length t with
| (n, c) :: tail when h = c -> (n + 1, h) :: tail
| tail -> (1, h) :: tail ;;
One way to answer your question is to point out that a list in OCaml isn't like an array in C or Python. There is no (constant-time) way to index an OCaml list like you can an array.
If you want to code in an imperative style, you can treat an OCaml list like a list in C, i.e., a linked structure that can be traversed in one direction from beginning to end.
To make this work you would indeed have a while statement that continues only as long as the list is non-empty. At each step you examine the head of the list and update your output accordingly. Then replace the list with the tail of the list.
For this you would want to use references for holding the input and output. (As a side comment, where you have int 0 you almost certainly wanted ref 0. I.e., you want to use a reference. There is no predefined OCaml function or operator named int.)
However, the usual reason to study OCaml is to learn functional style. In that case you should be thinking of a recursive function that will compute the value you want.
For that you need a base case and a way to reduce a non-base case to a smaller case that can be solved recursively. A pretty good base case is an empty list. The desired output for this input is (presumably) also an empty list.
Now assume (by recursion hypothesis) you have a function that works, and you are given a non-empty list. You can call your function on the tail of the list, and it (by hypothesis) gives you a run-length encoded version of the tail. What do you need to do to this result to add one more character to the front? That's what you would have to figure out.
Update
Your code is getting closer, as you say.
You need to ask yourself how to add a new character to the beginning of the encoded value. In your code you have this, for example:
. . .
match to_run_length t with
| [] -> []
. . .
This says to return an empty encoding if the tail is empty. But that doesn't make sense. You know for a fact that there's a character in the input (namely, h). You should be returning some kind of result that includes h.
In general if the returned list starts with h, you want to add 1 to the count of the first group. Otherwise you want to add a new group to the front of the returned list.

Checking elements of a list in SML

Hi I am relatively new to ML/SML and I am trying to write function that takes as input 2 lists. The one list contains 4 random strings ["duck","goose","swan","gull"] and the second takes another 4 strings ["duck","swan","goose","pigeon"].
What I would like to do i check each element in the first list against each element the other. If the strings are in the same position and are equal output a 'yes'. If the elements are not in the same position but are in the list then output 'maybe', and if the element isn't in the second list output 'no'.
So given the 2 examples above it would output ["yes","maybe","maybe","no"].
This is what I have done so far, but I can't figure out how to keep recursively calling the main function, checkEqual, to iterate over the entire first list.
fun buildStringList nil nil = nil
|buildStringList lst appList =
lst # appList
in
fun checkEqual nil nil = nil
| checkEqual code guess =
if hd code = hd guess then
buildStringList ([])(["yes"])
else if hd code = hd(tl guess) then
buildStringList ([])(["maybe"])
else if hd code = hd(tl(tl guess)) then
buildStringList ([])(["maybe"])
else if hd code = hd(tl(tl(tl guess))) then
buildStringList ([])(["maybe"])
else
buildStringList ([])(["no"])
end;
Any help would be greatly appreciated.
There are two code paths, comparing items by index [the "yes" condition] and then comparing them without regard to index [the "maybe" path]. Using recursion and a helper function [or two] allows both code paths to be followed:
val ls1 = ["duck", "goose", "swan", "gull"]
val ls2 = ["duck", "swan", "goose", "pigeon"]
fun checker (list1,list2) =
(* Zipping the two lists together creates
a list of pairs that can be searched
for "yes" values as the first part of the aux function.
It might be worth checking to see if
ListPair.zipEq is more suited to the
needs of a particular appliation. *)
let val zipped = ListPair.zip(list1, list2)
(* find_in_list is called if there is
no "yes" match. It recurses down
list2 with the string from list1
which did not return "yes". *)
fun find_in_list (x, xs) =
case xs
of [] => "no"
| x'::xs' =>
if x' = x
then "maybe"
else find_in_list (x, xs')
(* This function could be the main body
of checker, but instead it trampolines.
First it checks for "yes". Either appends
"yes" onto a recursive call to itself or
otherwise appends a call to find_in_list
onto a recursive call to itself.
The type checker wants an explicit type
for lop because the record is being accessed
with #1 and #2 *)
fun aux (lop : (string * string) list) =
case lop
of [] => []
| x'::xs' =>
if #1 (hd lop) = #2 (hd lop)
then "yes"::aux (tl lop)
else (find_in_list (#1 (hd lop), list2))::(aux (tl lop))
in aux(zipped) end
checker (ls1,ls2) (* returns ["yes", "maybe", "maybe", "no"] *)

Error in code to flatten a list in Ocaml

Hello All I am trying to flatten a list in Ocaml. I am a newbie so please pardon me if my mistake is dumb
So for example, if input is [[1];[2;3];[4]] I should end up with [1;2;3;4].
The idea I am trying to use is as follows
Iterate through the list from the right (Using fold_right) with accumaltor = []
The pseudo code is as follows
func flatten(list, accumalator)
For each item from right to left in list
If Item is a scalar then n :: accumalator
Else fi Item is a list of form head :: tail then
head :: flatten (tail, accumalator).
I think that theoretically the algorithm is correct, but please let me know if you disagree.
Now to my OCaml code to implement this algorithm
let rec flatten acc x =
match x with
n -> n :: acc
| [x] -> x :: acc
| head :: remainder ->
head :: ( my_flat acc remainder )
and my_flat = List.fold_right flatten
;;
my_flat [] [[1];[2;3];[4]]
The Error I get is the following
Error: This expression has type 'a but an expression was expected of type
'a list
The error occurs on the line that reads head :: ( my_flat acc remainder ) in the last pattern in the match statement
Any help is appreciated.
In OCaml, all the elements of a list must be the same type. Thus the value [1; [2; 3]; 4] is invalid all by itself. It contains two elements that are of type int and one element of type int list. In essence, your statement of the problem to be solved is impossible.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
This sounds like a homework problem, so I'll just say that restricting yourself to lists that are valid in OCaml may make it easier to solve.
Edit
OK, the problem can now be solved!
The essence of the reported type error is something like this. You have your accumulated result acc (of type int list in the example). You want to add the list x (also of type int list) to it. You've broken x into head (an int) and remainder (an int list). As you can see, remainder is not a suitable argument for your my_flat function. It wants an int list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go to flatten and not to my_flat.
Another problem I see: the arguments of List.fold_right are: a function, a list, and a starting value. In your test call to my_flat, you're supplying the last two in the other order. The empty list [] is your starting value.
I hope this is enough to get you going. Since you're just starting out with OCaml there will probably be another problem or two before it works.
Edit 2
Here are a couple more comments, which might be spoilers if you're still working on your own solution....
A tidier version of your function my_flat is in the OCaml standard library under the name List.flatten. It's interesting to look at the implementation:
let rec flatten = function
[] -> []
| l::r -> l # flatten r
I'd call this a very elegant solution, but unfortunately it's not tail recursive. So it will consume some (linear) amount of stack space, and might even crash for a very long list.
Here's one based on the same idea, using the standard FP accumulator trick to get tail recursive behavior (as noted by Thomas):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.
You can start by writing directly your algorithm, by decomposing the base cases of your input value, ie. the input list is either empty, or the head of the input list is empty, or the head of the input list has a head and a tail:
let rec flatten = function
| [] -> []
| [] :: t -> flatten t
| (x::y) :: t -> x :: (flatten (y::t))
You can then optimize the function, because this code is not tail-recursive and thus will crash when lists become too big. So you can rewrite this by using the usual technique:
let flatten list =
let rec aux accu = function
| [] -> accu
| [] :: t -> aux accu t
| (x::y) :: t -> aux (x::accu) (y::t) in
List.rev (aux [] list)
So my advice is: start by decomposing your problem based on the input types, and then later use accumulators to optimize your code.
I like this one, where the auxiliary function takes the accumulator, the first element of the list of lists, and the rest of the list of lists, it is clearer for me :
let flatten list =
let rec aux acc list1 list2 =
match list1 with
| x :: tail -> aux (x :: acc) tail list2
| [] ->
match list2 with
| [] -> List.rev acc
| x :: tail -> aux acc x tail
in
aux [] [] list
Thanks for all your help
Here is the code I used to solve this problem
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> head :: ( flatten_each acc remainder )
in
List.fold_right flatten_each ( List.rev list ) []
;;
Edit: as pointed out by Thomas this solution is not tail recursive. Tail recursive version is below
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> (flatten_each (acc # [head]) remainder )
in
List.fold_right flatten_each list []
;;

Ocaml function to convert a tuple into a list

I have an (int * string) tuple which I want to covert into a list. The tuple is of the form (N, E) where is N is the number of occurances of element E.
The function should return a list with N occurences of E in it. Example is below. Lets assume this function is called tuple_decode.
tuple_decode (1, "A") -> ["A"]
tuple_decode (2,"B") -> ["B";"B"]
tuple_decode (4,"C") - > ["C";"C";"C";"C"]
The tuple_decode function is as follows
let tuple_decode acc (n,elem) =
let add_one_elem i =
match i with
0 -> acc
| i -> elem :: acc ; add_one_elem (i-1) (* Line 184 *)
in
add_one_elem n
;;
when I try to compile this function I get the following error.
File "all_code.ml", line 184, characters 11-22:
Warning 10: this expression should have type unit.
File "all_code.ml", line 184, characters 25-37:
Error: Unbound value add_one_elem
Could someone help me figure out why I get this error and warning.
Regards
Puneet
The warning comes from sequence composition using ;. When you write S1 ; S2, the compiler expects S1 to have unit type. But here S1 returns a list (elem::acc) whose value will be thrown away. Moreover, since you didn't pass acc as an argument, its value doesn't change after all recursive calls.
The error is due to recursive use of add_one_elem. Because you didn't use rec keyword, when add_one_elem (i-1) is called, OCaml doesn't know add_one_elem is being recursively defined.
Moreover, acc should be a parameter of add_one_elem to accumulate results:
let tuple_decode (n, elem) =
let rec add_one_elem i acc =
match i with
| 0 -> acc
| i -> add_one_elem (i-1) (elem::acc)
in add_one_elem n []
As #pad has already answered your question sufficiently, a nice solution would also be:
let decode (n, elem) = List.init n (fun _ -> elem)

Ocaml introduction

i'm trying to learn ocaml right now and wanted to start with a little program, generating all bit-combinations:
["0","0","0"]
["0","0","1"]
["0","1","0"]
... and so on
My idea is the following code:
let rec bitstr length list =
if length = 0 then
list
else begin
bitstr (length-1)("0"::list);
bitstr (length-1)("1"::list);
end;;
But i get the following error:
Warning S: this expression should have type unit.
val bitstr : int -> string list -> string list = <fun>
# bitstr 3 [];;
- : string list = ["1"; "1"; "1"]
I did not understand what to change, can you help me?
Best regards
Philipp
begin foo; bar end executes foo and throws the result away, then it executes bar. Since this makes only sense if foo has side-effects and no meaningful return value ocaml emits a warning if foo has a return value other than unit, since everything else is likely to be a programmer error (i.e. the programmer does not actually intend for the result to be discarded) - as is the case here.
In this case it really does make no sense to calculate the list with "0" and then throw it away. Presumably you want to concatenate the two lists instead. You can do this using the # operator:
let rec bitstr length list =
if length = 0 then
[list]
else
bitstr (length-1)("0"::list) # bitstr (length-1)("1"::list);;
Note that I also made the length = 0 case return [list] instead of just list so the result is a list of lists instead of a flat list.
Although sepp2k's answer is spot on, I would like to add the following alternative (which doesn't match the signature you proposed, but actually does what you want) :
let rec bitstr = function
0 -> [[]]
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in
(f "0" l)#(f "1" l);;
The first difference is that you do not need to pass an empty list to call the function bitsr 2 returns [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Second, it returns a list of ordered binary values. But more importantly, in my opinion, it is closer to the spirit of ocaml.
I like to get other ideas!
So here it is...
let rec gen_x acc e1 e2 n = match n with
| 0 -> acc
| n -> (
let l = List.map (fun x -> e1 :: x) acc in
let r = List.map (fun x -> e2 :: x) acc in
gen_x (l # r) e1 e2 (n - 1)
);;
let rec gen_string = gen_x [[]] "0" "1"
let rec gen_int = gen_x [[]] 0 1
gen_string 2
gen_int 2
Result:
[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]
[[0; 0]; [0; 1]; [1; 0]; [1; 1]]