Need help with exercices please

hi everybody

someone could help me with this exercice.
the function listes_paires l : take an argument the list of list l and retourns a copy of l.
and in that list all the list with lengt odd will be doubled.
doubled means : the list will replaced by a@a (concatenate of a by herself).

Exemple

listes_paires [; [1];[1;2];[1;2;3];;[5;4;3;2;1]];;
retourns this
[; [1; 1]; [1; 2]; [1; 2; 3; 1; 2; 3]; ; [5; 4; 3; 2; 1; 5; 4; 3; 2; 1]]*)

Hello. First of all, I suggest that when you post a code question like this, you also post your first attempt, so that we can see where your mistakes are and guide you to the correct answer, without giving you the
full solution to your homework.

I will try to give you some advice, I hope to be clear enough.

  • You need to process a list, so you probably want a function inspecting the list recursively, and applying a specific transformation to each of its elements. I don’t know if you’re that far in your functional programming course, but this is what we call a map operation.

    map : ('a -> 'b) -> 'a list -> 'b list
    

    I suggest you first implement this function.

  • The transformation you want to apply to the elements is the following:

    • Compute the length of the list.
    • If it’s even, don’t change anything.
    • Otherwise, apply the “doubling” operator fun l -> l @ l to the list.

    I suggest you implement this transformation as a second task.

  • Finally you can just declare your final function as a map on the input list.

    let listes_paires l = map my_transform l
    

If you have further questions do not hesitate. Good luck!

2 Likes

i can’t use map function
i can only use the functions function List.hd,List.tletList.length. so the functionsList.nth,List.map,List.rev,List.filteretList.fold_xxx` , are forbiden but i can use them for tests.

is there another manner to do except this one?

let rec listes_paires l =
if l = then
else
let fst = hd l in
let rest = tl l in
if length fst mod 2 = 0 then (fst :: (listes_paires rest))
else ((fst@fst):: (listes_paires rest));;

You can write your own map if you want. Or you can match the list recursively, and do essentially the same thing but manually. But as I can see it is what you did in the message below.

I think the idea is correct, but instead of chaining if then else you can use pattern matching with match. It is a strength of OCaml and lets you reason case by case.

if l = [] then
  (* ... *)
else
  let fst = hd l in
  let rest = tl l in
  (* ... *)

can be replaced with

match l with
| [] -> (* ... *)
| fst :: rest -> (* ... *)

It is more concise, more readable, and safer. :wink:

PS: to post code blocks, you can use triple back quotes

```ocaml
your code
```

2 Likes

do you have another suggestion like that one i suggested before.
i would like to find another one like that but i m not sure there is a second one

i m not sure
what i need put here (?)
match l with
|
| fst :: rest → (* .?.. *)

I’ve never used match with

| fst :: rest ->
  (* your previous code *)
  if length fst mod 2 = 0 then (fst :: (listes_paires rest))
  else ((fst@fst):: (listes_paires rest))

In OCaml, all values of a user-defined type (algebraic data type) are created with a constructor chosen from a finite set. For example, for lists it’s [] or ::.

type t = A of int | B of string | C

Here, any value of type t is either A x with x an integer, B s with s a string, or C. It cannot be obtained in another manner.
As we can enumerate all the possible cases, the match keyword was created for that. It lets you ‘deconstruct’ a value, i.e. check which constructor it was built from, and decide what you want to do according to the constructor.

match t with
| A x -> (* decide what to do when t is an A *)
| B s -> (* decide what to do when t is a B *)
| C   -> (* decide what to do when t is a C *)
1 Like

what means “x” " here"?

The A constructor takes an integer. It means that if your value is an A, it has been built with A applied to an integer. Here x is just a name we give to this integer to manipulate it (we say the integer is bound to the name x).

On the list example, if you match on a list, you can give names to the head and tail to manipulate them as you did manually with your let lines.

match l with
| [] -> (* [] takes no argument *)
| h :: t -> (* :: takes 2 arguments, the head and the tail *)

Here, I called h the head and t the tail, so that in the code following the arrow, I can manipulate these values.

If I don’t care about the tail, I can put a wildcard pattern (an underscore), but then I cannot access it in my function. Here is an implementation of List.hd that uses this feature (because we want the head and don’t care about the tail).

let hd l =
  match l with
  | [] -> failwith "hd called on an empty list"
  | x :: _ -> x
1 Like

i did that and it function
let rec listes_paires l =
match l with
|
| fst :: rest →
if length fst mod 2 = 0 then (fst :: (listes_paires rest))
else ((fst@fst):: (listes_paires rest));;

1 Like

thanks you for you clear explanations.

Good idea! Without it, the empty list, [], looks like a square, , which was driving me nuts!

You can also use `single backticks` for a short piece of code inline with ordinary text:

The empty list `[]` is my favorite list.

Result:

The empty list [] is my favorite list.

like that :slight_smile: ‘’‘let rec listes_paires l =
match l with
|
| fst :: rest →
if length fst mod 2 = 0 then (fst :: (listes_paires rest))
else ((fst@fst):: (listes_paires rest));;’‘’

Not quite. It looks like you are using single quotation mark (apostrophe)s. Try using backwards quotation mark ``` or tilde ~~~. With tilde I think you need to begin the code on a new line.

ok thanks you for all