Generate all sublists of a list in OCAML [duplicate] - list

This question already has answers here:
Computing a set of all subsets (power set)
(2 answers)
Closed 5 years ago.
What I want to do is generating all sub-lists of a list in OCAML,
for example for
[1; 2; 3]
as a result I want to get this
[[1]; [2]; [3]; [1; 2]; [1; 3]; [2; 3]; [1; 2; 3]]
This is my approach so far:
let sublist l =
let rec aux i j max l2 =
match l with
| [] -> l
| h:t ->
if (i = max && j = max) then l2
else if (j < max ) then aux i j+1 [h]::tl
else aux i+1 i+1 l
in
aux 0 0 (List.length l) []

Use an divide and conquer approach: given a non-empty list, you get a list of all its sublists by removing its first element x and solving the problem for the remaining elements (via a recursion step).
When the recursive call returns, you combine this intermediate result with the element x you previously cut off: you have to return each of the sublist with x added in front of it and unmodified.
let rec sublists = function
| [] -> [[]]
| x::xs -> let ls = sublists xs in
List.map (fun l -> x::l) ls # ls;;
For your example input this computes:
# sublists [1;2;3];;
- : int list list = [[1; 2; 3]; [1; 2]; [1; 3]; [1]; [2; 3]; [2]; [3]; []]
The computed list can be sorted and filtered, depending on whether you want the empty list in the result or not.

Related

Stack overflow during evaluation (looping recursion?)

i'm new to ocaml and i'm trying to create a function that takes an int list and turn it into a list of int list that are have the first element + the second element, followed by the rest of the list, until there is one element left, for example:
[1; 2; 0; 4; 2; 1]
[3; 0; 4; 2; 1]
[3; 4; 2; 1]
[7; 2; 1]
[9; 1]
[10]
And here is my code:
let rec nth l k =
match l with
| [] -> 0
| s::t -> if k = 0 then s else nth t (k - 1);;
let no_first l =
match l with
| [] -> []
| s::t -> t
let rec left_comp_once l =
match l with
| [] -> []
| s::t -> (s + nth t 0) :: no_first t
let rec left_comps l =
match l with
| [] -> []
| s::t -> let x = (s + nth t 0) :: no_first t in
[x] # left_comps x
The left_comp_once function works, however, i get looping recursion error when i try the left_comps function
I cannot figure out where the issue is coming from
Also, i would like to have a return element in this format:
int list -> (int list) list
However, what i wrote gives me:
int list -> int list list
What do these parenthesis imply ?
If you look at this expression:
let x = (s + nth t 0) :: no_first t in
[x] # left_comps x
you can see that x can't possibly be an empty list. It always has at least one element. Therefore left_comps will never terminate when given a non-empty list.
Possibly you want to terminate the recursion when the incoming list has length < 2.
Here's a cleaner way to do it, using pattern matching to get the first two elements of the list in a tail-recursive helper function:
let left_comps l =
let rec helper l acc =
match l with
(* Empty list; return the accumulator *)
| [] -> acc
(* Single element list; cons it to the accumulator *)
| _ :: [] -> l :: acc
(* Two or more elements; add the first two together,
cons the original to the accumulator and repeat with
a new shorter list *)
| a :: b :: t -> helper (a + b :: t) (l :: acc) in
helper l []
With this definition,
left_comps [1; 2; 0; 4; 2; 1]
returns
[[10]; [9; 1]; [7; 2; 1]; [3; 4; 2; 1]; [3; 0; 4; 2; 1]; [1; 2; 0; 4; 2; 1]]
What do these parenthesis imply?
Parenthesis in an ocaml type signature usually indicate a function. For example, (int -> int) means a function that takes an int argument and returns an int. You're just returning a list of lists of integers, hence int list list.

Workaround to append attaching elements in reverse order when sorting

I want to sort so that odd numbers in a list appeart first and evens appear last, but i need evens to be the same position to how they were pre sort, is there a simple workaround to this?
let rec first_odd list = match list with
| [] -> []
| h::t when h mod 2==0 -> first_odd t#[h]
| h::t -> h::first_odd t;;
first_odd[3;1;7;3;4;5;4;3;6;-1;0;3];;
first_odd[1;0;1;5;6;6;1;10;-8;4; -9];;
You can just use List.stable_sort, which implements a merge sort, with a function that compares whether or not each element is odd or even:
let first_odd =
List.stable_sort
(fun a b -> compare (a mod 2 = 0) (b mod 2 = 0))
first_odd[3;1;7;3;4;5;4;3;6;-1;0;3];;
- : int list = [3; 1; 7; 3; 5; 3; -1; 3; 4; 4; 6; 0]
first_odd[1;0;1;5;6;6;1;10;-8;4; -9];;
- : int list = [1; 1; 5; 1; -9; 0; 6; 6; 10; -8; 4]
This looks like a homework assignment, so I'll just make a few comments.
First, the expression list # [elt] has a very bad look to it. If you repeat this for n elements of a list, it has complexity of n^2, because it takes linear time to add to the end of a list. Furthermore, it's necessary to replicate the whole list to add an element to the end. So it's definitely something to avoid.
Second, you can just use List.stable_sort if you write a comparison function that gives the order you desire. This will be a lot faster than your current solution (because it will be n log n rather than n^2).
Third, if you want to work with your current method, I would keep two lists and combine them at the end.
As an academic exercise, it may help to see this implemented in terms of a fold. When using a fold, the initial state is crucial. Let's use two lists in a tuple. One for odds, and one for evens.
Each iteration we consider the initial value and the first element in the list. The function we provide uses that information to provide an updated initial value for the next iteration, which considers the next element in the list.
let list1 = [3; 1; 7; 3; 4; 5; 4; 3; 6; -1; 0; 3]
let list2 = [1; 0; 1; 5; 6; 6; 1; 10; -8; 4; -9]
let sort lst =
List.fold_left (* function *) ([], []) lst
Now, we just need a function that updates the initial value on each iteration. If the value is even, we'll tack it into the front of the evens list. Otherwise, onto the front of the odds list.
let sort lst =
List.fold_left
(fun (odds, evens) x ->
if x mod 2 = 0 then (odds, x :: evens)
else (x :: odds, evens))
([], []) lst
If we test this with list2:
utop # sort list2;;
- : int list * int list = ([-9; 1; 5; 1; 1], [4; -8; 10; 6; 6; 0])
The two lists are backwards. We can fix this with List.rev.
let sort lst =
let odds, evens =
List.fold_left
(fun (odds, evens) x ->
if x mod 2 = 0 then (odds, x :: evens)
else (x :: odds, evens))
([], []) lst
in
(List.rev odds, List.rev evens)
utop # sort list2;;
- : int list * int list = ([1; 1; 5; 1; -9], [0; 6; 6; 10; -8; 4])
Essentially we've now reinvented List.partition.
Now, we just need to concatenate those two lists.
let sort lst =
let odds, evens =
List.fold_left
(fun (odds, evens) x ->
if x mod 2 = 0 then (odds, x :: evens)
else (x :: odds, evens))
([], []) lst
in
List.rev odds # List.rev evens
utop # sort list2;;
- : int list = [1; 1; 5; 1; -9; 0; 6; 6; 10; -8; 4]

Create a function that produces a list of multiples ocaml

I have a function:
let rec multiply x ls =
match ls with
[] -> []
| h::tl -> (x * h) :: multiply x tl
multiply 2 [1;2;3] = [2;4;6]
I would like a function that calls multiply from n to 0. I keep having problems because of the base case:
let rec multiply_all x ls = if x > 0
then (multiply n ls) :: multiply_all (n-1) (ls) else ????
I am not sure what to put after the else. I tried to make it
if x > 1 then (multiply n ls) :: multiply_all (n-1) (ls) else multiply all 1.
but that doesn't work.
Putting 1 there certainly doesn't work since multiply_all must return a list. So you need a list (of lists of int) to put there. But which list should it be?
The short answer is that in such simple cases, the list you need is usually the empty list: [].
As a slightly longer answer, we can consider the case for multiply_all 0 in relation to the intended results of multiply_all 1, multiply_all 2, etc., and try to find a pattern that fits. We want multiply_all to behave like this:
# multiply_all 2 [1;2;3];;
- : int list list = [[2; 4; 6]; [1; 2; 3]]
# multiply_all 1 [1;2;3];;
- : int list list = [[1; 2; 3]]
So calling multiply_all with some number N as first argument should give us a list of length N. In particular, multiply_all with N = 0 should give a list of length 0. The list of length 0 is the empty list.
Here is your completed definition:
let rec multiply_all x ls =
if x > 0 then (multiply x ls) :: multiply_all (x-1) (ls) else []
Just an other solution :
let multiply_all n l =
let multiply n= List.map (( * ) n) in
let rec aux i acc =
if i > n then acc
else aux (i+1) (multiply i l :: acc)
in
aux 1 []
;;
Test :
# multiply_all 5 [1;2;3];;
- : int list list =
[[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]
First of all, your multiply method is pretty inefficient since it isn't tail recursive. Furthermore, the standard library provides you with tools to make that kind of function easier to write:
let multiply n = List.map (( * ) n);;;
val multiply : int -> int list -> int list = <fun>
multiply 5 [1;2;3];;
- : int list = [5; 10; 15]
Note: Also, use partial application when it doesn't obfuscate your code.
As of multiply_all, I'm not sure how to achieve it without JaneStreet's Core (see this question). However, here is a possible implementation using Core:
open Core.Std;; (*Using Core*)
let multiply_all n l =
let multiples = List.init n ~f:(fun x -> n-x) in (*This doesn't exist in Pervasives*)
List.map multiples ~f:(fun m -> multiply l m);;
val multiply_all : int list -> int -> int list list = <fun>
multiply_all 5 [1;2;3];;
- : int list list = [[5; 10; 15]; [4; 8; 12]; [3; 6; 9]; [2; 4; 6]; [1; 2; 3]]
Hope it helps. I'll keep this answer updated with my findings about List.init.

Find sublists that fulfill a given property in Ocaml

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 ?

Sublists of list in F#

How to get sublists
[1]; [1; 2]; [1; 2; 3]; ...; [1; 2; 3; ...; n]
from list
[1; 2; 3; ...; n]
by the most idiomatic way? All that I could is:
List.scan (fun acc elem -> elem::acc) [] [1;2;3;4;5]
> val it : int list list =
[[]; [1]; [2; 1]; [3; 2; 1]; [4; 3; 2; 1]; [5; 4; 3; 2; 1]]
Thanks.
Your implementation is fine. Here is my alternative:
let source = [1..10]
let counts = [0..source.Length] // Or start at 1 if you don't want to start with an empty list
counts |> List.map (fun count -> source |> List.take count)
Throwing mine onto the pile, which is maybe a refinement of Foole's answer:
let inits list =
list |> List.mapi (fun i _ -> List.take (i + 1) list)
mapi is a useful function: You provide it a function which takes the each index and item.
Here's another one:
let f n = List.init n (fun i -> [1..(i + 1)])
List.init exists for the task of initializing a list.