Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • paul.albuquer-main-patch-90746
  • main
  • paul.albuquer-main-patch-24020
  • added_codes
4 results

Target

Select target project
  • algorithmique / cours
  • aurelien.boyer / cours
  • jeremy.meissner / cours
  • radhwan.hassine / cours
  • yassin.elhakoun / coursAlgo
  • gaspard.legouic / cours
  • joachim.bach / cours
  • gabriel.marinoja / Algo_cours
  • loic.lavorel / cours
  • iliya.saroukha / cours
  • costanti.volta / cours
  • jacquesw.ndoumben / cours
12 results
Select Git revision
  • master
1 result
Show changes

Commits on Source 281

181 additional commits have been omitted to prevent performance issues.
698 files
+ 125834
2154
Compare changes
  • Side-by-side
  • Inline

Files

+11 −7
Original line number Original line Diff line number Diff line
# Remerciements et contributions
# Remerciements et contributions


Merci aux contributeurs suivants pour leurs efforts (dans un ordre aléatoire):
Merci aux contributeurs suivants pour leurs efforts (dans un ordre alphabétique):


* P. Kunzli
* A. Boyer
* G. Legouic
* P. Albuquerque
* P. Albuquerque
* O. Malaspinas
* J. Bach
* A. Escribano
* A. Boyer
* M. Corboz
* M. Corboz
* M. Divià
* Y. El Hakouni
* A. Escribano
* P. Kunzli
* G. Legouic
* G. Marino Jarrin
* H. Radhwan
* I. Saroukhanian
* I. Saroukhanian
* C. Volta
+1 −4
Original line number Original line Diff line number Diff line
*.pdf
*.pdf
*.json
*.err
*.err
*.markdown
*.html
index.md
.puppeteer.json
+3 −2
Original line number Original line Diff line number Diff line
@@ -18,14 +18,15 @@ all: puppeteer $(PDF)
# all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf
# all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf


docker: docker-compose.yml
docker: docker-compose.yml
	docker-compose run slides
	docker compose run slides


docker_clean: docker-compose.yml
docker_clean: docker-compose.yml
	docker-compose run slides clean
	docker compose run slides clean


puppeteer:
puppeteer:
	@echo "Setting chromium to $(CHROMIUM) for puppeteer"
	@echo "Setting chromium to $(CHROMIUM) for puppeteer"
	@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json
	@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json
	# @echo "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json


index.md: gen_index.sh
index.md: gen_index.sh
	$(shell ./gen_index.sh)
	$(shell ./gen_index.sh)
+10 −219
Original line number Original line Diff line number Diff line
---
---
title: "Introduction aux algorithmes"
title: "Introduction aux algorithmes I"
date: "2022-09-21"
date: "2025-09-16"
---
---


# Qu'est-ce qu'un algorithme?
# Qu'est-ce qu'un algorithme?
@@ -42,7 +42,7 @@ de résoudre typiquement une classe de problèmes ou effectuer un calcul.


. . .
. . .


* Opérateurs (arthimétiques / booléens)
* Opérateurs (arithmétiques / booléens)
* Boucles;
* Boucles;
* Structures de contrôle;
* Structures de contrôle;
* Fonctions;
* Fonctions;
@@ -79,7 +79,7 @@ booléen est_premier(nombre)


```C
```C
booléen est_premier(nombre) // fonction
booléen est_premier(nombre) // fonction
    soit i = 2;       // variable, type, assignation
    soit i = 2       // variable, type, assignation
    tant que i < nombre // boucle
    tant que i < nombre // boucle
        si nombre modulo i == 0 // expression typée
        si nombre modulo i == 0 // expression typée
            retourne faux    // expression typée
            retourne faux    // expression typée
@@ -99,7 +99,7 @@ bool est_premier(int nombre) {
        if (0 == nombre % i) { // is i divise nombre
        if (0 == nombre % i) { // is i divise nombre
            return false; // i n'est pas premier
            return false; // i n'est pas premier
        }
        }
        i += 1; // sinon on incrémente i
        i = i + 1; // sinon on incrémente i
    }
    }
    return true;
    return true;
}
}
@@ -121,8 +121,8 @@ bool est_premier(int nombre) {


- Il existe une multitude d'options de compilation:
- Il existe une multitude d'options de compilation:


    ```bash
    ```console
    $ gcc -O1 -std=c11 -Wall -Wextra -g porg.c -o prog 
    $ gcc -O1 -std=c11 -Wall -Wextra -g prog.c -o prog 
    	-fsanitize=address 
    	-fsanitize=address 
    ```
    ```
    1. `-std=c11` utilisation de C11.
    1. `-std=c11` utilisation de C11.
@@ -240,7 +240,7 @@ int main() {


# Quiz: compile ou compile pas?
# Quiz: compile ou compile pas?


## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033948)
## [Quiz: compile ou compile pas](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501934)


# Types de base (1/4)
# Types de base (1/4)


@@ -288,7 +288,7 @@ Type Signification


# Quiz: booléens
# Quiz: booléens


## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1032492)
## [Quiz: booléens](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501922)


<!-- TODO Quiz en ligne -->
<!-- TODO Quiz en ligne -->
<!-- ```C
<!-- ```C
@@ -332,7 +332,7 @@ if (x) { /* vrai */ }


# Quiz: conversions
# Quiz: conversions


## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033446)
## [Quiz: conversions](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501925)


<!-- TODO Quiz en ligne -->
<!-- TODO Quiz en ligne -->
<!-- ```C
<!-- ```C
@@ -347,212 +347,3 @@ bool d = 2.78; // 1
bool e = 1.0; // 1
bool e = 1.0; // 1
``` -->
``` -->
# Expressions et opérateurs (1/6)

Une expression est tout bout de code qui est **évalué**.

## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033629)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |

# Expressions et opérateurs (6/6)

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |


# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
} else {
    printf("Ni l'un ni l'autre.\n");
}
```

# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)

## Pièges

```C
int x, y;
x = y = 3;
if (x = 2)
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
else
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

# Quiz: `if ... else`{.C}

## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=1033916)


# Structures de contrôle: `while`{.C}

## La boucle `while`{.C}

```C
while (condition) {
    instructions;
}
do {
    instructions;
} while (condition);
```

## La boucle `while`{.C}, un exemple

```C
int sum = 0; // syntaxe C99
while (sum < 10) {
    sum += 1;
}
do {
    sum += 10;
} while (sum < 100)
```

# Structures de contrôle: `for`{.C}

## La boucle `for`{.C}

```C
for (expression1; expression2; expression3) {
    instructions;
}
```

## La boucle `for`{.C}

```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
    sum += i;
}

for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
    printf("C'est plus ésotérique.\n");
}
```
+210 −10
Original line number Original line Diff line number Diff line
---
---
title: "Introduction aux algorithmes"
title: "Introduction aux algorithmes II"
date: "2022-09-28"
date: "2025-09-23"
---
---


# Rappel (1/2)
# Rappel


* Quel est l'algorithme pour le calcul des nombres 1ers?
* Quel est l'algorithme pour le calcul des nombres 1ers?


@@ -22,16 +22,216 @@ bool est_premier(int nombre) {
}
}
```
```


# Rappel (2/2)
# Expressions et opérateurs (1/6)


* Quelles structures de contrôles avons nous vues?
Une expression est tout bout de code qui est **évalué**.


. . .
## Expressions simples

- Pas d'opérateurs impliqués.
- Les littéraux, les variables, et les constantes.

```C
const int L = -1; // 'L' est une constante, -1 un littéral
int x = 0;        // '0' est un litéral
int y = x;        // 'x' est une variable
int z = L;        // 'L' est une constante
```

## Expressions complexes

- Obtenues en combinant des *opérandes* avec des *opérateurs*

```C
int x;     // pas une expression (une instruction)
x = 4 + 5; // 4 + 5 est une expression
           // dont le résultat est affecté à 'x'
```

# Expressions et opérateurs (2/6)

## Opérateurs relationnels

Opérateurs testant la relation entre deux *expressions*:

  - `(a opérateur b)` retourne `1`{.C} si l'expression s'évalue à `true`{.C}, `0`{.C} si l'expression s'évalue à `false`{.C}.

| Opérateur | Syntaxe      | Résultat             |
|-----------|--------------|----------------------|
| `<`{.C}   | `a < b`{.C}  | 1 si a <  b; 0 sinon |
| `>`{.C}   | `a > b`{.C}  | 1 si a >  b; 0 sinon |
| `<=`{.C}  | `a <= b`{.C} | 1 si a <= b; 0 sinon |
| `>=`{.C}  | `a >= b`{.C} | 1 si a >= b; 0 sinon |
| `==`{.C}  | `a == b`{.C} | 1 si a == b; 0 sinon |
| `!=`{.C}  | `a != b`{.C} | 1 si a != b; 0 sinon |

# Expressions et opérateurs (3/6)

## Opérateurs logiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `&&`{.C}  | `a && b`{.C} | ET logique           |
| `||`{.C}  | `a || b`{.C} | OU logique           |
| `!`{.C}   | `!a`{.C}     | NON logique          |

# Quiz: opérateurs logiques

## [Quiz: opérateurs logiques](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501928)

<!-- TODO: Quiz -->
<!-- ```C
1 && 0 == 0
7 && 3 == 1
4 || 3 == 1
!34 == 0
!0 == 1

Soit n un unsigned char initialisé à 127:
!n == 0
``` -->

# Expressions et opérateurs (4/6)

## Opérateurs arithmétiques

| Opérateur | Syntaxe      | Signification        |
|-----------|--------------|----------------------|
| `+`{.C}   | `a + b`{.C}  | Addition             |
| `-`{.C}   | `a - b`{.C}  | Soustraction         |
| `*`{.C}   | `a * b`{.C}  | Multiplication       |
| `/`{.C}   | `a / b`{.C}  | Division             |
| `%`{.C}   | `a % b`{.C}  | Modulo               |

# Expressions et opérateurs (5/6)

## Opérateurs d'assignation

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `=`{.C}   | `a = b`{.C}  | Affecte la valeur `b` à la variable `a`     |
|           |              | et retourne la valeur de `b`                |
| `+=`{.C}  | `a += b`{.C} | Additionne la valeur de `b` à `a` et        |
|           |              | assigne le résultat à `a`.                  |
| `-=`{.C}  | `a -= b`{.C} | Soustrait la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `*=`{.C}  | `a *= b`{.C} | Multiplie la valeur de `b` à `a` et         |
|           |              | assigne le résultat à `a`.                  |
| `/=`{.C}  | `a /= b`{.C} | Divise la valeur de `b` à `a` et            |
|           |              | assigne le résultat à `a`.                  |
| `%=`{.C}  | `a %= b`{.C} | Calcule le modulo la valeur de `b` à `a` et |
|           |              | assigne le résultat à `a`.                  |

# Expressions et opérateurs (6/6)

## Opérateurs d'assignation (suite)

| Opérateur | Syntaxe      | Signification                               |
|-----------|--------------|---------------------------------------------|
| `++`{.C}  | `++a`{.C}    | Incrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a += 1`).            |
| `--`{.C}  | `--a`{.C}    | Décrémente la valeur de `a` de 1 et         |
|           |              | retourne le résultat (`a -= 1`).            |
| `++`{.C}  | `a++`{.C}    | Retourne `a`{.C} et incrémente `a` de 1.    |
| `--`{.C}  | `a--`{.C}    | Retourne `a`{.C} et décrémente `a` de 1.    |


# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (1/2)

## Syntaxe

```C
if (expression) {
    instructions;
} else if (expression) { // optionnel
                         // il peut y en avoir plusieurs
    instructions;
} else {
    instructions; // optionnel
}
```

```C
if (x) { // si x s'évalue à `vrai`
    printf("x s'évalue à vrai.\n");
} else if (y == 8) { // si y vaut 8
    printf("y vaut 8.\n");
} else {
    printf("Ni l'un ni l'autre.\n");
}
```

# Structures de contrôle: `if`{.C} .. `else if`{.C} .. `else`{.C} (2/2)

## Pièges

```C
int x, y;
x = y = 3;
if (x = 2)
    printf("x = 2 est vrai.\n");
else if (y < 8)
    printf("y < 8.\n");
else if (y == 3)
    printf("y vaut 3 mais cela ne sera jamais affiché.\n");
else
    printf("Ni l'un ni l'autre.\n");
    x = -1; // toujours évalué
```

# Quiz: `if ... else`{.C}

## [Quiz: `if ... else`{.C}](https://cyberlearn.hes-so.ch/mod/evoting/view.php?id=501931)


# Structures de contrôle: `while`{.C}

## La boucle `while`{.C}

```C
while (condition) {
    instructions;
}
do {
    instructions;
} while (condition);
```

## La boucle `while`{.C}, un exemple

```C
int sum = 0; // syntaxe C99
while (sum < 10) {
    sum += 1;
}
do {
    sum += 10;
} while (sum < 100);
```

# Structures de contrôle: `for`{.C}

## La boucle `for`{.C}

```C
for (expression1; expression2; expression3) {
    instructions;
}
```

## La boucle `for`{.C}

```C
int sum = 0; // syntaxe C99
for (int i = 0; i < 10; i++) {
    sum += i;
}

for (int i = 0; i != 1; i = rand() % 4) { // ésotérique
    printf("C'est plus ésotérique.\n");
}
```


* La boucle `while`,
* La boucle `do ... while`,
* La boucle `for`,
* La condition `if ... else if ... else`,


# Exercice: la factorielle
# Exercice: la factorielle


+102 −55
Original line number Original line Diff line number Diff line
---
---
title: "Introduction aux algorithmes"
title: "Introduction aux algorithmes III"
date: "2022-10-05"
date: "2025-09-30"
patat:
  eval:
    tai:
      command: fish
      fragment: false
      replace: true
    ccc:
      command: fish
      fragment: false
      replace: true
  images:
    backend: auto
---
---


# Rappel (1/2)
# Rappel (1/2)
@@ -23,7 +11,6 @@ patat:


* L'algorithme de la factorielle.
* L'algorithme de la factorielle.
* L'algorithme du PPCM.
* L'algorithme du PPCM.
* Le début de l'algorithme du PGCD.


# Rappel (2/2)
# Rappel (2/2)


@@ -46,6 +33,92 @@ int main() {
}
}
```
```


# Le calcul du PPCM (1/2)

## Réusinage: Comment décrire une fonction qui ferait ce calcul (arguments, sorties)?

. . .

En `C` on pourrait la décrire comme

```C
int ppcm(int a, int b); // La **signature** de cette fonction
```

. . .

## Algorithme

Par groupe de 3 (5-10min):

* réfléchissez à un algorithme alternatif donnant le PPCM de deux nombres;
* écrivez l'algorithme en pseudo-code.

. . .

* Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a * i = b * j`  ou encore `p / a = i` et `p / b = j`.


# Le calcul du PPCM (2/2)


## Pseudo-code

```C
int ppcm(int a, int b) {
    for (i in [1, b]) {
        if a * i est divisible par b {
            return a * i
        }
    }
}
```

# Le code du PPCM de 2 nombres (1/2)

## Implémentez le pseudo-code et postez le code sur matrix (5min).

. . .

## Un corrigé possible


```C
#include <stdio.h>
#include <stdlib.h> 
int main() { 
   int n = 15, m = 12;
   int i = 1;
   while (n * i % m != 0) {
      i++;
   }
   printf("Le ppcm de %d et %d est %d\n", n, m, n*i);
}
```

# Le code du PPCM de 2 nombres (2/2)

## Corrigé alternatif

```C
#include <stdio.h>
#include <stdlib.h> 
int main() { 
   int res = n*m;
   for (int i = 2; i <= m; i++) {
     if (n * i % m == 0) {
        res = n * i;
        break;
     }
   }
   printf("Le ppcm de %d et %d est %d\n", n, m, res);
}
```





# Le calcul du PGCD (1/5)
# Le calcul du PGCD (1/5)


## Définition
## Définition
@@ -102,7 +175,9 @@ PGCD(36, 90):


# Le calcul du PGCD (3/5)
# Le calcul du PGCD (3/5)


## Transcrivez cet exemple en algorithme (groupe de 3) et codez-le (5-10min)!
\footnotesize

## Transcrivez cet exemple en algorithme et codez-le (5-10min)!


. . .
. . .


@@ -158,16 +233,15 @@ Par groupe de 3 (5-10min):
## Pseudo-code
## Pseudo-code


```C
```C
entier pgcd(m, n) {
entier pgcd(m, n)
    tmp_n = n
    tmp_n = n
    tmp_m = m
    tmp_m = m
    tant que (tmp_m ne divise pas tmp_n) {
    tant que (tmp_m ne divise pas tmp_n)
        tmp   = tmp_n
        tmp   = tmp_n
        tmp_n = tmp_m
        tmp_n = tmp_m
        tmp_m = tmp modulo tmp_m
        tmp_m = tmp modulo tmp_m
    }
    retourne tmp_m
    retourne tmp_m
}

```
```


# Le code du PGCD de 2 nombres
# Le code du PGCD de 2 nombres
@@ -197,10 +271,10 @@ void main() {


# Quelques algorithmes simples
# Quelques algorithmes simples


* Remplissage d'un tableau et recherche de la valeur minimal
* Stockage d'une liste de nombre et recherche de la valeur minimale
* Anagrammes
* Anagrammes
* Palindromes
* Palindromes
* Crible dratosthène
* Crible d’Ératosthène


. . .
. . .


@@ -210,8 +284,8 @@ void main() {


\footnotesize
\footnotesize


* Objets de même type: leur nombre est **connu à la compilation**;
* Objets de même type: leur nombre est **connu à la compilation**
* Stockés contigüement en mémoire (très efficace);
* Stockés de façon contiguë en mémoire (très efficace)


    ```C
    ```C
    #define SIZE 10
    #define SIZE 10
@@ -235,8 +309,7 @@ void main() {


# Remarques
# Remarques


* Depuis  `C99` possibilité d'avoir des tableaux dont la taille est *inconnue à
* Depuis  `C99` la taille peut être *inconnue à la compilation* (VLA);
  la compilation*;


    ```C
    ```C
    int size;
    int size;
@@ -247,8 +320,7 @@ void main() {
 . . .
 . . .


* Considéré comme une mauvaise pratique: que se passe-t-il si `size == 1e9`?
* Considéré comme une mauvaise pratique: que se passe-t-il si `size == 1e9`?
* On préfère utiliser l'allocation **dynamique** de mémoire pour ce genre de
* On préfère utiliser l'allocation **dynamique** de mémoire pour ce genre de cas-là (spoiler du futur du cours).
  cas-là (spoiler du futur du cours).


# Initialisation
# Initialisation


@@ -273,6 +345,7 @@ for (int i = 0; i < SIZE; ++i) {
    tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0; 
    tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0; 
    // tab[i] contient un double dans [-5;5]
    // tab[i] contient un double dans [-5;5]
}
}
int other_tab[4] = {0}; // pareil que {0, 0, 0, 0}
```
```


# Recherche du minimum dans un tableau (1/2)
# Recherche du minimum dans un tableau (1/2)
@@ -304,36 +377,10 @@ pour i de 1 à SIZE - 1
int index = 0;
int index = 0;
float min = tab[0];
float min = tab[0];
for (int i = 1; i < SIZE; ++i) {
for (int i = 1; i < SIZE; ++i) {
    if min > tab[i] {
    if (min > tab[i]) {
        min = tab[i];
        min = tab[i];
        index = i;
        index = i;
    }
    }
}
}
```
```
# Tri par sélection (1/2)

## Problématique

Trier un tableau par ordre croissant.

## Idée d'algorithme

```C
ind = 0
tant que (ind < SIZE-1)
    Trouver le minimum du tableau, tab_min[ind:SIZE].
    Échanger tab_min avec tab[ind]
    ind += 1
```

# Tri par sélection (2/2)

## Implémentation par groupe de 3

* Initialiser aléatoirement un tableau de `double` de taille 10;
* Afficher le tableau;
* Trier par sélection le tableau;
* Afficher le résultat trié;
* Vérifier algorithmiquement que le résultat est bien trié.
+62 −665
Original line number Original line Diff line number Diff line
---
---
title: "Introduction aux algorithmes"
title: "Introduction aux algorithmes IV"
date: "2022-10-19"
date: "2025-10-07"
---
---


# Rappel
# Le tri par sélection

\Huge Le tri par sélection

# Tri par sélection (1/3)

## Problématique

Trier un tableau par ordre croissant.

## Idée d'algorithme

```C
ind = 0
tant que (ind < SIZE-1)
    Trouver le minimum du tableau, tab_min = min([ind:SIZE-1]).
    Échanger tab_min avec tab[ind]
    ind += 1
```

# Tri par sélection (2/3)


## Quel est l'algorithme du tri par sélection?
## Quel est l'algorithme du tri par sélection?


. . .
. . .


1. Soit un tableau d'entiers, `tab[0:SIZE-1]` et `i = 0`.
1. Soit un tableau d'entiers, `tab[0:SIZE-1]` et `i = 0`.
2. Trouver l'indice, `j`, de `tab[i:SIZE-2]` où la valeur est minimale.
2. Trouver l'indice, `j`, de `tab[i:SIZE-1]` où la valeur est minimale.
3. Échanger `tab[i]` et `tab[j]`.
3. Échanger `tab[i]` et `tab[j]`.
4. `i+=1` et revenir à 2, tant que `j < SIZE-2`.
4. `i += 1` et revenir à 2, tant que `i < SIZE-1`.

# Tri par sélection (3/3)

## Implémentation par groupe de 3

* Initialiser aléatoirement un tableau de `double` de taille 10;
* Afficher le tableau;
* Trier par sélection le tableau;
* Afficher le résultat trié;
* Vérifier algorithmiquement que le résultat est bien trié.

# Les chaînes de caractères

\Huge Les chaînes de caractères


# Un type de tableau particulier
# Un type de tableau particulier


@@ -82,6 +116,8 @@ char name[100] = "Paul is not 100 characters long.";


# Fonctions
# Fonctions


\footnotesize

- Il existe une grande quantités de fonction pour la manipulation de chaînes de caractères dans `string.h`.
- Il existe une grande quantités de fonction pour la manipulation de chaînes de caractères dans `string.h`.
- Fonctions principales:
- Fonctions principales:


@@ -98,11 +134,19 @@ char name[100] = "Paul is not 100 characters long.";
    int strcmp(char *str1, char *str2);
    int strcmp(char *str1, char *str2);
    ```
    ```


- Pour avoir la liste complète: `man string`.
- Pour avoir la liste complète: `man 3 string`.


. . .
. . .


## Quels problèmes peuvent se produire avec `strlen`, `strcpy`, `strcmp`?
## Quel problème peut se produire avec `strlen`, `strcpy`, `strcmp`?

. . .

- Si `\0` est absent... on a un comportement indéfini.

# Les anagrammes

\Huge Les anagrammes


# Les anagrammes
# Les anagrammes


@@ -141,10 +185,14 @@ int main() { // pseudo C
}
}
```
```


<!-- TODO: Live implémentation hors des cours? -->
# Les palindromes

\Huge Les palindromes


# Les palindromes
# Les palindromes


\footnotesize

Mot qui se lit pareil de droite à gauche que de gauche à droite:
Mot qui se lit pareil de droite à gauche que de gauche à droite:


. . .
. . .
@@ -158,7 +206,7 @@ Mot qui se lit pareil de droite à gauche que de gauche à droite:
## Solution 1
## Solution 1


```C
```C
while (first_index < last_index {
while (first_index < last_index) {
    if (mot[first_index] != mot [last_index]) {
    if (mot[first_index] != mot [last_index]) {
        return false;
        return false;
    }
    }
@@ -177,6 +225,10 @@ mot_tmp = revert(mot);
return mot == mot_tmp;
return mot == mot_tmp;
```
```


# Le crible d'Ératosthène

\Huge Le crible d'Ératosthène

# Crible d'Ératosthène
# Crible d'Ératosthène


Algorithme de génération de nombres premiers.
Algorithme de génération de nombres premiers.
@@ -194,658 +246,3 @@ Algorithme de génération de nombres premiers.


* Implémenter l'algorithme et le poster sur le salon `Element`.
* Implémenter l'algorithme et le poster sur le salon `Element`.
# Crible d'Ératosthène: solution

\footnotesize

```C
#include <stdio.h>
#include <stdbool.h>
#define SIZE 51
int main() {
   bool tab[SIZE];
   for (int i=0;i<SIZE;i++) {
      tab[i] = true;  
   }
   for (int i = 2; i < SIZE; i++) {
      if (tab[i]) {
         printf("%d ", i);
         int j = i;
         while (j < SIZE) {
            j += i;
            tab[j] = false;
         } 
      } 
   }
   printf("\n");
}
```


# Réusinage de code (refactoring)

## Le réusinage est?

. . .

* le processus de restructuration d'un programme:
    * en modifiant son design,
    * en modifiant sa structure,
    * en modifiant ses algorithmes
    * mais en **conservant ses fonctionalités**.

. . .

## Avantages?

. . .

* Amélioration de la lisibilité,
* Amélioration de la maintenabilité,
* Réduction de la complexité.

. . .

## "Make it work, make it nice, make it fast",  Kent Beck.

. . .

## Exercice:

* Réusiner le code se trouvant sur
  [Cyberlearn](https://cyberlearn.hes-so.ch/mod/resource/view.php?id=1627712).

# Tableau à deux dimensions (1/4)

## Mais qu'est-ce donc?

. . .

* Un tableau où chaque cellule est un tableau.

## Quels cas d'utilisation?

. . .

* Tableau à double entrée;
* Image;
* Écran (pixels);
* Matrice (mathématique);
 
# Tableau à deux dimensions (2/4)

## Exemple: tableau à 3 lignes et 4 colonnes d'entiers

+-----------+-----+-----+-----+-----+
| `indices` | `0` | `1` | `2` | `3` |
+-----------+-----+-----+-----+-----+
| `0`       | `7` | `4` | `7` | `3` |
+-----------+-----+-----+-----+-----+
| `1`       | `2` | `2` | `9` | `2` |
+-----------+-----+-----+-----+-----+
| `2`       | `4` | `8` | `8` | `9` |
+-----------+-----+-----+-----+-----+

## Syntaxe

```C
int tab[3][4]; // déclaration d'un tableau 4x3
tab[2][1]; // accès à la case 2, 1
tab[2][1] = 14; // assignation de 14 à la position 2, 1
```

# Tableau à deux dimensions (3/4)

## Exercice: déclarer et initialiser aléatoirement un tableau `50x100`

. . .

```C
#define NX 50
#define NY 100
int tab[NX][NY];
for (int i = 0; i < NX; ++i) {
    for (int j = 0; j < NY; ++j) {
        tab[i][j] = rand() % 256; // 256 niveaux de gris
    }
}
```
 
## Exercice: afficher le tableau

. . .

```C
for (int i = 0; i < NX; ++i) {
    for (int j = 0; j < NY; ++j) {
        printf("%d ", tab[i][j]);
    }
    printf("\n");
}
```

# Tableau à deux dimensions (4/4)

## Attention

* Les éléments ne sont **jamais** initialisés.
* Les bornes ne sont **jamais** vérifiées.

    ```C
    int tab[3][2] = { {1, 2}, {3, 4}, {5, 6} };
    printf("%d\n", tab[2][1]);  // affiche?
    printf("%d\n", tab[10][9]); // affiche?
    printf("%d\n", tab[3][1]);  // affiche?
    ```
    
# La couverture de la reine

* Aux échecs la reine peut se déplacer horizontalement et verticalement
* Pour un échiquier `5x6`, elle *couvre* les cases comme ci-dessous

+-----+-----+-----+-----+-----+-----+-----+
| ` ` | `0` | `1` | `2` | `3` | `4` | `5` |
+-----+-----+-----+-----+-----+-----+-----+
| `0` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `1` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `2` | `*` | `*` | `R` | `*` | `*` | `*` |
+-----+-----+-----+-----+-----+-----+-----+
| `3` | ` ` | `*` | `*` | `*` | ` ` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+
| `4` | `*` | ` ` | `*` | ` ` | `*` | ` ` |
+-----+-----+-----+-----+-----+-----+-----+

## Exercice

* En utilisant les conditions, les tableaux à deux dimensions, et des
  `char` uniquement.
* Implémenter un programme qui demande à l'utilisateur d'entrer les
  coordonnées de la reine et affiche un tableau comme ci-dessus pour un
  échiquier `8x8`.

## Poster le résultat sur `Element`

# Types énumérés (1/2)

* Un **type énuméré**: ensemble de *variantes* (valeurs constantes).
* En `C` les variantes sont des entiers numérotés à partir de 0.

    ```C
    enum days {
        monday, tuesday, wednesday,
        thursday, friday, saturday, sunday
    };
    ```
* On peut aussi donner des valeurs "custom"

    ```C
    enum days {
        monday = 2, tuesday = 8, wednesday = -2,
        thursday = 1, friday = 3, saturday = 12, sunday = 9
    };
    ```
* S'utilise comme un type standard et un entier

    ```C
    enum days d = monday;
    (d + 2) == tuesday + tuesday; // true
    ```

# Types énumérés (2/2)

* Très utile dans les `switch ... case`{.C}

    ```C
    enum days d = monday;
    switch (d) {
        case monday:
            // trucs
            break;
        case tuesday:
            printf("0 ou 1\n");
            break;
    }
    ```
* Le compilateur vous prévient qu'il en manque!

# Utilisation des types énumérés

## Réusiner votre couverture de la reine avec des `enum`

# Représentation des nombres (1/2)

* Le nombre `247`.

## Nombres décimaux: Les nombres en base 10 

+--------+--------+--------+
| $10^2$ | $10^1$ | $10^0$ |
+--------+--------+--------+
| `2`    | `4`    | `7`    |
+--------+--------+--------+

$$
247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
$$

# Représentation des nombres (2/2)

* Le nombre `11110111`.

## Nombres binaires: Les nombres en base 2

+-------+-------+-------+-------+-------+-------+-------+-------+
| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
+-------+-------+-------+-------+-------+-------+-------+-------+
| `1`   | `1`   | `1`   | `1`   | `0`   | `1`   | `1`   | `1`   |
+-------+-------+-------+-------+-------+-------+-------+-------+
 
$$
1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
+1\cdot 2^1 +1\cdot 2^0
$$

. . .

$$
= 247.
$$

# Conversion de décimal à binaire (1/2)

## Convertir 11 en binaire?

. . .

* On décompose en puissances de 2 en partant de la plus grande possible

    ```
    11 / 8 = 1, 11 % 8 = 3
    3  / 4 = 0,  3 % 4 = 3
    3  / 2 = 1,  3 % 2 = 1
    1  / 1 = 1,  1 % 1 = 0
    ```
* On a donc

    $$
    1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
    2^0=11.
    $$

# Conversion de décimal à binaire (2/2)

## Convertir un nombre arbitraire en binaire: 247?

* Par groupe établir un algorithme.

. . .

## Algorithme

1. Initialisation
    
    ```C
    num = 247
    while (2^N < num) {
        N += 1
    }
    ```

. . .

2. Boucle

    ```C
    while (N >= 0) {
        bit = num / 2^N
        num = num % 2^N
        N += 1
    }
    ```

# Les additions en binaire

Que donne l'addition `1101` avec `0110`?

* L'addition est la même que dans le système décimal

    ```
       1101         8+4+0+1 = 13
    +  0110    +    0+4+2+0 =  6
    -------    -----------------
      10011      16+0+0+2+1 = 19
    ```
* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
* Que se passe-t-il donc ici?

. . .

## Dépassement de capacité: le nombre est "tronqué"

* `10011 (19) -> 0011 (3)`.
* On fait "le tour"."

# Entier non-signés minimal/maximal

* Quel est l'entier non-signé maximal représentable avec 4 bit?

. . .

$$
(1111)_2 = 8+4+2+1 = 15
$$

* Quel est l'entier non-signé minimal représentable avec 4 bit?

. . .

$$
(0000)_2 = 0+0+0+0 = 0
$$

* Quel est l'entier non-signé min/max représentable avec N bit?

. . .

$$
0\mbox{ et  }2^N-1.
$$

* Donc `uint32_t?` maximal est?

. . .

$$
4294967295
$$


# Les multiplications en binaire (1/2)

Que donne la multiplication de `1101` avec `0110`?

* L'addition est la même que dans le système décimal

    ```
         1101                13
    *    0110    *            6
    ---------    --------------
         0000                78
        11010
       110100
    + 0000000
    ---------    --------------
      1001110    64+0+0+8+4+2+0
    ```

# Les multiplications en binaire (2/2)

## Que fait la multiplication par 2?

. . .

* Décalage de un bit vers la gauche!

    ```
         0110
    *    0010
    ---------
         0000
    +   01100
    ---------
        01100
    ```

. . .

## Que fait la multiplication par $2^N$?

. . .

* Décalade de $N$ bits vers la gauche!

# Entiers signés (1/2)

Pas de nombres négatifs encore...

## Comment faire?

. . .

## Solution naïve:

* On ajoute un bit de signe (le bit de poids fort):

    ```
    00000010: +2
    10000010: -2
    ```

## Problèmes?

. . .

* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
* Les additions différentes que pour les non-signés (très grave)
    
    ```
      00000010              2    
    + 10000100           + -4
    ----------           ----
      10000110 = -6  !=    -2
    ```

# Entiers signés (2/2)

## Beaucoup mieux

* Complément à un:
    * on inverse tous les bits: `1001 => 0110`.

## Encore un peu mieux

* Complément à deux:
    * on inverse tous les bits,
    * on ajoute 1 (on ignore les dépassements).

. . .

* Comment écrit-on `-4` en 8 bits?

. . .

```
     4 =  00000100
            ________
    -4 =>   00000100
            
            11111011
          + 00000001 
          ----------
            11111100
```

# Le complément à 2 (1/2)

## Questions:

* Comment on écrit `+0` et `-0`?
* Comment calcule-t-on `2 + (-4)`?
* Quel est le complément à 2 de `1000 0000`?

. . .

## Réponses

* Comment on écrit `+0` et `-0`?

    ```
    +0 = 00000000
    -0 = 11111111 + 00000001 = 100000000 => 00000000 
    ```
* Comment calcule-t-on `2 + (-4)`?

    ```
      00000010            2
    + 11111100        +  -4
    ----------        -----
      11111110           -2
    ```
* En effet

    ```
    11111110 => 00000001 + 00000001 = 00000010 = 2.
    ```

# Le complément à 2 (1/2)

## Quels sont les entiers représentables en 8 bits?

. . .

```
01111111 =>  127
10000000 => -128 // par définition
```

## Quels sont les entiers représentables sur $N$ bits?

. . .

$$
-2^{N-1} ... 2^{N-1}-1.
$$

## Remarque: dépassement de capacité en `C`

* Comportement indéfini!


<!-- # TODO --

<!-- ## Entiers, entiers non-signés -->

<!-- ## Complément à 1, 2 -->

<!-- ## Nombres à virgule flottante, simple/double précision -->

# Types composés: `struct`{.C} (1/6)

## Fractions

* Numérateur: `int num`;
* Dénominateur: `int denom`.

## Addition

```C
int num1 = 1, denom1 = 2;
int num2 = 1, denom2 = 3;
int num3 = num1 * denom2 + num2 * denom1;
int denom3 = denom1 * denom2;
```

## Pas super pratique....

# Types composés: `struct`{.C} (2/6)

## On peut faire mieux

* Plusieurs variables qu'on aimerait regrouper dans un seul type: `struct`{.C}.

```C
struct fraction { // déclaration du type
    int32_t num, denom;
}

struct fraction frac; // déclaration de frac
```

# Types composés: `struct`{.C} (3/6)

## Simplifications

- `typedef`{.C} permet de définir un nouveau type.

    ```C
    typedef unsinged int uint;
    typedef struct fraction fraction_t;
    typedef struct fraction {
        int32_t num, denom;
    } fraction_t;
    ```
- L'initialisation peut aussi se faire avec

    ```C
    fraction_t frac = {1, -2}; // num = 1, denom = -2
    fraction_t frac = {.denom = 1, .num = -2};
    fraction_t frac = {.denom = 1}; // argl! .num non initialisé 
    fraction_t frac2 = frac; // copie
    ```

# Types composés: `struct`{.C} (4/6)

## Pointeurs

- Comme pour tout type, on peut avoir des pointeurs vers un `struct`{.C}.
- Les champs sont accessible avec le sélecteur `->`{.C}

    ```C
    fraction_t *frac; // on crée un pointeur
    frac->num = 1;    // seg fault...
    frac->denom = -1; // mémoire pas allouée.
    ```

![La représentation mémoire de
`fraction_t`.](figs/pointer_struct.svg){width=50%}

# Types composés: `struct`{.C} (5/6)

## Initialisation

- Avec le passage par **référence** on peut modifier un struct *en place*.
- Les champs sont accessible avec le sélecteur `->`{.C}

    ```C
    void fraction_init(fraction_t *frac, 
                      int32_t re, int32_t im) 
    {
        // frac a déjà été allouée
        frac->num   = frac;
        frac->denom = denom;
    }
    int main() {
        fraction_t frac; // on alloue une fraction
        fraction_init(&frac, 2, -1); // on l'initialise
    }
    ```

# Types composés: `struct`{.C} (6/6)

## Initialisation version copie

* On peut allouer une fraction, l'initialiser et le retourner.
* La valeur retournée peut être copiée dans une nouvelle structure.

    ```C
    fraction_t fraction_create(int32_t re, int32_t im) {
        fraction_t frac;
        frac.num = re;
        frac.denom = im;
        return frac;
    }
    int main() {
        // on crée une fraction et on l'initialise
        // en copiant la fraction créé par fraction_create
        // deux allocation et une copie
        fraction_t frac = fraction_create(2, -1); 
    }
    ```

<!-- # TODO jusqu'aux vacances -->

<!-- * Refactorisation -->
<!-- * Tris et complexité -->
<!-- * Récursivité -->
+126 −759

File changed.

Preview size limit exceeded, changes collapsed.

+289 −328

File changed.

Preview size limit exceeded, changes collapsed.

+619 −54
Original line number Original line Diff line number Diff line
---
---
title: "Tris"
title: "Récursivité, représentation des nombres, tris, et complexité"
date: "2022-11-16"
date: "2025-11-11"
header-includes: |
    \usepackage{xcolor}
---
---


# Rappel: Complexité
# Rappel


\footnotesize
## La récursivité

* Une condition de récursivité - qui *réduit* les cas successifs vers...
* Une condition d'arrêt - qui retourne un résultat

## Un exemple

```C
int factorial(int n) {
    if (n > 1) {
        return n * factorial(n - 1);
    } else {
        return 1;
    }
}
```


Soit `tab` un tableau de longueur `N` de `double`.
# Exponentiation rapide


1. Comment déclare-t-on un tel tableau?
\Huge L'exponentiation rapide ou indienne

# Exponentiation rapide ou indienne (1/3)

## But: Calculer $x^n$

* Quel est l'algorithmie le plus simple que vous pouvez imaginer?


. . .
. . .


```C
```C
double tab[N];
double pow(double x, int n) {
    if (0 == n) {
        return 1;
    }
    double p = x;
    for (int i = 1; i < n; ++i) {
        p = p * x; // p *= x
    }
    return p;
}
```
```


2. Quelle est la complexité du calcul de la moyenne de `tab`?
* Combien de multiplication et d'assignations en fonction de `n`?

. . .

* `n` assignations et `n` multiplications.

# Exponentiation rapide ou indienne (2/3)

* Proposez un algorithme naïf et récursif


. . .
. . .


```C
```C
double mean = 0.0;
double pow(double x, int n) {
for (int i = 0; i < N; ++i) { // N assignations
    if (n != 0) {
    mean += tab[i];        // N additions
        return x * pow(x, n-1);
    } else {
        return 1;
    }
}
}
mean /= N; // O(N)
```
```


. . .
# Exponentiation rapide ou indienne (3/3)

## Le vrai algorithme


3. Quelle est la complexité du calcul de l'écart type de `tab` ($\sigma=\sqrt{\sum_i (t_i - m)^2}/N$?
* Si n est pair: calculer $\left(x^{n/2}\cdot x^{n/2}\right)$;
* Si n est impair: calculer $x \cdot \left(x^{(n-1)/2}\right)^2=x\cdot x^{n-1}$.

## Exercice: écrire l'algorithme récursif correspondant


. . .
. . .


```C
```C
double mean = moyenne(N, tab); // O(N)
double pow(double x, int n) {
double dev = 0.0;
    if (0 == n) {
for (int i = 0; i < N; ++i) {
        return 1;
    dev += pow(tab[i] - moyenne, 2); // N tours
    } else if (n % 2 == 0) {
        return pow(x, n / 2) * pow(x, n/2);
    } else {
        return x * pow(x, (n-1));
    }
}
}
dev = sqrt(dev); dev /= N; // O(2*N) = O(N)
```
```


# Tri par insertion (1/3)
# Représentation des nombres


## But
\Huge La représentation des nombres


* trier un tableau par ordre croissant
# Représentation des nombres (1/2)


## Algorithme
* Le nombre `247`.

## Nombres décimaux: Les nombres en base 10 

+--------+--------+--------+
| $10^2$ | $10^1$ | $10^0$ |
+--------+--------+--------+
| `2`    | `4`    | `7`    |
+--------+--------+--------+

$$
247 = 2\cdot 10^2 + 4\cdot 10^1 + 7\cdot 10^0.
$$


Prendre un élément du tableau et le mettre à sa place parmis les éléments déjà
# Représentation des nombres (2/2)
triés du tableau.


![Tri par insertion d'un tableau d'entiers](figs/tri_insertion.svg)
* Le nombre `11110111`.


# Tri par insertion (2/3)
## Nombres binaires: Les nombres en base 2


## Exercice: Proposer un algorithme (en C)
+-------+-------+-------+-------+-------+-------+-------+-------+
| $2^7$ | $2^6$ | $2^5$ | $2^4$ | $2^3$ | $2^2$ | $2^1$ | $2^0$ |
+-------+-------+-------+-------+-------+-------+-------+-------+
| `1`   | `1`   | `1`   | `1`   | `0`   | `1`   | `1`   | `1`   |
+-------+-------+-------+-------+-------+-------+-------+-------+
 
$$
1\cdot 2^7 + 1\cdot 2^6 +1\cdot 2^5 +1\cdot 2^4 +0\cdot 2^3 +1\cdot 2^2
+1\cdot 2^1 +1\cdot 2^0
$$


. . .
. . .


$$
= 247.
$$

# Conversion de décimal à binaire (1/2)

## Convertir 11 en binaire?

. . .

* On décompose en puissances de 2 en partant de la plus grande possible

    ```
    11 / 8 = 1, 11 % 8 = 3
    3  / 4 = 0,  3 % 4 = 3
    3  / 2 = 1,  3 % 2 = 1
    1  / 1 = 1,  1 % 1 = 0
    ```
* On a donc

    $$
    1011 \Rightarrow 1\cdot 2^3 + 0\cdot 2^2 + 1\cdot 2^1 + 1\cdot
    2^0=11.
    $$

# Conversion de décimal à binaire (2/2)

## Convertir un nombre arbitraire en binaire: 247?

* Par groupe établir un algorithme.

. . .

## Algorithme

1. Initialisation
    
    ```C
    ```C
void tri_insertion(int N, int tab[N]) {
    num = 247
    for (int i = 1; i < N; i++) {
    N = 0
        int tmp = tab[i];

        int pos = i;
    tant que (2^(N+1) < num) {
        while (pos > 0 && tab[pos - 1] > tmp) {
        N += 1
            tab[pos] = tab[pos - 1];
            pos      = pos - 1;
        }
        tab[pos] = tmp;
    }
    }
    ```

. . .

2. Boucle

    ```C
    tant que (N >= 0) {
        bit = num / 2^N
        num = num % 2^N
        N -= 1
    }
    }
    ```
    ```


# Tri par insertion (3/3)
# Les additions en binaire

Que donne l'addition `1101` avec `0110`?


## Question: Quelle est la complexité?
* L'addition est la même que dans le système décimal

    ```
       1101         8+4+0+1 = 13
    +  0110    +    0+4+2+0 =  6
    -------    -----------------
      10011      16+0+0+2+1 = 19
    ```
* Les entiers sur un ordinateur ont une précision **fixée** (ici 4 bits).
* Que se passe-t-il donc ici?


. . .
. . .


* Parcours de tous les éléments ($N-1$ passages dans la boucle)
## Dépassement de capacité: le nombre est "tronqué"
    * Placer: en moyenne $i$ comparaisons et affectations à l'étape $i$

* Moyenne: $\mathcal{O}(N^2)$
* `10011 (19) -> 0011 (3)`.
* On fait "le tour"."

# Entier non-signés minimal/maximal

* Quel est l'entier non-signé maximal représentable avec 4 bit?


. . .
. . .


* Pire des cas, liste triée à l'envers: $\mathcal{O}(N^2)$
$$
* Meilleurs des cas, liste déjà triée: $\mathcal{O}(N)$
(1111)_2 = 8+4+2+1 = 15
$$


# L'algorithme à la main
* Quel est l'entier non-signé minimal représentable avec 4 bit?


## Exercice *sur papier*
. . .


* Trier par insertion le tableau `[5, -2, 1, 3, 10]`
$$
(0000)_2 = 0+0+0+0 = 0
$$


```C
* Quel est l'entier non-signé min/max représentable avec N bit?

. . .

$$
0\mbox{ et  }2^N-1.
$$

* Donc `uint32_t?` maximal est?

. . .

$$
2^{32}-1=4'294'967'295
$$


# Les multiplications en binaire (1/2)

Que donne la multiplication de `1101` avec `0110`?

* La multiplication est la même que dans le système décimal

    ```
         1101                13
    *    0110    *            6
    ---------    --------------
         0000                78
        11010
       110100
    + 0000000
    ---------    --------------
      1001110    64+0+0+8+4+2+0
    ```

# Les multiplications en binaire (2/2)

## Que fait la multiplication par 2?

. . .


* Décalage de un bit vers la gauche!


    ```
         0110
    *    0010
    ---------
         0000
    +   01100
    ---------
        01100
    ```


. . .


## Que fait la multiplication par $2^N$?


. . .


* Décalage de $N$ bits vers la gauche!


# Entiers signés (1/2)


Pas de nombres négatifs encore...


## Comment faire?


. . .


## Solution naïve:


* On ajoute un bit de signe (le bit de poids fort):


    ```
    ```
    00000010: +2
    10000010: -2
    ```

## Problèmes?

. . .

* Il y a deux zéros (pas trop grave): `10000000` et `00000000`
* Les additions différentes que pour les non-signés (très grave)
    
    ```
      00000010              2    
    + 10000100           + -4
    ----------           ----
      10000110 = -6  !=    -2
    ```

# Entiers signés (2/2)

## Beaucoup mieux

* Complément à un:
    * on inverse tous les bits: `1001 => 0110`.

## Encore un peu mieux

* Complément à deux:
    * on inverse tous les bits,
    * on ajoute 1 (on ignore les dépassements).

. . .

* Comment écrit-on `-4` en 8 bits?

. . .

```
     4 =  00000100
            ________
    -4 =>   00000100
            
            11111011
          + 00000001 
          ----------
            11111100
```

# Le complément à 2 (1/2)

\footnotesize

## Questions:

* Comment on écrit `+0` et `-0`?
* Comment calcule-t-on `2 + (-4)`?
* Quel est le complément à 2 de `1000 0000`?

. . .

## Réponses

* Comment on écrit `+0` et `-0`?

    ```
    +0 = 00000000
    -0 = 11111111 + 00000001 = 100000000 => 00000000 
    ```
* Comment calcule-t-on `2 + (-4)`?

    ```
      00000010            2
    + 11111100        +  -4
    ----------        -----
      11111110           -2
    ```
* En effet

    ```
    11111110 => 00000001 + 00000001 = 00000010 = 2.
    ```

# Le complément à 2 (2/2)

## Quels sont les entiers représentables en 8 bits?

. . .

```
01111111 =>  127
10000000 => -128 // par définition
```

## Quels sont les entiers représentables sur $N$ bits?

. . .

$$
-2^{N-1} ... 2^{N-1}-1.
$$

## Remarque: dépassement de capacité en `C`

* Comportement indéfini!


# Le tri rapide ou quicksort

\Huge Tri rapide ou quicksort


# Tri rapide ou quicksort (1/8)
# Tri rapide ou quicksort (1/8)


@@ -177,7 +478,7 @@ rien quicksort(entier tableau[], entier ind_min, entier ind_max)
        ind_pivot = partition(tableau, ind_min, ind_max)
        ind_pivot = partition(tableau, ind_min, ind_max)
        si (longueur(tableau[ind_min:ind_pivot-1]) != 0)
        si (longueur(tableau[ind_min:ind_pivot-1]) != 0)
            quicksort(tableau, ind_min, pivot_ind - 1)
            quicksort(tableau, ind_min, pivot_ind - 1)
        si (longueur(tableau[ind_pivot+1:ind_max-1]) != 0)
        si (longueur(tableau[ind_pivot+1:ind_max]) != 0)
            quicksort(tableau, ind_pivot + 1, ind_max)
            quicksort(tableau, ind_pivot + 1, ind_max)
```
```


@@ -253,7 +554,7 @@ int partition(int size, int array[size], int first, int last) {
}
}
```
```


# Tri rapide ou quicksort (8/8)
<!-- # Tri rapide ou quicksort (8/8)


## Quelle est la complexité du tri rapide?
## Quelle est la complexité du tri rapide?


@@ -267,7 +568,7 @@ int partition(int size, int array[size], int first, int last) {
    * Chaque fois le tableau est séparé en $2$ parties égales.
    * Chaque fois le tableau est séparé en $2$ parties égales.
    * On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot
    * On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot
      \log_2(N)$.
      \log_2(N)$.
* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$.
* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$. -->


# L'algorithme à la main
# L'algorithme à la main


@@ -291,5 +592,269 @@ int partition(int size, int array[size], int first, int last) {


```
```


# L'efficacité d'un algorithmique

\Huge L'efficacité d'un algorithmique

# Efficacité d'un algorithmique

Comment mesurer l'efficacité d'un algorithme?

. . .

* Mesurer le temps CPU,
* Mesurer le temps d'accès à la mémoire,
* Mesurer la place prise mémoire,

. . .

Dépendant du **matériel**, du **compilateur**, des **options de compilation**, etc!

## Mesure du temps CPU

```C
#include <time.h>
struct timespec tstart={0,0}, tend={0,0};
clock_gettime(CLOCK_MONOTONIC, &tstart);
// some computation
clock_gettime(CLOCK_MONOTONIC, &tend);
printf("computation about %.5f seconds\n",
       ((double)tend.tv_sec + 1e-9*tend.tv_nsec) - 
       ((double)tstart.tv_sec + 1e-9*tstart.tv_nsec));
```

# Programme simple: mesure du temps CPU

## Preuve sur un [petit exemple](../source_codes/complexity/sum.c)

```bash
source_codes/complexity$ make bench
RUN ONCE -O0
the computation took about 0.00836 seconds
RUN ONCE -O3
the computation took about 0.00203 seconds
RUN THOUSAND TIMES -O0
the computation took about 0.00363 seconds
RUN THOUSAND TIMES -O3
the computation took about 0.00046 seconds
```

Et sur votre machine les résultats seront **différents**.

. . .

## Conclusion

* Nécessité d'avoir une mesure indépendante du/de la
  matériel/compilateur/façon de mesurer/météo.

# Analyse de complexité algorithmique (1/4)

* On analyse le **temps** pris par un algorithme en fonction de la **taille de
  l'entrée**.

## Exemple: recherche d'un élément dans une liste triée de taille N

```C
int sorted_list[N];
bool in_list = is_present(N, sorted_list, elem);
```

* Plus `N` est grand, plus l'algorithme prend de temps sauf si...

. . .

* l'élément est le premier de la liste (ou à une position toujours la même).
* ce genre de cas pathologique ne rentre pas en ligne de compte.

# Analyse de complexité algorithmique (2/4)

## Recherche linéaire

```C
bool is_present(int n, int tab[], int elem) {
    for (int i = 0; i < n; ++i) {
        if (tab[i] == elem) {
            return true;
        } else if (elem < tab[i]) {
            return false;
        }
    }
    return false;
}
```

* Dans le **meilleurs des cas** il faut `1` comparaison.
* Dans le **pire des cas** (élément absent p.ex.) il faut `n` comparaisons.

. . .

La **complexité algorithmique** est proportionnelle à `N`: on double la taille
du tableau $\Rightarrow$ on double le temps pris par l'algorithme.

# Analyse de complexité algorithmique (3/4)

## Recherche dichotomique

```C
bool is_present_binary_search(int n, int tab[], int elem) {
    int left  = 0;
    int right = n - 1;
    while (left <= right) {
        int mid = (right + left) / 2;
        if (tab[mid] < elem) {
            left = mid + 1;
        } else if (tab[mid] > elem) {
            right = mid - 1;
        } else {
            return true;
        }
    }
    return false;
}
```

# Analyse de complexité algorithmique (4/4)

## Recherche dichotomique

![Source: [Wikipédia](https://upload.wikimedia.org/wikipedia/commons/a/aa/Binary_search_complexity.svg)](figs/Binary_search_complexity.svg){width=80%}

. . .

* Dans le **meilleurs de cas** il faut `1` comparaison.
* Dans le **pire des cas** il faut $\log_2(N)+1$ comparaisons

. . .

## Linéaire vs dichotomique

* $N$ vs $\log_2(N)$ comparaisons logiques.
* Pour $N=1000000$: `1000000` vs `21` comparaisons.

# Notation pour la complexité

## Constante de proportionnalité

* Pour la recherche linéaire ou dichotomique, on a des algorithmes qui sont $\sim N$ ou $\sim \log_2(N)$
* Qu'est-ce que cela veut dire?

. . .

* Temps de calcul est $t=C\cdot N$ (où $C$ est le temps pris pour une comparaisons sur une machine/compilateur donné)
* La complexité ne dépend pas de $C$.

## Le $\mathcal{O}$ de Leibnitz

* Pour noter la complexité d'un algorithme on utilise le symbole $\mathcal{O}$ (ou "grand Ô de").
* Les complexités les plus couramment rencontrées sont

. . .

$$
\mathcal{O}(1),\quad \mathcal{O}(\log(N)),\quad \mathcal{O}(N),\quad
\mathcal{O}(\log(N)\cdot N), \quad \mathcal{O}(N^2), \quad
\mathcal{O}(N^3).
$$

# Ordres de grandeur

\begin{table}[!h]  
\begin{center} 
\caption{Valeurs approximatives de quelques fonctions usuelles de complexité.} 
\medskip 
\begin{tabular}{|c|c|c|c|c|} 
\hline 
$\log_2(N)$ & $\sqrt{N}$      & $N$    & $N\log_2(N)$    & $N^2$     \\ 
\hline\hline 
$3$         & $3$             & $10$   & $30$            & $10^2$    \\ 
\hline 
$6$         & $10$            & $10^2$ & $6\cdot 10^2$   & $10^4$    \\ 
\hline 
$9$         & $31$            & $10^3$ & $9\cdot 10^3$   & $10^6$    \\ 
\hline 
$13$        & $10^2$          & $10^4$ & $1.3\cdot 10^5$ & $10^8$    \\ 
\hline 
$16$        & $3.1\cdot 10^2$ & $10^5$ & $1.6\cdot 10^6$ & $10^{10}$ \\ 
\hline 
$19$        & $10^3$          & $10^6$ & $1.9\cdot 10^7$ & $10^{12}$ \\ 
\hline 
\end{tabular} 
\end{center} 
\end{table} 


# Quelques exercices (1/3)

## Complexité de l'algorithme de test de primalité naïf?

```C
for (i = 2; i < sqrt(N); ++i) {
    if (N % i == 0) {
        return false;
    }
}
return true;
```

. . .

## Réponse 

$$
\mathcal{O}(\sqrt{N}).
$$

# Quelques exercices (2/3)

## Complexité de trouver le minimum d'un tableau?

```C
int min = MAX;
for (i = 0; i < N; ++i) {
    if (tab[i] < min) {
        min = tab[i];
    }
}
return min;
```

. . .

## Réponse 

$$
\mathcal{O}(N).
$$

# Quelques exercices (3/3)

## Complexité du tri par sélection?

```C
int ind = 0;
while (ind < SIZE-1) {
    min = find_min(tab[ind:SIZE]);
    swap(min, tab[ind]);
    ind += 1;
}
```

. . .

## Réponse

### `min = find_min`

$$
(N-1)+(N-2)+...+2+1=\sum_{i=1}^{N-1}i=N\cdot(N-1)/2=\mathcal{O}(N^2).
$$

## Finalement

$$
\mathcal{O}(N^2\mbox{ comparaisons}) + \mathcal{O}(N\mbox{swaps})=\mathcal{O}(N^2).
$$



slides/exemples/pgcd.c

0 → 100644
+43 −0
Original line number Original line Diff line number Diff line
/*
 * entier pgcd(a, b):
 *   v_min = min(a, b)
 *   tant que a % v_min != 0 ou b % v_min != 0:
 *       v_min -= 1
 *   retourne v_min
 */

#include <stdio.h>

int pgcd_1(int a, int b) {
    int v_min = a > b ? b : a;
    while (a % v_min != 0 || b % v_min != 0) {
        v_min -= 1;
    }
    return v_min;
}

/*
 * entier pcgd(a, b):
 *  tant que b != 0:
 *      tmp = b
 *      b = a % b
 *      a = tmp
 *
 *  return a
 */

int pgcd_2(int a, int b) {
    while (b != 0) {
        int tmp = b;
        b = a % b;
        a = tmp;
    }
    return a;
}

int main() {
    int a = 36;
    int b = 90;
    printf("pgcd_1(%d, %d) = %d\n", a, b, pgcd_1(a, b));
    printf("pgcd_2(%d, %d) = %d\n", a, b, pgcd_2(a, b));
}
+33 −0
Original line number Original line Diff line number Diff line
#include <stdlib.h>
#include <stdio.h>

#define NX 8

int main() {
    int co = 1;
    int li = 2;

    char board[NX][NX];
    for (int i = 0; i < NX; ++i) {
        for (int j = 0; j < NX; ++j) {
            board[i][j] = ' ';
        }
    }

    for (int i = 0; i < NX; ++i) {
        for (int j = 0; j < NX; ++j) {
            if (i == co || j == li || i - j == co - li || i + j == li + co) {
                board[i][j] = '*';
            }
        }
    }
    board[co][li] = 'R';
    for (int i = 0; i < NX; ++i) {
        for (int j = 0; j < NX; ++j) {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }

    return EXIT_SUCCESS;
}
+78 −0
Original line number Original line Diff line number Diff line
// factorial(n):
//   return 1 * 2 * 3 * .... * n
//   return n * factorial(n-1)
//   return n * (n-1) * factorial(n-2)
//   return n * (n-1) * (n-2) * factorial(n-3)
//   ....
//   return n * (n-1) * (n-2) * (n-3) * (n-4) * (n-5) * (n-6) * ... * (n-1000) * ...
#include <stdio.h>
#include <stdlib.h>

int factorial(int n) {
    int prod = 1;
    for (int i = 1; i <= n; ++i) {
         prod *= i;
    }
    return prod;
}

// factorial_rec(5);
// return 5 * factorial_rec(4);
// return 5 * (4 * factorial_rec(3));
// return 5 * (4 * (3 * factorial_rec(2)));
// return 5 * (4 * (3 * (2 * factorial_rec(1))));
// return 5 * (4 * (3 * (2 * 1)));
int factorial_rec(int n) {
   if (n <= 1) {
        return 1;
    } else {
        return n * factorial_rec(n-1);
    }
}

double epsilon() {
    double eps = 1.0;
    while (1.0 != 1.0 + eps) {
        eps /= 2.0;
    }
    return eps;
}

double epsilon_rec(double eps) {
    if (1.0 != 1.0 + eps) {
        return epsilon_rec(eps / 2.0);
    }     
    return eps;
}

int pgcd(int a, int b) {
    int rest = a % b;
    if (rest == 0) {
        return b;
    } else {
        return pgcd(b, rest);
    }
}

int fib(int n) {
    if (n == 0) {
        return 0;
    } else if (n == 1) {
        return 1;
    } else {
        return fib(n-2) + fib(n-1);
    }
}

int main() {
    int val = factorial(10);
    printf("val = %d\n", val);
    int val_rec = factorial_rec(10);
    printf("val_rec = %d\n", val_rec);
    printf("espilon = %g\n", epsilon());
    printf("espilon_rec = %g\n", epsilon_rec(1.0));
    printf("pgcd(27, 42) = %d\n", pgcd(27, 42));
    printf("fib(8) = %d\n", fib(8));

    return EXIT_SUCCESS;
}
+64 −0
Original line number Original line Diff line number Diff line
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SIZE 10

void initialization_tab(int size, double tab[size]) {
    for (int i = 0; i < size; ++i) {
        tab[i] = rand() / (double)RAND_MAX;
    }
}

void swap(double *left, double *right) {
    double tmp = *left;  // déréférencement de left
    *left = *right;
    *right = tmp;
}

int index_min(int size, double tab[size], int i) {
    double min = tab[i];
    int ind_min = i;
    for (int j = i + 1; j < size; ++j) {
        if (min > tab[j]) {
            ind_min = j;
            min = tab[j];
        }
    }
    return ind_min;
}

void selection_sort(int size, double tab[size]) {
    for (int i = 0; i < size - 1; ++i) {
        // 1. Trouver l'indice auquel se trouve le minimum du tableau
        int ind_min = index_min(size, tab, i);
        // 2. Échanger la valeur minimale avec l'élément courant du tableau
        swap(&tab[i], &tab[ind_min]);
    }
}

void print_tab(int size, double tab[size]) {
    for (int i = 0; i < size; ++i) {
        printf("%f ", tab[i]);
    }
    printf("\n");
}

int is_sorted(int size, double tab[size]) {
    for (int i = 0; i < size - 1; ++i) {
        if (tab[i] > tab[i + 1]) {
            return EXIT_FAILURE;
        }
    }
    return EXIT_SUCCESS;
}

int main() {
    srand(0);
    // Déclaration: tableau
    double tab[SIZE];
    initialization_tab(SIZE, tab);
    selection_sort(SIZE, tab);
    print_tab(SIZE, tab);
    return is_sorted(SIZE, tab);
}
+32 −0
Original line number Original line Diff line number Diff line
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void init(int nx, int ny, int tab[nx][ny]) {
    for (int i = 0; i < nx; ++i) {
        for (int j = 0; j < ny; ++j) {
            tab[i][j] = rand() % 256;
        }
    }
}

void print(int nx, int ny, int tab[nx][ny]) {
    for (int i = 0; i < nx; ++i) {
        for (int j = 0; j < ny; ++j) {
            printf("%d\t", tab[i][j]);
        }
        printf("\n");
    }
}

int main() {
    srand(time(NULL));
    int nx = 10;
    int ny = 20;

    int tab[nx][ny];
    init(nx, ny, tab);
    print(nx, ny, tab);

    return EXIT_SUCCESS;
}
+18 −19
Original line number Original line Diff line number Diff line
---
---
title: "Introduction générale"
title: "Introduction générale"
date: "2022-09-20"
date: "2025-09-16"
---
---


# La hotline
# La hotline
@@ -11,10 +11,9 @@ Paul Albuquerque paul.albuquerque@hesge.ch B410
Orestis Malaspinas     orestis.malaspinas@hesge.ch       A401
Orestis Malaspinas     orestis.malaspinas@hesge.ch       A401
--------------------   ------------------------------    --------------------
--------------------   ------------------------------    --------------------


* Utilisez le libre service (l'horaire sera fixé prochainement).
- Utilisez le libre service (l'horaire sera fixé prochainement).
* On va intensivement utiliser *Element*, installez le et utilisez le!
- On va intensivement utiliser *Element*, installez le et utilisez le!

- Espace de discussion Matrix: <https://rb.gy/ku5es>, installez [element.io](https://element.io).
* Espace de discussion [Matrix](https://matrix.to/#/!aKYVlcclmPGYXQFxAK:matrix.org?via=matrix.org), installez [element.io](https://element.io).


    ![](figs/matrix_qr.png){width=20%}
    ![](figs/matrix_qr.png){width=20%}


@@ -23,31 +22,31 @@ Orestis Malaspinas orestis.malaspinas@hesge.ch A401
Tout le contenu de ce qu'on raconte se trouve sur cyberlearn:
Tout le contenu de ce qu'on raconte se trouve sur cyberlearn:


- Algorithmes et structures de données
- Algorithmes et structures de données
  - <https://cyberlearn.hes-so.ch/course/view.php?id=13941>
  - <https://cyberlearn.hes-so.ch/course/view.php?id=7276>
  - Clé d'inscription: algo_2021_22
  - Clé d'inscription: algo_2025_26


- Programmation Sequentielle en C
- Programmation quentielle en C
  - <https://cyberlearn.hes-so.ch/course/view.php?id=12399>
  - <https://cyberlearn.hes-so.ch/course/view.php?id=7282>
  - Clé d'inscription: prog_seq_2021_22
  - Clé d'inscription: prog_seq_2025_26




# Organisation du module
# Organisation du module


* Deux cours, 50% chacun.
## Cinq cours, 20% chacun.
1. Algorithmes et structures de données:

1. Algorithmes et structures de données (2 semestres):
    * 1er semestre:
    * 1er semestre:
        * bases de programmation en C jusqu'à Noël.
        * bases de programmation en C jusqu'à Noël,
        * algorithmique jusqu'à fin janvier.
        * algorithmique jusqu'à fin janvier.
    * 2e semestre:
    * 2ème semestre:
        * algorithmique.
        * algorithmique.
    * Deux évaluations écrites par semestre (1er: novembre et janvier).
    * Deux évaluations écrites par semestre (1er sem.: novembre et janvier).
2. Programmation séquentielle en C
2. Programmation séquentielle en C (2 semestres)
    * Familiarisation avec l'environnement Linux.
    * Familiarisation avec l'environnement Linux.
    * Travaux pratiques en C.
    * Travaux pratiques en C.
    * Apprentissage du gestionnaire de versions: git.
    * Apprentissage du gestionnaire de versions: git.
    * Plusieurs exercices illustrant les concepts d'algorithmique.
    * Plusieurs exercices illustrant les concepts d'algorithmique.
    * Évaluations:
    * Évaluations (4 tests machine).
        * Deux évaluations machine (1er semestre).
3. Programmation système (semestre de printemps)
        * Probablement, une évaluation machine et un projet (2e semestre).


+3 −3
Original line number Original line Diff line number Diff line
---
---
subtitle: "Algorithmique et structures de données, 2022-2023"
subtitle: "Algorithmes et structures de données, 2025-2026"
author: "P. Albuquerque (B410), P. Künzli et O. Malaspinas (A401), ISC, HEPIA"
author: "P. Albuquerque (B410) et O. Malaspinas (A401), ISC, HEPIA"
institute: En partie inspirés des supports de cours de P. Albuquerque
institute: En partie inspiré des supports de cours de P. Albuquerque
lang: fr-CH
lang: fr-CH
revealjs-url: /reveal.js
revealjs-url: /reveal.js
mathjaxurl: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML"
mathjaxurl: "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML"

slides_2022/Makefile

0 → 100644
+61 −0
Original line number Original line Diff line number Diff line
PDFOPTIONS = -t beamer
# PDFOPTIONS += -F pantable
PDFOPTIONS += -F mermaid-filter
PDFOPTIONS += --highlight-style my_highlight.theme
PDFOPTIONS += --pdf-engine xelatex
PDFOPTIONS += -V theme:metropolis
PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot
PDFOPTIONS += -V fontsize=smaller
PDFOPTIONS += -V urlcolor=blue

MD=$(wildcard *.md) # Tous les fichiers .md
PDF=$(MD:%.md=%.pdf) # Pour les fichier pdf on transforme .md -> .pdf
HTML=$(MD:%.md=%.html) # Pour les fichier html on transforme .md -> .html
MARKDOWN=$(MD:%.md=%.markdown) # Pour les fichier markdown on transforme .md -> .markdown
CHROMIUM:=$(shell which chromium || which chromium-browser)

all: puppeteer $(PDF) 
# all: puppeteer $(PDF) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf

docker: docker-compose.yml
	docker-compose run slides

docker_clean: docker-compose.yml
	docker-compose run slides clean

puppeteer:
	@echo "Setting chromium to $(CHROMIUM) for puppeteer"
	@echo -e "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json

index.md: gen_index.sh
	$(shell ./gen_index.sh)

index.html: index.md
	pandoc -s $(OPTIONS) --css ../css/tufte-css/tufte.css -o $@ $^

markdown: $(MARKDOWN) # La markdown les cibles %.markdown

%.pdf: %.md metadata.yaml # %.pdf (chaque fichier %.md génère un fichier avec le même nom mais l'extension .pdf et la dépendance metadata.yaml)
	pandoc -s $(OPTIONS) $(PDFOPTIONS) -o $@ $^

%.markdown: %.md metadata.yaml yq
	sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header
	grep -v -F -x -f  no_header $< > header.yaml
	echo "---" > tmp.yaml
	./yq_linux_amd64 merge metadata.yaml header.yaml >> tmp.yaml
	cat tmp.yaml no_header > $@
	rm no_header header.yaml tmp.yaml

yq: # On peut même télécharger un petit programme avec notre makefile
	wget -nc https://github.com/mikefarah/yq/releases/download/3.4.1/yq_linux_amd64
	chmod "u+x" yq_linux_amd64 

deploy: all index.html
	mkdir -p algo_cours
	cp *.pdf algo_cours
	cp index.html algo_cours

clean:
	rm -rf *.html *.pdf *.markdown yq_linux_amd64* index.md .puppeteer.json algo_cours *.err

.PHONY:	clean index.md puppeteer yq

slides_2022/cours_1.md

0 → 100644
+558 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+0 −0

File moved.

+2 −1
Original line number Original line Diff line number Diff line
@@ -461,11 +461,12 @@ node *matrix_to_qt(int nb_li, int nb_co, int matrix[nb_li][nb_co], int depth)


```C
```C
matrice arbre_à_matrice(arbre)
matrice arbre_à_matrice(arbre)
    matrice = creer_matrice(nb_lignes(arbre), nb_colonnes(arbre))
    pour li de 0 à nb_lignes(matrice)
    pour li de 0 à nb_lignes(matrice)
        pour co de 0 à nb_colonnes(matrice)
        pour co de 0 à nb_colonnes(matrice)
            noeud = position(li, co, arbre)
            noeud = position(li, co, arbre)
            matrice[co][li] = noeud.info
            matrice[co][li] = noeud.info
    retourne arbre
    retourne matrice
```
```


. . .
. . .

slides_2022/cours_2.md

0 → 100644
+317 −0
Original line number Original line Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2022-09-28"
---

# Rappel (1/2)

* Quel est l'algorithme pour le calcul des nombres 1ers?

. . .

```C
bool est_premier(int nombre) {
    int i = 2; // bonne pratique!
    while (i < nombre) { // penser à bien indenter!
        if (0 == nombre % i) { // ça rend le code LISIBLE!
            return false;
        }
        i += 1;
    }
    return true;
}
```

# Rappel (2/2)

* Quelles structures de contrôles avons nous vues?

. . .

* La boucle `while`,
* La boucle `do ... while`,
* La boucle `for`,
* La condition `if ... else if ... else`,

# Exercice: la factorielle

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un pseudo-code

. . .

```python
entier factorielle(entier n)
    i = 1
    fact = 1
    tant que i <= n
        fact *= i
        i += 1
    retourne fact
```

# Exercice: la factorielle

\footnotesize

Écrire un programme qui calcule la factorielle d'un nombre
$$
N! = 1\cdot 2\cdot ... \cdot (N-1)\cdot N.
$$

## Par groupe de 3: écrire un code en C

Quand vous avez fini postez le code sur le salon matrix.

. . .

```C
#include <stdio.h>
int main() {
   int nb = 10;
   int fact = 1;
   int iter = 2;
   while (iter <= nb) {
      fact *= iter;
      iter++;
   }
   printf("La factorielle de %d est %d\n", nb, fact);
}
```

. . .

## Comment améliorer ce code? (notez ça sur une feuille)


# Exercice: la factorielle en mieux

## Individuellement

1. Écrivez l'algorithme de calcul de deux façon différentes.
2. Que se passe-t-il si $n>=15$?
3. Pour celles et ceux qui ont fini pendant que les autres essaient: faites-le 
   en récursif (sans aide).

. . .

## Postez vos solutions sur **matrix**!

# Exercice: test si un nombre est premier

## Avec tout ce que vous avez appris jusqu'ici:

* Écrivez le code testant si un nombre est premier.
* Quels sont les ajouts possibles par rapport au code de la semaine passée?
* Rencontrez-vous des problèmes éventuels de compilation?
* Voyez-vous une façon de générer des nombres premiers avec votre programme?

. . .

## Implémentez-la et postez votre code sur le salon matrix (10 min).

# Corrigé: enfin pas vraiment mais juste un possible

\footnotesize 

```C
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
int main() {
   int nb = 1;
   printf("Entrez un nombre: ");
   scanf("%d", &nb);
   bool premier = true;
   for (int div = 2; div <= sqrt(nb); div++) {
      if (nb % div == 0) {
         premier = false;
         break;
      }
   }
   if (premier) {
      printf("Le nombre %d est premier\n", nb);
   } else {
      printf("Le nombre %d n'est pas premier\n", nb);
   }
   return 0;
}
```

# Quelques algorithmes simples

## Voyons quelques algorithmes supplémentaires

- Plus petit commun multiple (PPCM) de deux nombres
- Autre algorithme de calcul du PPCM de deux nombres
- Plus grand commun diviseur (PGCD) de deux nombres

# Le calcul du PPCM (1/5)

## Définition

Le plus petit commun multiple (PPCM), `p`, de deux entiers non nuls, `a` et `b`,
est le plus petit entier strictement positif qui soit multiple de ces deux
nombres.

Exemples:

```C
PPCM(3, 4) = 12,
PPCM(4, 6) = 12,
PPCM(5, 15) = 15.
```

. . .

## Mathématiquement

Décomposition en nombres premiers:

$$
36 = 2^2\cdot 3^2,\quad 90=2\cdot 5\cdot 3^2,
$$
On garde tous les premiers à la puissance la plus élevée
$$
PPCM(36, 90)=2^2\cdot 3^2\cdot 5=180.
$$

# Le calcul du PPCM (2/5)

## Exemple d'algorithme

```C
PPCM(36, 90):
36  < 90  // 36  + 36
72  < 90  // 72  + 36
108 > 90  // 90  + 90
108 < 180 // 108 + 36
144 < 180 // 144 + 36
180 = 180 // The End!
```

* 5 additions, 5 assignations, et 6 comparaisons.

. . .

## Transcrivez cet exemple en algorithme (groupe de 3), 5min

. . .

## et codez-le!


# Le calcul du PPCM (3/5)

## Tentative de correction

```C
int main() { 
    int m = 15, n = 12;
    int mult_m = m, mult_n = n;
    while (mult_m != mult_n) {
        if (mult_m > mult_n) {
            mult_n += n;
        } else {
            mult_m += m;
        }
    }
    printf("Le ppcm de %d et %d est %d\n", n, m, mult_m);
}
```

. . .

* Combien d'additions / comparaisons au pire?

# Le calcul du PPCM (4/5)

## Réusinage: Comment décrire une fonction qui ferait ce calcul (arguments, sorties)?

. . .

En `C` on pourrait la décrire comme

```C
int ppcm(int a, int b); // La **signature** de cette fonction
```

. . .

## Algorithme

Par groupe de 3 (5-10min):

* réfléchissez à un algorithme alternatif donnant le PPCM de deux nombres;
* écrivez l'algorithme en pseudo-code.

# Le calcul du PPCM (5/5)

## Indication

Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a
* i = b * j`  ou encore `p / a = i` et `p / b = j`.

. . .

## Pseudo-code

```C
int ppcm(int a, int b) {
    for (i in [1, b]) {
        if a * i est divisible par b {
            return a * i
        }
    }
}
```

# Le code du PPCM de 2 nombres (1/2)

## Implémentez le pseudo-code et postez le code sur matrix (5min).

. . .

## Un corrigé possible


```C
#include <stdio.h>
#include <stdlib.h> 
int main() { 
   int n = 15, m = 12;
   int i = 1;
   while (n * i % m != 0) {
      i++;
   }
   printf("Le ppcm de %d et %d est %d\n", n, m, n*i);
}
```

# Le code du PPCM de 2 nombres (2/2)

## Corrigé alternatif

```C
#include <stdio.h>
#include <stdlib.h> 
int main() { 
   int res = n*m;
   for (int i = 2; i <= m; i++) {
     if (n * i % m == 0) {
        res = n * i;
        break;
     }
   }
   printf("Le ppcm de %d et %d est %d\n", n, m, res);
}
```



+1 −1
Original line number Original line Diff line number Diff line
@@ -429,7 +429,7 @@ rien compression_avec_pertes(arbre, theta)
```C
```C
arbre = matrice_à_arbre(matrice)
arbre = matrice_à_arbre(matrice)
moyenne(arbre)
moyenne(arbre)
compression_sans_pertes(arbre)
compression_avec_pertes(arbre)
```
```


# La dynamique des corps célestes
# La dynamique des corps célestes
+0 −0

File moved.

+1 −1
Original line number Original line Diff line number Diff line
@@ -157,7 +157,7 @@ booléen est_feuille(page)


entier position(page, valeur)
entier position(page, valeur)
    i = 0
    i = 0
    tant que i < page.nb && val >= page.tab[i+1].clef
    tant que i < page.nb && valeur >= page.tab[i+1].clef
        i += 1
        i += 1
    retourne i
    retourne i


+4 −4
Original line number Original line Diff line number Diff line
@@ -256,7 +256,7 @@ E&=\{(1,2),(2,3),(2,4),(4,1)\},\\


:::: column
:::: column


![Un graphe non-orienté.](figs/ex_graphe_oriente.svg)
![Un graphe orienté.](figs/ex_graphe_oriente.svg)




::::
::::
@@ -404,7 +404,7 @@ avec $k$ la longueur de la chaîne (le nombre d'arêtes du chemin).


## Définition
## Définition


* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\leq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes.
* Un **cycle** dans un graphe *non-orienté* est une chaîne de longueur $\geq 3$ telle que le 1er sommet de la chaîne est le même que le dernier, et dont les arêtes sont distinctes.
* Pour un graphe *orienté* on parle de **circuit**.
* Pour un graphe *orienté* on parle de **circuit**.
* Un graphe sans cycles est dit **acyclique**.
* Un graphe sans cycles est dit **acyclique**.


@@ -712,8 +712,8 @@ $$
\mathcal{O}(|E|)
\mathcal{O}(|E|)
$$
$$


* Pour les graphes *non-orientés*: $\mathcal{O}2|E|$.
* Pour les graphes *non-orientés*: $\mathcal{O}(2|E|)$.
* Pour les graphes *orientés*: $\mathcal{O}|E|$.
* Pour les graphes *orientés*: $\mathcal{O}(|E|)$.


## Définition
## Définition


+709 −0

File added.

Preview size limit exceeded, changes collapsed.

+1077 −0

File added.

Preview size limit exceeded, changes collapsed.

slides_2022/cours_3.md

0 → 100644
+339 −0

File added.

Preview size limit exceeded, changes collapsed.

slides_2022/cours_4.md

0 → 100644
+851 −0

File added.

Preview size limit exceeded, changes collapsed.

slides_2022/cours_5.md

0 → 100644
+834 −0

File added.

Preview size limit exceeded, changes collapsed.

slides_2022/cours_6.md

0 → 100644
+488 −0

File added.

Preview size limit exceeded, changes collapsed.

slides_2022/cours_7.md

0 → 100644
+295 −0

File added.

Preview size limit exceeded, changes collapsed.

+0 −0

File moved.

+0 −0

File moved.

+10 −0
Original line number Original line Diff line number Diff line
version: "3.3"
services:
    slides:
        image:  omalaspinas/pandoc:latest
        user: 1000:1000
        container_name: slides
        volumes:
            - ./:/data
        entrypoint: ["make"]
        working_dir: /data