Getting all indices of a value - list

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.

Related

How does this nested fold_left work? and what is ~f: and ~init:?

I have this code snippet in Ocaml which is taken from here. I know it fills a data structure for a demand (traffic matrix) with a the specified value and when the two hosts are the same it just fill the value with 0. In python or in any imerative language, we would use two for loop one inside another to do the task. I assume this is the reason we have two (fold_left) in this code in which each one is equivilant to a one for loop (I might be mistaken!). My question is how this code works? and what is ~f: and ~init:? are these labels. If they are labels why the compiler complains when I remove them or when I change them? even when I put these arguments in the right order?!
I have finished one book and have watched alot of youtube videos but still find it difficult to understand most of Ocaml code.
let create_3cycle_input () =
let topo = Net.Parse.from_dotfile "./data/topologies/3cycle.dot" in
let hosts = get_hosts topo in
let demands =
List.fold_left
hosts
~init:SrcDstMap.empty
~f:(fun acc u ->
List.fold_left
hosts
~init:acc
~f:(fun acc v ->
let r = if u = v then 0.0 else 53. in
SrcDstMap.set acc ~key:(u,v) ~data:r)) in
(hosts,topo,demands);;
Please, read my another SO answer that explains how fold_left works. Once you understand how a single fold works, we can move forward to the nested case (as well as to the labels).
When you have a collection of collections, i.e., when an element of a collection is another collection by itself, and you want to iterate over each element of those inner collections than you need to nest your folds. A good example, are matrices which could be seen as collections of vectors, where vectors are by themselves are also collections.
The iteration algorithm is simple,
state := init
for each inner-collection in outer-collection do
for each element in inner-collection do
state := user-function(state, element)
done
done
Or, the same in OCaml (using the Core version of the fold)
let fold_list_of_lists outer ~init ~f =
List.fold outer ~init ~f:(fun state inner ->
List.fold inner ~init:state ~f:(fun state elt ->
f state elt)
This function will have type 'a list list -> init:'b -> f:('b -> 'a -> 'b) -> 'b
and will be applicable to any list of lists.
Concerning the labels and their removal. The labels are keyworded arguments and enable passing arguments to a function in an arbitrary manner, which is very useful when you have so many arguments. Removing labels is sometimes possible, but could be disabled using a compiler option. And the Core library (which is used by the project that you have referenced) is disabling removing the labels, probably for the good sake.
In general, labels could be omitted if the application is total, i.e., when the returned value is not a function by itself. Since fold_left returns a type variable, it could always be a function, therefore we always need to use labels with the Core's List.fold (and List.fold_left) function.

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.

ocaml sum of two lists with different length

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.

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.