I am working on an OCaml assignment and am a bit stuck. Currently this is what I have:
let rec icent (image) =
match image with
| [] -> 0.0
| imgHead::imgTail -> (centImCol(image, 1)) +. (icent(imgHead))
;;
let rec jcent (image) =
match image with
| [] -> 0.0
| imgHead::imgTail -> (centImRow(imgHead, 1)) +. (jcent(imgTail))
;;
where the centIm* functions are properly defined. The required signature for this is int list list -> float. Currently, I am only achieving error after error and can't quite get a grasp on why. Any help would be appreciated.
let rec centImRow(image, start_j) =
match image with
| imgHead::imgTail -> (sumRowCount(imgHead, start_j)) + (centImRow(imgTail, start_j+1))
| _ -> 0
;;
let rec centImCol(image, start_i) =
match image with
| imgHead::imgTail -> (sumRowCount(imgHead, start_i)) + (centImCol(imgTail, start_i+1))
| _ -> 0
;;
The first problem I see is that your recursive call to icent is applied to the head of the list. But the head of a list is not a list. But icent is supposed to work for lists.
The recursive call of a list handling function is going to be applied to the tail of the list.
I'd also expect some function to be applied to the head of the list. Otherwise nothing is going on other than the recursion itself.
Related
I have a simple function that splits a list at an index:
let rec split_at ls i =
match i with
| 0 -> ([], ls)
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
match split_at t (i - 1) with
| (left, right) -> ((h :: left), right)
Is there a way to get the OCaml compiler to optimize this function to use constant stack space?
I have tried using #tail_mod_cons but it doesn't work. I understand that the call is not really in tail position, but it feels like it should be optimizable.
Firstly, let's clean up your function by pattern matching on a tuple of i and ls and using a local let binding rather than that last match expression.
let rec split_at ls i =
match i, ls with
| 0, _ -> ([], ls)
| _, [] -> raise Not_found
| _, h::t ->
let (left, right) = split_at t (i - 1) in
(h::left, right)
As Jeffrey says, the cons (::) is not in tail call position, so tail_mod_cons does nothing for you. If we try to use it, we'll get a warning to that effect:
Lines 1-7, characters 33-20:
Warning 71 [unused-tmc-attribute]: This function is marked #tail_mod_cons
but is never applied in TMC position.
As also hinted, though, it's trivial to let your brain modify this for tail-recursion using an accumulator.
let split_at lst n =
let rec aux lst n first_part =
match n, lst with
| 0, _ -> (List.rev first_part, lst)
| _, [] -> raise Not_found
| _, h::t -> aux t (n - 1) (h::first_part)
in
aux lst n []
The function split_at can be written in a partial tail_mod_cons way if we split the construction of the new prefix from the part of the function returning the suffix using a reference:
let[#tail_mod_cons] rec split_at r ls i =
match i with
| 0 -> r := ls; []
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
h:: (split_at[#tailcall]) r t (i - 1)
let split_at ls i =
let r = ref [] in
let l = split_at r ls i in
l, !r
The way I understand it, "tail mod cons" works by passing an incomplete constructor into which the called function should place its answer. So to make the optimization work you have to be able to put your problem into a form for which this is a solution.
Maybe it would work if you split the problem into two parts. The first part duplicates the first n elements of the list. The second part returns all but the first n elements of the list.
The second part is trivial to implement tail recursively. And it seems like you should be able to duplicate a list using "tail mod cons".
While learning Ocaml, I saw a code that removing duplicate elements from the list.
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
However, what I found is that this code only removes successive duplicates so if I try some duplicates that takes a place separately such as [6;6;8;9;4;2;5;1;5;2;3], the code deals with 6 which has successive duplicate but not with 2 or 5 which are separated.
How can I completely make the list have only unique elements?
like remove [6;6;8;9;4;2;5;1;5;2;3] -> [6;8;9;4;2;5;1;3].
p.s. I managed to delete duplicate which comes first but cannot have figured out how to delete duplicates that come later.
From your description, you coded the quadratic version of the algorithm.
There is also a O(n log n) version, using a set of already seen values:
let remove_duplicates (type a) (l: a list) =
let module S = Set.Make(struct type t = a let compare = compare end) in
let rec remove acc seen_set = function
| [] -> List.rev acc
| a :: rest when S.mem a seen_set -> remove acc seen_set rest
| a :: rest -> remove (a::acc) (S.add a seen_set) rest in
remove [] S.empty l
(the code above uses the polymorphic compare, you may want to provide a compare function argument in real code)
This question is pretty old but here is a solution that doesn't use sets, in case that's useful :
let rec remove_duplicates l =
let rec contains l n =
match l with
| [] -> false
| h :: t ->
h = n || contains t n
in
match l with
| [] -> []
| h :: t ->
let acc = remove_duplicates t in
if contains acc h then acc else h :: acc
;;
I finally figured out.
Without sorting, I made an element check and element remove functions, so I can check if the tail of the list has a duplicate of head and decide to append head and tail after deleting the duplicates in the tail. Making the main function as recursive it finally removes all duplicates without changing orders(and also preserves the first coming duplicate.)
Thanks you, glennsl.
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)
I'm trying to implement a RLE decoder for a game, and it works, but I'd like to shrink the code a bit, but I can't figure out how to put List.append and the repeat and rleExpand calls on one line
The signature of List.append is List.append : 'T list -> 'T list -> 'T list, so obviously I cannot just do
List.append(repeat(pattern,count), rleExpand(tail,rleTag)) - but would like to know how to do that. I also can use the # operator - maybe that's the most readable one. But how do I use List.append if my lists are created by a function application like in the listing below?
let rec repeat(item,count) =
match count with
| 0 -> []
| n -> item :: repeat(item,n-1)
let rec rleExpand(packed, rleTag: int) =
match packed with
| [] -> []
| tag :: count :: pattern :: tail when tag = rleTag ->
let repeated = repeat(pattern,count)
let rest = rleExpand(tail,rleTag)
List.append repeated rest
| head :: tail -> head :: rleExpand(tail,rleTag)
I would probably write:
repeat(pattern,count) # rleExpand(tail,rleTag)
But you can also write
List.append (repeat(pattern,count)) (rleExpand(tail,rleTag))
You cannot use List.append(repeat(pattern,count), rleExpand(tail,rleTag)) as you originally suggested because List.append takes curried (rather than tupled) arguments.
Does something like this work?
let repeat(item, count) = [for i in 1 .. count -> item]
let rec rleExpand(packed, rleTag: int) =
match packed with
| [] -> []
| tag :: count :: pattern :: tail when tag = rleTag ->
List.collect id [repeat(pattern,count); rleExpand(tail,rleTag)]
| head :: tail -> head :: rleExpand(tail,rleTag)
It's also more commonplace to use make functions curryable by not using tuples as parameters.
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.