(* Exercice 1 *)
let rec fibo n = match n with
	|0 -> 0
	|1 -> 1
	|_ -> (fibo (n-1)) + (fibo (n-2));;
let fibot n =
	let rec aux acc1 acc2 n = match n with
		| 0 -> acc1
		| _ -> aux acc2 (acc2+acc1) (n-1) in
	aux 0 1 n;;

let comp fa fb i j =
	let debuta =Sys.time () in
	fa i j;
	let fina = Sys.time () in
	let debutb = Sys.time () in
	fb i j;
	let finb = Sys.time() in
	print_float (fina -. debuta);
	print_newline ();
	print_float (finb -. debutb);;
fibo 20;;
Sys.time ();;
comp fibot fibot 50000000;;

(* Exercice 2 *)

let rec numero x y = match y with
	|0 when x = 0 -> 0
	|0 -> numero 0 (x-1) + 1
	|_ -> numero (x+1) (y-1) + 1;;
let numero_ter x y =
	let rec aux acc x y = match y with
		|0 when x = 0 -> acc
		|0 -> aux (acc+1) 0 (x-1)
		|_ -> aux (acc+1) (x+1) (y-1) in
	aux 0 x y;;
numero_ter 2 2;;
let rec suite x y = match x with
	|0 -> [numero_ter 0 y]
	|_ -> (numero_ter x y)::(suite (x-1) y);;
suite 100 0;;
let numero_formule x y = (x+y)*(x+y+1)/2 + y ;;
numero 6 2;;

(* Exercice 3 *)

let binome k n =
	let m = Array.make_matrix (n+1) (k+1) 0 in
	for i = 0 to n do
		for j = 0 to k do
			if j = 0 then m.(i).(j) <- 1
			else if  i = 0 then m.(i).(j) <- 0
			else m.(i).(j) <- m.(i-1).(j) + m.(i-1).(j-1)
		done
	done;
	m.(n).(k);;
let rec binrec k n = match (k,n) with
	| (0,n) -> 1
	| (k,0) -> 0
	| _ -> binrec (k-1) (n-1) + binrec k (n-1);;
binrec 2 7;;
binome 2 7;;

comp binrec binome 12 22;;
(* La version itérative est plus rapide. *)
(* En effet, la version itérative ne calcule qu'une seule fois chacun
des coefficients là où la version récursive calcule à plusieures reprises
les mêmes coefficients *)

(* Exo Bonus *)

let rec binr n = match n with
	| 0 -> [""]
	| _ -> List.map (fun s -> "1"^s) (binr (n-1)) @ List.map (fun s -> "0"^s) (binr (n-1));;
binr 5;;

let binit n = 
	let rec puis x n = match n with
		| 0 -> 1
		| _ -> x * (puis x (n-1)) in
	let aux = fun x -> match x with | true -> 0 | false -> 1 in
	let res = Array.make (puis 2 n) "" in
	for i = 0 to (puis 2 n) - 1 do
		let cur = ref "" in
		for j = n downto 1 do
			cur:= !cur ^ string_of_int (aux ( (i / (j)) mod 2  = 0))
			done;
		res.(i) <- !cur
	done;
	res;;
binit 3;;