OCaml How to reverse only even values in list - ocaml

I want to transefer something like this:
[0,1,2,3,4,5,6,7]
into
[6,1,4,3,2,5,0,7]

Here's a draft, that reverses the elements at even positions (which is what I assume you meant by your question). This is probably far from optimal (e.g. you should make split and join tail-recursive):
let rec split = function
| [] -> [],[]
| h::[] -> [h],[]
| x::y::t -> let a,b = split t in x::a, y::b;;
let rec join a b = match a,b with
| [],_ -> b
| _,[] -> a
| ha::ta,hb::tb -> ha::hb::(join ta tb);;
let doit l = let a,b = split l in join a (List.rev b);;

Related

F# match pattern discriminator not defined issue

im in the process of writing a transposing recursive function and i have stopped at a problem. So i want to have a check using match by calling isTable function to verify that the input M is a valid table, however it errors and im not sure how to fix it
let isTable list =
match List.map List.length list |> List.distinct |> List.length with
| 1 -> true
| _ -> false
let rec transpose M =
match M with
| []::_ -> []
| (isTable M) -> [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
error FS0039: The pattern discriminator 'isTable' is not defined.
Active patterns are one approach, but the overhead of adding one just for a single use is not worth it. An easy and uncluttered solution would be to use a when clause:
let rec transpose M =
match M with
| []::_ -> []
| _ when isTable M -> []
| _ -> (List.map List.head M::transpose(List.map List.tail M))
None of the answers yet show how to turn your case into an Active Pattern. This is particularly useful for (1) readability and (2) reusability of code. Assuming you'd need isTable more than once, this can be beneficial.
/// Active pattern, must start with capital letter.
let (|IsTable|_|) list =
match List.map List.length list |> List.distinct with
| [_] -> Some list
| _ -> None
let rec transpose M =
match M with
| []::_ -> []
| IsTable M -> [] // using the active pattern
| _ ->
List.map List.head M::transpose(List.map List.tail M)
As an aside, your isTable function matched over List.length result. A List.length iterates over the whole list and is O(n). Since we're only interested if the result is one item, the above approach will be more efficient, removing at least one iteration from the code.
Try something like
let rec transpose M =
match M with
| []::_ -> []
| _ -> match (isTable M) with
| true - > [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
As a matter of programming style I'd recommend adding a data constructor like Table so that you can match on it but this should get things working.

Create a list with data extracted from a list of tuples - type issue

My data is ordered like this:
([(x1,y1,z1);(x2,y2,z2);(x3,y3,z3);........;(xn,yn,zn)], e:int)
Example: I try to create a list [x1;x2;x3;....;xn;e] where a value is found only once.
I began the following code but I encounter an issue with type.
let rec verifie_doublons_liste i liste = match liste with
| [] -> false
| head::tail -> i = head || verifie_doublons_liste i tail
let rec existence_doublon liste = match liste with
| [] -> false
| head::tail -> (verifie_doublons_liste head tail) ||
existence_doublon tail
let premier_du_triplet (x,y,z) = x
let deuxieme_du_triplet (x,y,z) = y
let troisieme_du_triplet (x,y,z) = z
let rec extract_donnees l = match l with
| [] -> []
| (x,y,z)::r -> (extract_donnees r)##(x::z::[])
let arrange donnees = match donnees with
| [],i -> i::[]
| (x,y,z)::[],i -> x::z::i::[]
| (x,y,z)::r,i -> (extract_donnees r)##(x::z::i::[])
Basically, you want to extract first elements in a list of tuples, and add the e elemnent at the end.
The easiest way is to use a List.map to extract the first elements
List.map premier_du_triplet
is a function that will take a list of 3-tuples and extract the first element of each.
then you can add the e element at the end using the "#" operator.
The more efficient and informative way would be to directly write a recursive function, say f that does just what you want.
When writing a recursive function, you need to ask yourself two things
what does it do in the simplest case (here, what does f [] do ?)
when you have a list in format head::tail, and you can already use f on the tail, what should you do to head and tail to obtain (f (head::tail)) ?
With this information, you should be able to write a recursive function that does what you want using pattern matching
here the simplest case is
| [] -> [e]
(you just add e at the end)
and the general case is
| h::t -> (premier_de_triplet h)::(f t)

sum of each element in two lists by ocaml (beginner)

I want to make a list of summation of two lists by recursively.
let rec listadd a b
match a with
| [] -> b
| hd::tl ->
( match b with
| hd2::tl2 -> [hd + hd2]#(list_add tl tl2)
| [] -> [hd + hd2]#(list_add tl tl2)
)
However, it causes an error.
File "test.ml", line 56, characters 17-20:
Error: Unbound value hd2
Did you mean hd?
What is the problem?
The problem is that hd2 is undefined in the case [] -> [hd + hd2]#(list_add tl tl2). I guess you are trying to write something like
let rec listadd a b =
match a with
| [] -> b
| hd :: tl ->
(match b with
| hd2 :: tl2 -> [hd + hd2]#(listadd tl tl2)
| [] -> a
)
I would also recommend not to use list concatenation, instead appending an element to the head of a list directly:
let rec listadd a b =
match a with
| [] -> b
| hd :: tl ->
(match b with
| hd2 :: tl2 -> (hd + hd2) :: (listadd tl tl2)
| [] -> a
)
While that works, the code can be simplified a lot by using one match only:
let rec listadd a b =
match a, b with
| [], _ -> b
| _, [] -> a
| hd :: tl, hd2 :: tl2 -> (hd + hd2) :: (listadd tl tl2)
The name hd2 is defined by the pattern match in the line above. But the name is only defined for that one pattern match and result. So there's no definition for hd2 on the line in error. Since this erroneous line matches an empty list, it's not clear what you were intending the code to do.
As a possible hint, it seems to me that the case where the second list is empty should be handled the same as the case where the first list is empty.
And using the List.map2 function :
let listadd l l' = List.map2(fun x y -> x+y) l l';;

Find unique elements in a list in OCaml

I am working on a project with OCaml and there are some problems regarding to arrays that I am not sure with. I am not allowed to use the List module, so please give me some idea or suggestion with my works.
First, I already implemented a function 'a list -> 'a list called uniq that return a list of the uniq elements in an array, for example uniq [5;6;5;4] => [6;5;4]
Here is my implementation:
let rec uniq x =
let rec uniq_help l n =
match l with
[] -> []
| h :: t -> uniq_help t, n if (n = h) else (h :: (uniq_help(t, n)))
match x with
[] -> []
| h::t -> uniq_help t, h
;;
I mot sure this is a correct implementation, can someone give me some suggestion or correctness?
You functions are syntactically incorrect for various reasons:
uniq_help takes two elements so you have to invoke it using uniq_help t n, not uniq_help(t, n) and the like.
an if/else expression should have the form of if cond then expr1 else expr2.
to use uniq_help locally in uniq, you need an in keyword.
After fixing syntax errors, your function looks like:
let rec uniq x =
let rec uniq_help l n =
match l with
| [] -> []
| h :: t -> if n = h then uniq_help t n else h::(uniq_help t n) in
match x with
| [] -> []
| h::t -> uniq_help t h
However, to be sure that each element is unique in the list, you have to check uniqueness for all of its elements. One quick fix could be:
let rec uniq x =
(* uniq_help is the same as above *)
match x with
| [] -> []
| h::t -> h::(uniq_help (uniq t) h)

how to make these simple functions tail recursive in f#

I have these these two functions
//Remove all even indexed elements from a list and return the rest
let rec removeEven l =
match l with
| x0::x1::xs -> x1::removeEven (xs)
| [] -> []
| [_] -> []
//combine list members into pairs
let rec combinePair l =
match l with
| x0::x1::xs -> (x0,x1) :: combinePair(xs)
| [] -> []
| [_] -> []
That work.
But I thought now that I was at it that I might as well learn a bit about tail recursion which I'm having a hard time getting the grasp of.
That's why I thought that if I could get some help making functions I had made myself tail-recursive perhaps it would become more clear how it works, instead of reading an example somewhere which I might not understand as well as my own code (remember, I'm a complete f# newbie :))
Any other constructive comments about my code are of course most welcome!
A typical way of making functions tail-recursive in F# is using a list (acc in this case) to accumulate results and reversing it to get the correct order:
let removeEven l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| _::x1::xs' -> loop xs' (x1::acc)
loop l [] |> List.rev
let combinePair l =
let rec loop xs acc =
match xs with
| [] | [_] -> acc
| x0::x1::xs' -> loop xs' ((x0, x1)::acc)
loop l [] |> List.rev
Since we simply return results after each recursive call of loop, these functions are tail-recursive.
Your functions look quite nice, but I still have several comments:
Indentation is important in F#. I would prefer match... with is a few spaces behind lec rec declaration.
Patter matching cases should follow a consistent order. It's a good idea to start with base cases first.
The function keyword is natural to use for shortening functions whenever you have a pattern of fun t -> match t with.
It's better to get rid of unnecessary parentheses, especially in functions with one argument.
Applying above comments, your functions become as follows:
// Remove all even indexed elements from a list and return the rest
let rec removeEven = function
| [] | [_] -> []
| _::x1::xs -> x1::removeEven xs
// Combine list members into pairs
let rec combinePair = function
| [] | [_] -> []
| x0::x1::xs -> (x0, x1)::combinePair xs
If you need a slower, less maintainable way to do it that uses more memory, you can use a continuation.
let removeEven items =
let rec loop f = function
| _::h::t -> loop (fun acc -> f (h::acc)) t
| [] | [_] -> f []
loop id items
But hey, it's tail-recursive.