ocaml sum of two lists with different length - ocaml

I tried to add two lists with different lengths using this:
let sumList(a,b) = match a,b with
|[],_ -> []
|(x::xs,y::ys)-> (x + y)::diffList(xs,ys)
It returns Unbound value sumList. Is it possible to do this as in Haskell: zipWith(+) a b.

Possibly the actual error is "Unbound value diffList", since you don't define diffList in your code.
If this is a transcription error, then the next problem is that you need to declare sumList as a recursive function: let rec sumList (a, b) = ....
Your pattern match is not exhaustive. It fails if the first list is longer.
The Haskell zipWith is friendlier than the OCaml List.map2, which requires the lists to be the same length. I don't think there's anything so friendly in the OCaml standard library.

Related

Ocaml function parsing list of lists

I am trying to build a function in Ocaml which parses a list of lists, eg from [[0;1];[3;4;8]] to [0;1;3;4;8]. I tried to do something like:
#let rec parse listoflists=
match listoflists with
[[]]->[]
|[h::t]->h::parse [t];;
but it doesn't work... I also need an explanation, because I don't understand how the lists of lists actually work...
I don't have to use the Ocaml library functions.
If you can understand a list, then I claim you already know about lists of lists. This is the beauty of recursion.
The only real difficulty (as I see it) is keeping track of which list you're talking about. Your code needs to work with the list of lists itself, which consists of one list (call it h) followed by some other lists. It also needs to work with the list h, which consists of some element (call it hh) followed by some other elements.
It seems to me there are three interesting cases: (a) the list of lists is empty; (b) the first element of the list of lists h is empty (c) neither the list of lists nor h is empty.
You are not handling all three of these cases. That's one way to see that your code probably wouldn't work.
Here is a match that matches the three cases, which might help a little:
match listoflists with
| [] -> ... (* List of lists is empty *)
| [] :: t -> ... (* First list h is empty *)
| (hh :: ht) :: t -> ... (* Neither is empty *)

Pack consecutive duplicates of list elements into sublists in Ocaml

I found this problem in the website 99 problems in ocaml. After some thinking I solved it by breaking the problem into a few smaller subproblems. Here is my code:
let rec frequency x l=
match l with
|[]-> 0
|h::t-> if x=[h] then 1+(frequency x t)
else frequency x t
;;
let rec expand x n=
match n with
|0->[]
|1-> x
|_-> (expand x (n-1)) # x
;;
let rec deduct a b=
match b with
|[]-> []
|h::t -> if a=[h] then (deduct a t)
else [h]# (deduct a t)
;;
let rec pack l=
match l with
|[]-> []
|h::t -> [(expand [h] (frequency [h] l))]# (pack (deduct [h] t))
;;
It is rather clear that this implementation is overkill, as I have to count the frequency of every element in the list, expand this and remove the identical elements from the list, then repeat the procedure. The algorithm complexity is about O(N*(N+N+N))=O(N^2) and would not work with large lists, even though it achieved the required purpose. I tried to read the official solution on the website, which says:
# let pack list =
let rec aux current acc = function
| [] -> [] (* Can only be reached if original list is empty *)
| [x] -> (x :: current) :: acc
| a :: (b :: _ as t) ->
if a = b then aux (a :: current) acc t
else aux [] ((a :: current) :: acc) t in
List.rev (aux [] [] list);;
val pack : 'a list -> 'a list list = <fun>
the code should be better as it is more concise and does the same thing. But I am confused with the use of "aux current acc" in the inside. It seems to me that the author has created a new function inside of the "pack" function and after some elaborate procedure was able to get the desired result using List.rev which reverses the list. What I do not understand is:
1) What is the point of using this, which makes the code very hard to read on first sight?
2) What is the benefit of using an accumulator and an auxiliary function inside of another function which takes 3 inputs? Did the author implicitly used tail recursion or something?
3) Is there anyway to modify the program so that it can pack all duplicates like my program?
These are questions mostly of opinion rather than fact.
1) Your code is far harder to understand, in my opinion.
2a) It's very common to use auxiliary functions in OCaml and other functional languages. You should think of it more like nested curly braces in a C-like language rather than as something strange.
2b) Yes, the code is using tail recursion, which yours doesn't. You might try giving your code a list of (say) 200,000 distinct elements. Then try the same with the official solution. You might try determining the longest list of distinct values your code can handle, then try timing the two different implementations for that length.
2c) In order to write a tail-recursive function, it's sometimes necessary to reverse the result at the end. This just adds a linear cost, which is often not enough to notice.
3) I suspect your code doesn't solve the problem as given. If you're only supposed to compress adjacent elements, your code doesn't do this. If you wanted to do what your code does with the official solution you could sort the list beforehand. Or you could use a map or hashtable to keep counts.
Generally speaking, the official solution is far better than yours in many ways. Again, you're asking for an opinion and this is mine.
Update
The official solution uses an auxiliary function named aux that takes three parameters: the currently accumulated sublist (some number of repetitions of the same value), the currently accumulated result (in reverse order), and the remaining input to be processed.
The invariant is that all the values in the first parameter (named current) are the same as the head value of the unprocessed list. Initially this is true because current is empty.
The function looks at the first two elements of the unprocessed list. If they're the same, it adds the first of them to the beginning of current and continues with the tail of the list (all but the first). If they're different, it wants to start accumulating a different value in current. It does this by adding current (with the one extra value added to the front) to the accumulated result, then continuing to process the tail with an empty value for current. Note that both of these maintain the invariant.

Getting all indices of a value

Im trying to create a haskell function where all the indices of an occurence of a value in a list are returned as a list, so like
indices 3 [1,2,3,3,7]
gives [2, 3] as output. I am very new to Haskell and couldnt find something useful. I tried using filter, but all i got working is getting a list of [3, 3] but not the actual indices. It would be cool if you could give me a little hint.
This is a pretty common pattern in functional programming, sometimes called decorate-process-undecorate. The idea is that you want to attach some extra information to each of the elements in your list, filter using a slightly altered version of the filter you would have done normally, then strip that extra information away.
indicies n = undecorate . filter predicate . decorate where
decorate = ...
predicate = ...
undecodate = ...
When trying to code decorate I suggest taking a look at the function zip:
zip :: [a] -> [b] -> [(a, b)]
Consider its effect on infinite lists, too, such as repeat 1 or [1,3,...]. When trying to code undecorate you'll likely want to map:
map :: (a -> b) -> [a] -> [b]
Finally, don't worry about the efficiency of this process. In a strict language, decorate-filter-undecorate might require 3 traversals of the list. In a non-strict language like Haskell the compiler will automatically merge the 3 inner loops into a single one.

takeWhile, lambdas, and pattern matching

I'm pretty new to Haskell and still trying to learn the ropes. My problem is this:
I am trying to take all of the numbers which when added to the number after it in a list is less than a certain number. In a more formal sense, how can I use sublists of my list as arguments for my filtering boolean function?
For example: we have the list [a0,a1,a2,...], how can I take from the list while a_n + a_(n+1) < c (where c is just some number)?
Ultimately I am going to be using this to create a sequence of root approximations of a function. Currently I have an infinite list of approximations (since I don't know where to stop yet) and I would like to take all of the approximations up until an approximation that has some tolerable error. The error of the approximation p_n is given as a function of p_n, p_(n-1), p_(n-2). Lets call this function f. So ideally I would like to keep taking elements from the list while
f(p_(n),p_(n-1),p_(n-2)) > error.
The signature of the function you want to write looks like this
takeLessThan :: (Num a, Ord a) => a -> [a] -> [a]
takeLessThan bound xs = ...
You can extract each pair of the list by zipping the list with the tail of itself.
pairs :: [b] -> [(b, b)]
pairs xs = zip xs (tail xs)
So the pairs of the list [1,2,3,4,5] will give you a tuple of (an, an+1).
[(1,2),(2,3),(3,4),(4,5)]
From there you can use the filter function from the Prelude to select the elements you want based on the function (a -> Bool).
filter :: (a -> Bool) -> [a] -> [a]
I think its easier to break down your problem into multiple steps intead of trying to solve it all at once with a super smart filtering function.
Start with a list [a0 ... an]
Turn it into a list of pairs [ (a0, a1) ... (a_n-1, an) ] with zip
Filter the interesting pairs with takeWhile (or filter, depending on what you want to do).
Turn the list of good pairs back into a list with just the first numbers using map
Don't worry about performance or about generating wasteful intermediate lists. Everything should be efficiently created on demand due to the lazy evaluation.

Flattening a list of lists in OCaml

I am implementing this hoemwork functionality using Ocaml:
Not allowed to use List module
the function has type 'a list list -> 'a list
the function return a list consisting of the lists in x concatenated together (just top level of lists is concatenated, unlike List.flatten)
For example : [[1,2,3],[45]] => [1,2,3,4,5] and [[[1,2,3],[4,5]],[[6,7]]] => [[1,2,3],[4,5],[6,7]]
I am not sure where to start, can anyone give me some suggestion? Thank you
I don't see the difference between List.flatten and your function.
To answer to your question: as usual with lists, try to think about the base cases:
what do you do when you concatenate an empty list with something ?
what do you do when you concatenate a non-empty list (with a head and a tail) with something ?
Wrap everything into a pattern match, cook it for few hours, and that's done :-)
Thomas has given excellent advice. Your basic operation is going to be to append one list to another. It might help to write this function as a separate function first. It will look something like this:
let rec myappend a b =
match a with
| [] -> (* Empty list prefixed to b (easy case) *)
| ahead :: atail -> (* Recursive case *)
Armed with your own append function, you can carry out another level of recursion
to append all the top-level lists as Thomas suggests.