epicours/Algo/B1/Séminaire/Exercices seminaire.md

554 lines
11 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Exercise 2.2 (Power)
```Ocaml
(*First version ; 6 multiplications*)
# let power28(x) =
let x2 = x + x in
let x4 = x2*x2 in
let x8 = x4*x4 in
let x16 = x8*x8 in
x16*x8*x4 ;;
(*Second version ; 27 multiplications*)
# let power28(x) = x*x*x*x*x*x...*x ;;
(*Third version ; 11 multiplications*)
# let power28(x) =
let sq(x) = x*x in
let pow4(x) = sq(sq(x)) in
pow4(pow4(x))*sq(pow4(x))*pow4(x);;
(*Fourth version ; 7 multiplications*)
# let power28(x)=
let sq(x) = x+x in
let p4=sq(sq(x)) in
sq(sq(p4))*sq(p4)*p4;;
```
## Exercise 2.3
```Ocaml
# (*my verison*)
# let mirror(n) = let diz = n/10 and uni = n mod 10 in uni*10 + diz;;
val mirror : int -> int = <fun>
# (*teatcher version*)
# let mirror n = 10 *(n mod 10)+n/10;;
val mirror : int -> int = <fun>
```
```Ocaml
# let abba(n) = n*100 + mirror(n) ;;
val abba: int -> int = <fun>
```
```Ocaml
# let stammer(n) = abba(mirror(n)) * 10 000 + abba(n) ;;
val stammer: int -> int = <fun>
```
## Exercice 2.6
```Ocaml
let sec_of_time h m s =
h*3600 + m*60 + s ;;
let time_of_sec s =
let hours = s/3600 in let minutes = (s - hours*3600)/60 in let seconds = s - hours *3600 - minutes * 60 in (hours, minutes, seconds);;
let add_times h1 m1 s1 h2 m2 s2 =
let sec1 = sec_of_time h1 m1 s1 and sec2 = sec_of_time h2 m2 s2 in let resultsec = sec1 + sec2 in time_of_sec resultsec ;;
```
## Exercise 3.1
```Ocaml
let add a b =
if a > b then
a-b + a/b
else
b-a + b/a
let test x y = (if x> y then x else y ) *(x+y);;
let f a b c =
let g x y = (x+y)*(x-y) in
if a > b then
if b > c then (a+b)*(a-b) else (c+a) *(a-c)
else
if a > c then (a+b)*(a-b) else (b+c) * (b-c);;
let f a b c =
(if a > b && if b > c then
a + b else c + a
else if a > c then a + b else b + c)*
(if a > b && b > c then
a - b else a - c
else if a > c then a-b else b-c);;
```
### Exercise 3.2
```OCaml
(*logical and*)
# let and_if a b =
if a then
b
else false;;
val and_if: bool -> bool -> bool = <fun>
(*logical or*)
# let or_if a b =
if a then true
else b;;
val or_if: bool -> bool -> bool = <fun>
(*logical implication*)
# let imply_if a b =
if a then b
else true;;
val imply_if: bool -> bool -> bool = <fun>
(*logical exclusive or*)
let xor a b =
if a then
if b then false else true
else
if b then true else false
(*logical equivalence = a b*)
let equiv a b =
if a then b
else
if b then false else true (*not b*)
```
### Exercise 3.3
```Ocaml
# let max2 number1 number2 = if number1 > number2 then number1 else number2
val max2 : 'a -> 'a -> 'a = <fun>
# let min2 number1 number2 = if number1 > number2 then number2 else number1
val min2 : 'a -> 'a -> 'a = <fun>
# let max3 x y z =
let high = if x > y then x else y in
if high > z then
high
else z;;
val max3 : 'a -> 'a -> 'a -> 'a = <fun>
# let min3 x y z =
let low = if x < y then x else y in
if low < z then
low
else z;;
val min3 : 'a -> 'a -> 'a -> 'a = <fun>
# let middle3 x y z =
x + y + z - min3 x y z - max x y z ;;
val middle3 = int -> int -> int = <fun>
#let max4 number1 number2 number3 number4 =
let nb1 = max2(number1 number2) and nb2 = max2(number3 number4) in max2(nb1 nb2)
# let max4 x y z t= max2(max2 x y)(max2 z t)
val max4 : 'a -> 'a -> 'a -> 'a -> 'a = <fun>
# let min4 x y z t= min2(min2 x y)(min2 z t)
```
### Exercise 3.4
```Ocaml
let highest_square_sum x y z =
let sq x = x*x in
sq(max3 x y z) + sq(middle3 x y z)
val highest_square_sum : int -> int -> int -> int = <fun>
```
## Exercise 3.7
```Ocaml
# let rate_eco kg = match kg with
x when x <= 500 -> 3.40
| x when x <=1000 -> 4.60
| x when x <= 2000 -> 5.10
| x when x <= 3000 -> 6.90
| _ -> invalid_arg "Cannot be more than 3000g";;
val rate_eco : int -> float = <fun>
# let rate_standard kg = match kg with
x when x <= 500 -> 4.60
| x when x <=1000 -> 5.90
| x when x <= 2000 -> 6.50
| x when x <= 3000 -> 7.20
| _ -> invalid_arg "Cannot be more than 3000g";;
val rate_standart : int -> float = <fun>
# let rate_express kg = match kg with
x when x <= 500 -> 9.10
| x when x <=1000 -> 11.
| x when x <= 2000 -> 13.5
| x when x <= 3000 -> 14.2;
| _ -> invalid_arg "Cannot be more than 3000g";;
val rate_express : int -> float = <fun>
# let rate rt kg = match rt with
| ^x when x = "economic" -> rate_eco(kg)
| x when x = "standard" -> rate_standard(kg)
| x when x = "express" -> rate_express(kg)
| _ -> invalid_arg "Bad type of shipping class";;
val rate : string -> int -> float = <fun>
(*4th question*)
let price w (p1, p2, p3, p4) =
if w <=500 then p1
else if w <=1000 then p2
else if w <=2000 then p3
else if w <=3000 then p4
else failwith "Too heavy";;
val price = int -> 'a * 'a * 'a * 'a -> 'a = <fun>
```
## Exercise 3.9
```Ocaml
let apm = function
| (0, 0) -> 2
| (0, y) -> 1
| (x, 0) -> 1
| (x, y) -> 0
| _ -> invalid_arg "Error";;
val amp: int*int -> int = <fun>
let strange = function
| (0, n) -> 0
| (m, 0) -> 2*m
| (m, n) -> m*n ;;
val strange: int*int -> int = <fun>
let or3 = function
| (true, _, _) -> true
| (_, true, _) -> true
| (_, _, true) -> true
| _ -> false
val or3: bool*bool*bool -> bool = <fun>
let or3-simple = function
| (false, false, false) -> false
| _ -> true
val or3-simple: bool*bool*bool -> bool = <fun>
```
### Exercise 3.10
```Ocaml
let time_difference (d1, md1, sd1, pos1) (d2, md2, sd2, pos2)
```
## Exercise 4.2
```Ocaml
let rec sequence = function
| 0 -> 1
| n -> 4* sequence(n-1) - 1;;
val sequence : int -> int = <fun>
```
```mermaid
flowchart LR
A[seq 3] --> B[4*seq2-1] --> C[4*seq1-1] --> D[4*seq0-1] --> E[1] --> F[4*1-1] --> G[4*3-1] --> H[4*11-1]
```
## Exercise 4.3
```Ocaml
# let geometric n u0 q =
let rec geo = function
| 0 -> u0
|n -> q*geo(n-1) in geo n;;
```
## Exercise 4.4
```Ocaml
# let rec gcd a b =
if a mod b = 0 then
b
else
gcd b (a mod b);;
```
## Exercise 4.5
```Ocaml
let rec add a = function
| 0 -> a
| b -> 1 + add a (b-1);;
```
## Exercise 4.6
```Ocaml
let rec mult a b =
if a = 0 || b = 0 then
0
else if b > 0 then
a + mult a (b - 1)
else
-mult a (-b) ;;
```
## Exercise 4.7
```Ocaml
let rec quo a b =
if a < b || b = 0 then
0
else if b = 1 then
a
else
1 + quo (a-b) b ;;
```
## Exercise 4.9
```Ocaml
let rec reverse n =
let str_n = string_of_int n in
let len = String.length str_n in
let rec reverse_helper index =
if index < 0 then
""
else
String.make 1 str_n.[index] ^ reverse_helper (index - 1)
in
reverse_helper (len - 1) ;;
let rec reverse_int n =
let rec reverse_helper acc remaining =
if remaining = 0 then
acc
else
let last_digit = remaining mod 10 in
let new_acc = acc * 10 + last_digit in
let new_remaining = remaining / 10
in reverse_helper new_acc new_remaining in reverse_helper 0 n ;;
```
## Exercise 4.9 - Correction
```Ocaml
# let reverse = function
| 0 -> " "
| n -> string_of_int(n mod 10) ^ reverse(n/10);;
val reverse : int -> string = <fun>
# let reverse_int =
let rec rev inv = function
| 0 -> inv
| n -> rev (inv*10 + n mod 10)(n/10)
in rev 0 n;;
```
## Exercise 4.10
```Ocaml
let rec multiply x y =
if x = 0 || y = 0 then
0
else if x mod 2 = 0 then
multiply (x / 2) (y * 2)
else
y + multiply (x / 2) (y * 2)
(*correction*)
# let egypt a b =
let (a, b) = if a > b then (a,b) else (b,a) in
let rec eg = function
| 0 -> 0
| b -> 2*eg(b/2) + (if b mod 2 = 0 then 0 else a)
in
eg b;;
```
## Exercise 4.11
```Ocaml
let rec puissance x n =
if n = 0 then
1
else
x*puissance x (n-1);;
let rec puissance_better x n =
if n = 0 then
1
else if n mod 2 = 0 then
let pb = puissance_better x (n/2) in pb*pb
else
let pb_odd = puissance_better x (n/2) * n in pb_odd*pb_odd;;
(*Correction v1*)
let power x n = match n with
| 0 -> (match x with
| 0. -> failwith "power 0^0 impossible"
| _ -> 1.)
| _ -> (match x with
| 1. -> 1.
| 0. -> 0.
| -1. -> if n mod 2 = 0 then 1. else -1.)
| _ -> (let rec p = function
| 0 -> 1.
| n -> x*.p(n-1) in p n)
;;
(*Correction v2*)
let power x n = match n with
| 0 -> (match x with
| 0. -> failwith "power 0^0 impossible"
| _ -> 1.)
| _ -> (match x with
| 1. -> 1.
| 0. -> 0.
| -1. -> if n mod 2 = 0 then 1. else -1.)
| _ -> (let rec p = function
| 0 -> 1.
| n -> (let res. = p x (n/2) in
res *. res *. (if n mod 2 = 1 then x else 1.)
in p x n)
;;
(*Correction v3*)
let power x n = match n with
| 0 -> (match x with
| 0. -> failwith "power 0^0 impossible"
| _ -> 1.)
| _ -> (match x with
| 1. -> 1.
| 0. -> 0.
| -1. -> if n mod 2 = 0 then 1. else -1.)
| _ -> (let rec p x = function
| 0 -> 1.
| n -> p (x*x) (n/2) *. (if n mod 2 = 1 then x else 1.)
in p x n)
;;
```
Complexity :
$$
x^0 -> 1 \ | \
x^1 -> (x^0)^2 -> 2 \ | \
x^2 -> x^1 -> 3 \ | \
x^4 -> x^2 -> 4 \ | \
x^8 -> x^4 -> 5 \ | \
x^16 -> x^8 -> 6 \ | \
x^(2^k) -> x^(2^k-1) -> k+2 \approx{k} \ | \
n = 2^k -> K*log(n) \ | \
log(n) = log(2^k) = k
$$
$$
= O(log(n))
$$
## Exercise 4.12 - Prime number
```OCaml
(* V1 *)
let prime n =
if n < 1 then
invalid_args "n should not be inferior to zero"
else if x = 2 then true
else
let rec pr n k =
if n = k then
true
else if n mod k = 0 then
false
else
check n (k + 1)
in pr n 2;;
(* V2 *)
let prime n =
if n < 1 then
invalid_args "n should not be inferior to zero"
else if x = 2 then true
else
let rec pr n k =
if n = k then
true
else if n mod k = 0 then
false
else
check n (k + 1)
in (n = 2) || (n mod 2 = 1 and check n 3)
(*correction*)
let is_prime n =
if n < 2 then
invalid_arg "is_prime undefined for n < 2"
else
if n mod 2 = 0 tjen
n = 2
else
let rec check d =
if d*d > n then
true
else if n mod d = 0 then
false
else
check (d + 2);
check 3;;
```
## 4.13 - Perfect
```Ocaml
let is_perfect n =
if n < 1 then
invalid_arg "is_perfect: undefinded for n < 1"
else
let rec perfect d =
if d = n then
1
else if n mod d > n then
d + perfect (d + 1)
else
perfect (d + 1)
in perfect d;;
(*v2*)
let is_perfect n =
if n < 1 then
invalid_arg "is_perfect: undefinded for n < 1"
else
let rec perfect d =
if d*d >= n then
1 + (if d*d = n then d else 0)
else if n mod d > n then
d + n/d + sumd (d+1)
else
perfect (d + 1)
in perfect d;;
```
## Hanoi
```Ocaml
(* displays moves: source -> destination *)
let move source destination =
  print_int source ;
  print_string " -> " ;
  print_int destination ;
  print_newline()
;;
let hanoi n =
  let rec play n source auxiliary destination =
    if n = 1 then
      move source destination
    else
    begin
      play (n-1) source destination auxiliary;
      move source destination;
      play (n-1) auxiliary source destination
    end
  in
  if n < 0 then
    invalid_arg "Hanoi: number of disks invalid"
  else
    play n 1 2 3
;;
hanoi 3;;
```