Find sublists that fulfill a given property in Ocaml - list

I have a function that returns every "sublists" from a given list:
let rec sublists = function
[] -> [[]]
| h::t -> let st = sublists t in
List.map (function l -> h::l) st # st;;
For example, if you try
sublists [1;4;9;12]
it will return:
[[1; 4; 9; 12]; [1; 4; 9]; [1; 4; 12]; [1; 4]; [1; 9; 12]; [1; 9]; [1; 12];
[1]; [4; 9; 12]; [4; 9]; [4; 12]; [4]; [9; 12]; [9]; [12]; []]
That are every possible combinations of elements in the list (order doesn't matter)
I have to do a function that returns a different sublists pair that fulfill a given property.
Function must have this type: ('a list -> 'a list -> bool) -> 'a list -> 'a list * 'a list
For example, if we have the previous list and we try
search (<4) [1;4;9;12]
It will return:
([9;12], [9]) because these lists satisfaces the given condition (<4). Order does not matter, it could return ([9], [12]) instead, or another possible combination.
I'm stucked at this, I have done a function that check if a given list is a sublist of another list:
let is_sublist_of l1 l2 =
let sub = sublists l1 in
List.mem l2 sub;;
But I think that is useless here. Coul anyone help me?

Can't you just filter the list first and then apply the two first runs of sublist to it ?
let filter_sublist f l =
let l = List.filter f l in
let rec sublists = function
| [] -> [], []
| h :: t ->
let st1, st2 = sublists t in
h :: st1, st2
in sublists l
The problem here is that f is of type 'a -> bool because I don't understand your type ('a list -> 'a list -> bool). What is it supposed to represent ?

Related

deleting duplicates tail recursively in OCaml

I tried to write my own solution for this exercise by iterating through a list with a empty complst list where all non duplicates are inserted into and then get returned.
I know it is a over complicated approach after looking up the solution but would still like to understand why the pattern matching does not work as intended:
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c) -> if a = b then aux complst (b::c) else aux (a::complst) (b::c)
| x -> x
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Regardless of the input, the output is always a list with only the last element:
compress [1;1;2;2;3];;
- : int list = [3]
compress [1;2;3];;
- : int list = [3]
Pattern matching
Your pattern-matching matches against three patterns:
The empty list: []
The list with at least two elements: a :: (b :: c)
A catch-all, which must by process of elimination be a list with a single element.
Consider what happens when we evaluate your example:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
[3]
Oops, as soon as it hit lst being [3] it just returned it.
Let's rewrite your function to handle that single element list by adding to complst.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> complst
| [x] -> aux (x::complst) []
| a :: (b :: c) ->
if a = b then aux complst (b::c)
else aux (a::complst) (b::c)
in
aux [] list
Now:
compress [1; 1; 2; 2; 3]
aux [] [1; 1; 2; 2; 3]
aux [] [1; 2; 2; 3]
aux [1] [2; 2; 3]
aux [1] [2; 3]
aux [2; 1] [3]
aux [3; 2; 1] []
[3; 2; 1]
Clean up and reversing the resulting list
Of course, there are also ways to clean up your code a bit using a conditional guard and _ for values you don't need to bind names to. You probably also want to reverse your accumulator.
let compress lst =
let rec aux complst lst =
match lst with
| [] -> List.rev complst
| [x] -> aux (x::complst) []
| a :: (b :: _ as tl) when a = b -> aux complst tl
| a :: (_ :: _ as tl) -> aux (a::complst) tl
in
aux [] lst
Fold
When you see this pattern of iterating over a list one element at a time and accumulating a new value, you can usually map that pretty well to List.fold_left.
let compress lst =
List.(
fold_left
(fun i x ->
match i with
| (x'::_) when x = x' -> i
| _ -> x::i)
[] lst
|> rev
)
Because List.fold_left can only be aware of one element at a time on the list, the function we pass as its first argument can't be aware of the next element in the list. But it is aware of the accumulator or "init" value. In this case that's another list, and we can pattern match out that list.
If it's not empty and the first element is equal to the current element we're looking at, don't add it to the result list. Otherwise, do add it. This also handles the first element case where the accumulator is empty.
Kudos on creating a tail-recursive solution to this problem!
The problem with your code here is mainly the last part, which corresponds to when you have the last element in your list so here [3], and you return that list with this single element.
What you need to do instead is append it to complst like this :
let compress list =
let rec aux complst lst =
match lst with
| [] -> complst
| a :: (b :: c ) -> if a=b then aux complst (b::c) else aux (a::complst) (b::c)
| x::e -> x::complst
in aux [] list;;
val comp : 'a list -> 'a list = <fun>
Now you can check with the given example :
compress [1;1;2;2;3];;
- : int list = [3; 2; 1]
Hope it helps you understand your mistake better.
Note regarding comments:
you should keep the [] case, because although it can only happen in one scenario, it is still a valid input meaning it must be kept!.

How to generate all possible splitting of a list?

Given a list: [1; 2; 3], how can I generate all possible splits:
[
[ [1; 2; 3] ];
[ [1]; [2; 3] ];
[ [1]; [2]; [3] ];
[ [1; 2]; [3] ]
]
I have no real attempt yet, I don't know how to start
EDIT : attempt
I tried to do it step by step but it's kinda messy
and I couldn't do mergeFirst, without mergeFirst it gives : [[[1]; [2; 3]]; [[1]; [2]; [3]]]
Am I on the right path ? I don't think my code will work if the list contains more than 3 elements too ...
let split = function
| [] -> []
| x::y -> [[x::y]] # [[[x]] # [[List.hd y]]]
(* let mergeFirst a = function
... *)
let addtoseperatelist a list =
List.map (fun t -> [[a]] # t) (list)
let rec generateAllSplit = function
| [] -> []
| [x;y] -> split (x::y::[])
| x::y -> addtoseperatelist x (generateAllSplit y) # (mergeFirst x (generateAllSplit y))
let myList = [[1;2;3]]
let _ = generateAllSplit myList
Until you get farther with your analysis, this isn't actually an OCaml question. It's more a question about breaking down a problem recursively.
One good way to solve problems that feel recursive is to imagine that you already had the solution. If you had your split function already, it would return the following for the tail of your list ([2; 3]):
[ [[2; 3]]; [[2]; [3]] ]
Is there a way to process this smaller result into your desired final result? Yes. There are two things you can do with [1]: you can merge it with the first element of the returned lists, or you can add it as a separate list. That gives you the four values of the desired result. You should be able to prove to yourself that his always gives the right answer. (Or maybe it doesn't, you'll have to check.)
If your given list has fewer than 2 elements, the result is obvious. You can probably combine this with the above recursive processing to get the answer.
You are on the right track. The merge first is still missing, which you have to do with pattern matching because the empty list is a special case. In my code that is (function [] -> [[x]] | z::zs -> (x::z)::zs) ys
The one element list is also a special case for split because it only has one result. If you would solve that recursively you would get [[x]; []] and [[x] # []] == [[x]].
Instead of adding to the recursive results and merging to the recursive results and then appending the two resulting lists I decided to use a fold_left and construct the adding and merging of each sub list in parallel. Then you can :: the results instead of append:
let myList = [1;2;3]
let rec split = function
| [] -> [[[]]]
| [x] -> [[[x]]]
| (x : int)::xs ->
List.fold_left
(fun (acc : int list list list) (ys : int list list) ->
([x] :: ys) (* add to separate list *)
:: (function [] -> [[x]] | z::zs -> (x::z)::zs) ys (* merge first *)
:: acc
)
[]
(split xs)
let res = split myList;;
val myList : int list = [1; 2; 3]
val split : int list -> int list list list = <fun>
val res : int list list list =
[[[1]; [2; 3]]; [[1; 2; 3]]; [[1]; [2]; [3]]; [[1; 2]; [3]]]

insert element in all positions of a list in OCaml

Trying to insert a number in all positions of the list, result being a list of lists.
something like:
insert 4 [1; 2; 3] = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]; [1; 2; 3; 4]]
My idea is to apply Map on the list with a function that returns a list.
resulting in list of lists. like [f 1; f 2 ; f3] (I know will only have 3 lists, but just want to get this working first)
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Hope is, function aux will return a list with x inserted in the right place.
The problem is, List.map f1 ls line is assuming ls is 'a list list even though it is defined as 'a list
Any ideas please?
To actually answer your question, instead of providing you with different methods to reach your goal (you wanted to know what is actually wrong with your code, not how one could solve the problem.):
signature of fold_left is ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>. Instead of ('a -> 'b -> 'a) your provide it with fun f2 acc q -> ... = ('a -> 'b -> 'c -> 'a). Just remove the f2 and you're fine.
put brackets around stuff like x::[q], or use ##.
Your code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun f2 acc q ->
if p = q then List.append acc x::[q]
else List.append acc q::[])
[] ls
in
List.map aux ls
Working code:
let insert (x : 'a) (ls : 'a list): 'a list list =
let aux p =
List.fold_left
(fun acc q ->
if p = q then List.append acc (x::[q])
else List.append acc (q::[]))
[] ls
in
List.map aux ls
For input insert 4 [1;2;3]this returns int list list = [[4; 1; 2; 3]; [1; 4; 2; 3]; [1; 2; 4; 3]]. This is almost what you wanted. The rest can be fixed by you :).
Note:
The Error that the Compiler throws is: Error: This expression has type 'a list but an expression was expected of type 'b list -> 'b list list. For the next time, just think about what happened. You provide fold_left with ('a -> 'b -> 'c -> 'a); which is not "wrong", but not what you want. You could write it as ('a -> ('b -> 'c) -> 'a). This means the acc-value is some 'a and the value of the fold is a function 'b -> 'c. This explains the error-message :).
Try breaking this problem down.
First hurdle: can you insert an element at a given index in a list? The start might look like:
let rec insert lst pos v =
(* ... *)
Well, we know if the position is 0, it should go at the front.
let rec insert lst pos v =
match pos with
| 0 -> v :: lst
| _ -> (* ... *)
If it's not 0 then you'd need to append the first element in lst to the result of inserting into the tail of the list at pos - 1.
Of course, the devil is in the details. What happens if you try insert [1; 2; 3; 4] 7 5? You need to find a way to check for situations like this.
If you can get this function to work, you then just need to iterate from 0 to the length of the list, inserting the new value into the list.
List.init would work nicely.
List.(
let lst = [1; 2; 3; 4] in
let len = length lst + 1 in
init len (fun i -> insert lst i 5)
)
And as a result, if you wrote insert correctly, you should get:
[[5; 1; 2; 3; 4]; [1; 5; 2; 3; 4]; [1; 2; 5; 3; 4];
[1; 2; 3; 5; 4]; [1; 2; 3; 4; 5]]
This should do the trick:
let rec insert v l =
match l with
| [] -> [[v]]
| x::xs -> (v::l) :: (List.map (List.cons x) (insert v xs))
Adding an explanation, had to think about this a while too:
For an empty list there is only one way to insert v and [[v]] is the result.
For a list x::xs first insert v at all positions in xs: insert v xs, which gives a list of lists. Then for each list add x back to the front: List.map (List.cons x) .... This gives all the results where v is inserted after x. So last construct the list where v is added before x: v::l. Adding that to the front of the list of lists gives the final result.

Set a key value to the closest node element given two lists

Say I have a list of keys, k = [2,3,7,15,18,23] ; and a list of nodes, n = [1,5,10,15,20] . Both lists are sorted lists.
Then the "closest next node", or the successor node for key k = 2 is n = 5 ; for k = 3 is n = 5; for k = 7 is n = 10 , and so on. If the key value is greater than the last node value, then its successor node is the first node element, so k = 23 is n = 1. I want to output a list array that maps each successor nodes with their keys in format [[successor_node1, key, key],[successor_node2, key, key],...]. So the results for example is output_array = [[5,2,3],[10,7,],[15,15],[20,18],[1,23]]
how can I achieve these with F# in just ONE function?
You can do this by writing a recursive function that iterates over the two lists and pattern matches on the first elements. To keep the result, the best option is probably to use an immutable map - as you go, you can add the values for the individual keys associated with individual successor nodes:
let k = [2;3;7;15;18;23]
let n = [1;5;10;15;20]
let rec findSuccessors first res k n =
// Add a key 'k' associated with a successor node 'n' to the list
let add k n =
match Map.tryFind n res with
| None -> Map.add n [n; k] res
| Some l -> Map.add n (l # [k]) res
match k, n with
| [], _ ->
// If there are no more keys, we return the results
res |> Map.toList |> List.map snd
| k::ks, [] ->
// If there are no more successors, use the special 'first'
findSuccessors first (add k first) ks []
| k::ks, n::ns when n < k ->
// If we have a key 'k', but the next node is smaller, skip it
findSuccessors first res (k::ks) ns
| k::ks, n::ns ->
// Found a key 'k' with a successor 'n' - add it to the list
findSuccessors first (add k n) ks (n::ns)
findSuccessors (List.head n) Map.empty k n
I came up with a new solution to your description of the problem, rather than trying to modify your code. I'm using quite a different approach: no mutable variables or data structures, just pure functional code with one recursive function. I did this because it was easier for me, not because pure code is always better.
let mapNodes startingNodes startingKeys =
let rec loop remainingNodes remainingKeys acc =
match remainingNodes, remainingKeys with
| _, [] ->
acc
| [], keys ->
let next = startingNodes |> List.tryHead |> Option.map (fun firstNode -> firstNode :: keys)
match next with
| Some next -> next :: acc
| None -> acc // this shouldn't happen if there is at least one starting node
| nextNode :: restNodes, keys ->
let keysForNode = keys |> List.takeWhile (fun key -> key <= nextNode)
match keysForNode with
| [] ->
loop restNodes keys acc
| keysForNode ->
let next = nextNode :: keysForNode
let restKeys = keys |> List.skip keysForNode.Length
loop restNodes restKeys (next :: acc)
loop (startingNodes |> List.tail) startingKeys [] |> List.rev
let nodes = [ 1; 5; 10; 15; 20 ]
let keys = [ 2; 3; 7; 15; 18; 23 ]
let expected = [ [ 5; 2; 3 ]; [ 10; 7 ]; [ 15; 15 ]; [ 20; 18 ]; [ 1; 23 ] ]
let result = mapNodes nodes keys // [[5; 2; 3]; [10; 7]; [15; 15]; [20; 18]; [1; 23]]
result = expected // true
The general approach is to use a recursive loop that explicitly passes through all of the input state required, rather than using mutable variables. An accumulator acc is also passed through to gather the output.
This code uses a List.takeWhile, followed by a List.skip on the same list. This is slightly inefficient. It could be improved if there was a List.splitWhen function in the F# library, or if you were to write one yourself.
One more attempt in addition to what was proposed earlier :) I'm not well familiar with F# standard library and idioms, so it might be not idiomatic/suboptimal/both, but I tried to solve it in a very straightforward way (as I would explain the solution verbally):
let nearest_keys_per_node keys nodes =
(* Simple helper function that finds the nearest next node for a given key *)
let nearest_next_node nodes k =
match nodes with
| [] -> failwith "Empty nodes list!"
| hd :: tl ->
let rec nearest_node_tr k current_best = function
| [] -> current_best
| hd :: tl when hd < k -> nearest_node_tr k current_best tl
| hd :: tl -> hd
nearest_node_tr k hd tl
List.map (nearest_next_node nodes) keys (* Get the nearest next node for each key *)
|> List.zip keys (* "Glue" them together with the keys - gettin a list of tuples (key, node) *)
|> Seq.groupBy (fun (_, node) -> node) (* Group by nodes*)
|> List.ofSeq
|> List.map (fun (node, seq) -> (* "Cleanup" the structure that we got after the grouping and transform in to your desired output *)
node :: (List.ofSeq(seq) |> List.map fst)
)
;;
> nearest_keys_per_node [2;3;7;15;18;23] [1;5;10;15;20];;
val it : int list list = [[5; 2; 3]; [10; 7]; [15; 15]; [20; 18]; [1; 23]]

How to make a tuple from two indices in a list of lists?

I currently have a list that contains other lists inside. [ [1, 2, 3]; [9, 8, 7];...]
I would like to create a list of tuples from two indices in one of these 3 element lists I have stored inside of the entire list.
I have written something like
let makeTuple list =
let rec tuple list tuplesList =
match list with
| [] -> ()
| h::t -> (tuple t ( (List.item 2 list, List.item 5 list)::tuplesList))
tuple list []
When I run this function, it is giving me an error that there is an out of range index. I've tried other options but I can't seem to make sense of any of them. I'm new to F-sharp :-S. Any tips would be great.
It's not 100% clear what output you are expecting. But this revision at least runs and returns a list of tuples, so maybe it is close to what you want.
let makeTuple list =
let rec tuple list tuplesList =
match list with
| [] -> tuplesList
| h::t -> (tuple t ( (List.item 0 h, List.item 2 h)::tuplesList))
tuple list []
let lst = [ [1; 2; 3]; [9; 8; 7]; [14; 15; 16]]
lst |> makeTuple
Output:
val makeTuple : list:'a list list -> ('a * 'a) list
val lst : int list list = [[1; 2; 3]; [9; 8; 7]; [14; 15; 16]]
val it : (int * int) list = [(14, 16); (9, 7); (1, 3)]