Create a function that produces a list of multiples ocaml - 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.

Related

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]

Generate all sublists of a list in OCAML [duplicate]

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.

F# - How to make a copy of elements in a list?

I wish to write something that can make copies of all the elements in a list. So if I wanted 2 of list
[1; 2; 3; 4]
it would become
[1; 1; 2; 2; 3; 3; 4; 4]
So I was planning on writing a function recursively with
let rec dupeElem row count =
match row with
| [] -> []
| hd::tl -> (makeCopy hd count) # dupeElem tl count
where count is the number of copies I want. The function will take each head element in the list and send it to the copy function to make copies to insert back into the list. Then makeCopy would look like:
let makeCopy elem Count =
match Count with
| 0 -> []
| 1 -> elem
| 2 -> elem :: elem
|....
But I get errors for when it returns back to dupeElem. I understand doing hard cases would not be the wisest idea but it was to test whether it can work or not. How would I fix/improve what I have to get it to work?
Just for the sake of non-recursive solutions:
let xs = [1; 2; 3; 4; 5]
xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 1; 2; 2; 2; 3; 3; 3; 4; 4; 4; 5; 5; 5]
makeCopy returns a list for the 0 case, but for the 1 case you are returning a single element. Changing the case for 1 to the following should fix a compile time error:
| 1 -> [elem]
For case 2, your use of :: is invalid because the right hand side is not a list, but it is a single element. Consider replacing it with either of the following:
| 2 -> elem :: [elem]
Or...
| 2 -> [ elem; elem ]
A mutually recursive way:
let rec dupl n = function
| [] -> []
| h::t -> cons h (dupl n t) n
and cons h t = function
| 0 -> t
| n -> cons h (h::t) (n-1)
The answer by s952163 is clean and straightforward. For more generality, if you don't just want to replicate, you could define functions f, g, and h, and do the following:
let xs = [1; 2; 3; 4]
let f = id // No need for type annotation, given the definitions of g and h
let g x = x * x
let h x = x * x * x
(List.zip3 xs xs xs) |> List.map (fun (a, b, c) -> [f a; g b; h c]) |> List.concat
For your specific case in which you just want to replicate you could do
let f = id<int> // The type annotation is necessary
and similarly for g and h or just use f for all three cases. Of course in this case the solution proposed by s952163 is much preferred.

Generate all list of a given length between two values (OCaml or other languages)

I am new to ocaml and trying to write some code to generate all lists of number between two value.
For example, if I call this function generate, I want to obtain something like this :
let generate ~min ~max ~length (* Maybe other arguments *) =
(* The code *)
;;
generate ~min:0 ~max:3 ~length:4;;
Should return
[
[0;0;0];
[1;0;0];
[2;0;0];
[3;0;0];
[0;1;0];
And so on, to
[3;2;3];
[0;3;3];
[1;3;3];
[2;3;3];
[3;3;3];
]
I already tried code like this :
open Core.Std;;
type next_list =
| Complete of int list
| Partial of int list
| Result of (int array) list
;;
let rec next ~r ~min ~max ~l =
let detox = function | Partial a -> a | _ -> assert false in
match l with
| Partial (hd :: tl) when hd <= max -> Partial (hd + 1 :: tl)
| Partial (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Partial (min :: (detox (next ~r ~min ~max ~l:(Partial tl))) ))
| Complete (hd :: tl) when hd <= max -> next ~r:([l] :: r) ~min ~max
~l:(Complete (hd + 1 :: tl))
| Complete (hd :: tl) when hd = max + 1 -> next ~r ~min ~max
~l:(Complete (min :: (detox (next ~r ~min ~max ~l:(Partial tl)))))
(*| Partial [] -> next ~r ~min ~max ~l:(Result r)*)
| Result a -> Result a
It may be spread around several functions if necessary, that is not a problem.
I am also interested by non ocaml code or idea.
Thanks for your help.
This is my first question on Stackoverflow, do not hesitate to say if my question is unclear.
here some solution :
First, let's define that takes 2 lists l1 & l2 as input and that produces a list of list, where each element is l2 augmented by 1 element of l1 :
let enumerate l ll = List.fold ~init:[] ~f:(fun op x -> (x::ll)::op) l;;
enumerate [0;1;2;3] [4;5;6];;
- : int list list = [[3; 4; 5; 6]; [2; 4; 5; 6]; [1; 4; 5; 6]; [0; 4; 5; 6]]
Now generate :
let rec generate length ll =
if length=1 then List.fold ~init:[] ~f:(fun op x -> [x]::op) ll
else
let result = generate (length-1) ll in
List.fold ~init:[] ~f:(fun op x -> (enumerate ll x)#op) result;;
and usage is as follows :
generate 2 [1;2;3];; (* instead of generate ~min:1 ~max:3 ~length:2 *)
Some explanation :
List.fold ~init:[] ~f:(fun op x -> [x]::op) ll
=> this creates the initial list of list (singleton)
And the second : takes each of the list of length -1 and performs the enumeration.
Here's a hint:
let count_prefix low high lists =
???
let generate min max length =
let rec recur low high len =
if len = 0 then []
else count_prefix low high (recur low high (len - 1)) in
recur min max length
count_prefix should return a list that is the elements of lists prefixed with the numbers low to high. If lists is empty, it should return a list of lists containing the numbers low to high. That is:
count_prefix 0 3 [] => [[0]; [1]; [2]]
count_prefix 0 3 [[10];[20]] => [[0; 10]; [0; 20]; [1; 10]; [1; 20]; [2; 10]; [2; 20]]
Fill in the definition of count_prefix.

F# function to find all rotations of a list

I have some F# code here for a recursive function that rotates a list to the left by n places. I am very new to F# and I'm looking for a way to modify this code to output not just one rotation by n positions, but all possible rotations.
For example, say I have the list:
let list1 = [1; 2; 3; 4]
I want to call rotate on this list such that the output is:
[ [1; 2; 3; 4]; [2; 3; 4; 1]; [3; 4; 1; 2]; [4; 1; 2; 3] ]
The code I have that does a left shift by n is:
let rec rotate xs k =
match xs, k with
|[], _ -> []
|xs, 0 -> xs
|x::xs, k when k > 0 -> rotate(xs # [x])(k-1)
|xs, k -> rotate xs (List.length xs + k)
I'm not sure how to edit this to do the steps listed above. Any help or resources would be appreciated. I should add that I really want to function to be recursive. Thanks.
If I understand the question correctly, you can also write the function using the built-in List.permute function:
let rotate xs =
let length = xs |> List.length
let perm n = xs |> List.permute (fun index -> (index + n) % length)
[1 .. length] |> List.rev |> List.map perm
Example output (slightly formatted for improved readability):
> [1 .. 4] |> rotate;;
val it : int list list =
[[1; 2; 3; 4];
[2; 3; 4; 1];
[3; 4; 1; 2];
[4; 1; 2; 3]]
I would start off with making an infinite cyclic sequence off your original list. And then use List.init to get all the rotations.
let rotations list =
let rec cyclic sequence = seq {
yield! sequence
yield! cyclic sequence }
let cyclic = cyclic list
let length = List.length list
List.init length (fun i -> cyclic |> Seq.skip i |> Seq.take length |> List.ofSeq)
the important thing is, that the sequence is lazy and therefore can be infinite.
Using the rotate function you already wrote:
let rotations xs = List.init (List.length xs) (rotate xs)
By the way, you can shorten your rotate function to this:
let rec rotate xs k =
match xs, k with
|[], _ -> []
|xs, 0 -> xs
|x::xs, k -> rotate (xs # [x]) (k-1)
Patterns are matched top-down, so the guard when k > 0 is not necessary. The last line of your original solution would never match, so I removed it.
Since I wanted to do this specific question using recursion and matchings, I managed to figure it out and this is what I came up with:
let rotate xs =
let n = List.length xs
let rec rotation xs n =
match xs, n with
|[], _ -> []
|xs, 0 -> xs
|x::xs, n -> rotation (xs # [x]) (n-1)
let rec rotateList xs n = //we are compiling a list of different rotations
match xs, n with
|xs, 0 -> []
|xs, n -> (rotation xs ((List.length xs)-n))::rotateList xs (n-1)
rotateList xs n
I also specifically wanted only one input parameter, namely the list