## 1.1 - Product

```Ocaml
# let rec product = function
	| [] -> 0
	| x::t -> x * product t;;
```
## 1.2 - Count
```Ocaml
# let rec count x n =
	if x = [] then
		0
	else
		let e::t = x in
		if e = x then
			1 + count t n
		else
			count t n;;
(* Correction *)
# let rec count x = function
	| [] -> 0
	| e::t -> (if x = e then 1 else 0) + count x t;;
val count = 'a -> 'a list -> int = <fun>
```

## 1.3 - Search
```Ocaml
# let rec search x n =
	if x = [] then
		false
	else
		let e::t = x in
		if e = x then
			true
		else
			search t n;;
(* Correction *)
# let search x = function
	| [] -> false
	| e::t -> x = e || search x t
	| _::t -> search x t ;;
val search 'a -> 'a list -> bool = <fun>
```

## 1.4 - $n^{th}$
```Ocaml
# let nth l n =
	if n <= 0 then
		invalid_arg "n <= 0"
	else
		let rec nthrec = function 
			| ([],_) -> failwith "list too short"
			| (h::_,1)-> h
			| (_::t, n) -> nthrec(t, n-1)
		in
			ntrec(l, n);;
val nth 'a list -> int -> 'a = <fun>

```

## 1.5 - Maximum
```Ocaml
# let rec max_value list = match list with 
	| [] -> failwith "La liste est vide" 
	| [x] -> x 
	| hd :: tl -> 
		let max_tail = max_value tl in 
		if hd > max_tail then hd else max_tail;;

(* v2 *)
# let max_value list = 
	if list = [] then
		failwith "la list est vide"
	else 
		let rec mv = match list with
			| [x] -> x 
			| hd :: tl -> 
				let max_tail = max_value tl in 
				if hd > max_tail then hd else max_tail
		in mv list;;

(* Correction *)
let maximum = function
	[] -> invalid_arg "Pas bô"
	| e::t ->
		(let rec max_rec m = function
			[]-> m
			|e::t -> max_rec (if e>m then e else m) t in max_rec e t);;
```

## 1.6 - Bonus second
```Ocaml
# let rec second_smallest list =
  match list with
  | [] | [_] -> failwith "La liste ne contient pas au moins deux éléments distincts"
  | [x; y] -> if x < y then y else x
  | hd1 :: hd2 :: tl ->
    let min1, min2 =
      if hd1 < hd2 then (hd1, hd2) else (hd2, hd1)
    in
    let rec find_second_smallest rest =
      match rest with
      | [] -> min2
      | hd :: tl ->
        if hd < min1 then find_second_smallest (min1 :: tl)
        else if hd < min2 && hd > min1 then find_second_smallest (hd :: min1 :: tl)
        else find_second_smallest (min2 :: tl)
    in
    find_second_smallest tl;;
```

## Exercise 2.1
```Ocaml
let rec arith_list n a1 r =
  if n <= 0 then []
  else a1 :: arithmetic_list (n - 1) (a1 + r) r;;

(*Other solution*)
# let arith_list n a1 r =
	if n <= 0 then
		invalid_arg "invalid rank n"
	else
		let rec f a i = function
			| 0 -> []
			| i -> (a1+(n-i)+r)::f(ai+r) (i-1)
		in f ai n;;
```

## Exercise 2.2
```Ocaml
let concatenate_lists lst1 lst2 =
  lst1 @ lst2;;
```

## Exercise 3.1
```Ocaml
let rec growing = function
		| [] | [_] -> true
		| x :: y :: rest -> if x <= y then growing (y :: rest) else false;;

let growing = function
	|[] -> true
	|l -> let rec g = function
		|[_]-> true
		| e1::e2::_ -> when e1 > e2 -> false
		| _::t -> gt
	in g l;;
```

## Exercise 3.2
```ocaml
let rec delete x = function
	| [] -> []
	| e::i -> 
		if x == e then i 
		else 
			e::delete x i

(* Correction *)
let rec delete x = function
	|[] -> []
	|e::t -> if e = x then
			t
		else if x < e then
			e::t
		else
			e::delete x t ;;
val delete: int -> 'a list -> list = <fun>

```

## Exercise 3.3
```Ocaml
# let rec length l = 
	if l = [] then 0
	else
		let e::t = l in
			1 +. length t;;
			
#let rec insert x i list =
	if x < 0 then
		invalid_arg "negative rank"
	else if i > length list then
		failwith "Out of bound"
	else

(* Correction *)
let insert_nth w i list =
	if i <= 0 then
		invalid_arg "negative rank"
	else
		let rec insrec i = function
			(1,l) -> x::l
			| (_, []) -> failwith "out of bound"
			| (i, e::t) -> e::insrec(i-1, t)
		in insrec i list;;
val insert_nth: 'a -> int -> 'a list -> 'a list = <fun>
```

## Exercise 3.4
```Ocaml
# let insert_post x y = function
	| [] -> failwith "list is too large or empty"
	| e::t -> if e = y then e::x::t else e::insert_post x y t;;
val insert_post : 'a -> 'a -> a' list -> list = <fun>
```

## Exercise 3.5
```Ocaml
let rec reverse = function 
	| [] -> []
	| e::t -> reverse t@[e];;
val reverse : 'a list -> 'a list = <fun>

(* Correction *)
# let reverse l = 
	let rec rev rl = function
		[] -> rl
		| e::t -> rev(e::rl) l
	in rev [] l
val reverse: 'a list -> 'a list = <fun>
```

## Exercise 4.1
```Ocaml
let rec equals l = function
	| [] when l = [] -> true
	| [] -> false
	| e::t -> if l = [] then false else (let e2::l2 = l in e = e2 + equal (l-1))
val equals = 'a list -> 'a list -> bool = <fun>
```

## Exercise 4.2
```Ocaml
let shared l1 l2 = function 
	| [] -> []
	| e::t -> let rec s l2 = function
		|e::t -> if e = e1 
					then e::sharede t t2 
				else if e2 > e then
					shared t (e2::t2)
				else
					shared (e::t) t2;;
val shard = 'a list -> 'a list -> 'a list -> 'a list = <fun>
```

## Exercise 5.1
```Ocaml
let assos k = function
	[] -> failwith "not found"
	| (k2, v2)::t when k2 = k -> v2
	| (k2, v2):: t when k < k2 -> faiwith "not found"
	| e::t -> assoc k t
val assos = 'a -> ('a + 'b) list -> 'b = <fun>

(*Correction*)
let assoc k l =
	if k < 0 then
			invalid_arg "k not a natural"
		else
			let rec findkey k = function
				[] -> failwith "not found"
				| (ke, ve)::t when k = ke -> ve
				| (ke, ve)::t when k < ke -> failwith "not found"
				| (ke, ve)::t -> findkey k t
			in findkey l;;
val assoc: int -> (int * 'a)list -> 'a = <fun>
```

## Exercise 5.2
```Ocaml
let rec flattten = function
	| [] -> []
	| e::t -> (match e with
		| [] -> flatten t
		| e2::t2 -> e2==flatten(2::t));;

val flatten: 'a list list -> 'a list = <fun>
```
Complexity : $O(\sum_{\forall{l\in{(el::ll)}}}^{}1+length(l))$

## Exercise 6.1
```Ocaml
let rec decompose x =
	let l = [] in
	if x = 1 then x::l
	else if x mod 2 == 0 then
		decompose(x/2)
	else if x mod 3 = 0 then
		decompose(x/3)
	else if x mod 5 = 0 then
		decompose(x/5)
	else if x mod 7 = 0 then
		decompose(x/7)
	else if x mod 9 = 0 then
		decompose(x/9)
	else if x mod 11 = 0 then
		decompose(x/11)
	else if x mod 13 = 0 then
		decompose(x/13)
	else x::l

