# OCaml recursive function that repeats the values of an array

I have to solve this exercise in OCaml : Write a recursive function that repeats the values of a list, for exemple repeat [3;2;4;5] should give [3;2;2;4;4;4;5;5;5;5]

I think that I should use match with and concatenate but I really have no idea how to start this exercise…

I would be very grateful for your help !

Is it “repeat n times list member number n-1” for all list members?

Repeat 1 time member number 0 which is 3
etc.

It seems like you want to repeat the nth element (n+1) times (remember indexes start at 0).

I think that I should use match with and concatenate

Not bad intution, if you were to use an imperative approach that could work.

I got it to work like this:

``````utop # let repeat ls =
(* `helper` will just repeat `l` n times *)
let rec helper acc n l =
if n = 0
then acc
else helper (l @ acc) (n-1) l in
(* `mapi` to know the position of the element, `flatten`
build a single list out of many *)
List.flatten @@ List.mapi (fun i x -> helper [] (i+1) [x]) ls ;;
val repeat : 'a list -> 'a list = <fun>

utop # repeat [3;2;4;5] ;;
- : int list = [3; 2; 2; 4; 4; 4; 5; 5; 5; 5]
``````

This builds a list of lists and then flattens it. Not the best code but seems to work like you want it to

Have fun with OCaml!

2 Likes

Besides the recursive approach, there’s also a really fun way to do it with some standard library list functions ( https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html ) and the following technique:

• For a given list, map each element to a list of n + 1 elements, where n is the zero-based index of the element
• Flatten the resulting list of lists of ints, into a list of ints.

I actually could have sworn there was a `List.flat_map`, which allowed doing this in an even more succinct way, but it looks like it’s not in the published library yet.

2 Likes
``````let repeat_values l =
List.mapi (fun i v -> List.init (i + 1) (fun _ -> v)) l
|> List.concat
``````

for a standard library quick solution. If you want a more efficient solution, you should probably write your own recursive function, a kind of custom `List.fold_left`.

1 Like

I found a solution !
`let rec inter l = match l with |[]->[] |p::q->p::q@(inter q) ;; (* # inter [1;2;3;4];; - : int list = [1; 2; 3; 4; 2; 3; 4; 3; 4; 4] *)`
Then I just sorted this list and It works

What about using Preformatted text (</> or Crt+Shift+c) to improve code readability?
Example:

``````let rec inter l =
match l with
| []->[]
| p :: q -> p :: q @ ( inter q )
``````

What if the elements can’t be sorted after application of the function `inter` because they are not sorted in the input value?
Example:

``````List.sort compare (inter [3;2;4;5])
- : int list = [2; 2; 3; 4; 4; 4; 5; 5; 5; 5]
``````
1 Like

If you use Base, there’s `List.concat_mapi`:

``````let repeat l =
List.concat_mapi l ~f:(fun i ele ->
List.init (i + 1) ~f:(fun _ -> ele))``````
1 Like