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
  • main
1 result

Target

Select target project
No results found
Select Git revision
  • master
1 result
Show changes
688 files
+ 119589
435
Compare changes
  • Side-by-side
  • Inline

Files

+11 −7
Original line number Diff line number Diff line
# 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
* O. Malaspinas
* A. Escribano
* J. Bach
* A. Boyer
* M. Corboz
* M. Divià
* Y. El Hakouni
* A. Escribano
* P. Kunzli
* G. Legouic
* G. Marino Jarrin
* H. Radhwan
* I. Saroukhanian
* C. Volta
Original line number Diff line number Diff line
*.pdf
*.json
*.err
*.markdown
*.html
index.md
.puppeteer.json
+3 −2
Original line number 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

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

docker_clean: docker-compose.yml
	docker-compose run slides clean
	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
	# @echo "{\n\"executablePath\":" \"$(CHROMIUM)\" ",\n\"args\": [\"--no-sandbox\"]\n}" > .puppeteer.json

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

# 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;
* Structures de contrôle;
* Fonctions;
@@ -79,7 +79,7 @@ booléen est_premier(nombre)

```C
booléen est_premier(nombre) // fonction
    soit i = 2;       // variable, type, assignation
    soit i = 2       // variable, type, assignation
    tant que i < nombre // boucle
        si nombre modulo i == 0 // 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
            return false; // i n'est pas premier
        }
        i += 1; // sinon on incrémente i
        i = i + 1; // sinon on incrémente i
    }
    return true;
}
@@ -121,8 +121,8 @@ bool est_premier(int nombre) {

- Il existe une multitude d'options de compilation:

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

# 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)

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

# 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 -->
<!-- ```C
@@ -332,7 +332,7 @@ if (x) { /* vrai */ }

# 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 -->
<!-- ```C
@@ -347,212 +347,3 @@ bool d = 2.78; // 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 Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2022-09-28"
title: "Introduction aux algorithmes II"
date: "2025-09-23"
---

# Rappel (1/2)
# Rappel

* 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

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

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

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

* Espace de discussion [Matrix](https://matrix.to/#/!aKYVlcclmPGYXQFxAK:matrix.org?via=matrix.org), installez [element.io](https://element.io).
- Utilisez le libre service (l'horaire sera fixé prochainement).
- On va intensivement utiliser *Element*, installez le et utilisez le!
- Espace de discussion Matrix: <https://rb.gy/ku5es>, installez [element.io](https://element.io).

    ![](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:

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

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


# Organisation du module

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

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

Original line number Diff line number Diff line
---
subtitle: "Algorithmique et structures de données, 2022-2023"
author: "P. Albuquerque (B410), P. Künzli et O. Malaspinas (A401), ISC, HEPIA"
institute: En partie inspirés des supports de cours de P. Albuquerque
subtitle: "Algorithmique et structures de données, 2025-2026"
author: "P. Albuquerque (B410) et O. Malaspinas (A401), ISC, HEPIA"
institute: En partie inspiré des supports de cours de P. Albuquerque
lang: fr-CH
revealjs-url: /reveal.js
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 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
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2022-09-21"
---

# Qu'est-ce qu'un algorithme?

## Définition informelle (recette)

* des entrées (les ingrédients, le matériel utilisé) ;
* des instructions élémentaires simples (frire, flamber, etc.), dont les 
  exécutions dans un ordre précis amènent au résultat voulu ;
* un résultat : le plat préparé.

. . .

## Histoire et étymologie

- Existent depuis 4500 ans au moins (algorithme de division, crible 
  d'Eratosthène).
- Le mot algorithme est dérivé du nom du mathématicien perse
    *Muḥammad ibn Musā al-Khwārizmī*, qui a été "latinisé" comme 
    *Algoritmi*.

. . .

## Définition formelle

En partant d'un état initial et d'entrées (peut-être vides), une séquence finie 
d'instruction bien définies (ordonnées) implémentables sur un ordinateur, afin 
de résoudre typiquement une classe de problèmes ou effectuer un calcul.

# Notions de base d'algorithmique

## Variable

. . .

* Paire: identifiant - valeur (assignation);

## Séquence d'instructions / expressions

. . .

* Opérateurs (arthimétiques / booléens)
* Boucles;
* Structures de contrôle;
* Fonctions;


# Algorithme de vérification qu'un nombre est premier (1/3)

Nombre premier: nombre possédant deux diviseurs entiers distincts.

. . .

## Algorithme naïf (problème)

```C
booléen est_premier(nombre) 
    si 
        pour tout i, t.q. 1 < i < nombre 
            i ne divise pas nombre
    alors vrai
    sinon faux
```

. . .

## Pas vraiment un algorithme: pas une séquence ordonnée et bien définie

. . .

## Problème: Comment écrire ça sous une forme algorithmique?

# Algorithme de vérification qu'un nombre est premier (2/3)

## Algorithme naïf (une solution)

```C
booléen est_premier(nombre) // fonction
    soit i = 2;       // variable, type, assignation
    tant que i < nombre // boucle
        si nombre modulo i == 0 // expression typée
            retourne faux    // expression typée
        i = i + 1
    retourne vrai // expression typée
```

# Algorithme de vérification qu'un nombre est premier (3/3)

## Algorithme naïf (une solution en C)

```C
bool est_premier(int nombre) {
    int i; // i est un entier
    i = 2; // assignation i à 2
    while (i < nombre) { // boucle avec condition
        if (0 == nombre % i) { // is i divise nombre
            return false; // i n'est pas premier
        }
        i += 1; // sinon on incrémente i
    }
    return true;
}
```

. . .

## Exercice: Comment faire plus rapide?

# Génération d'un exécutable

- Pour pouvoir être exécuté un code C doit être d'abord compilé (avec `gcc` ou `clang`).
- Pour un code `prog.c` la compilation "minimale" est

    ```bash
    $ gcc prog.c
    $ ./a.out # exécutable par défaut
    ```

- Il existe une multitude d'options de compilation:

    ```bash
    $ gcc -O1 -std=c11 -Wall -Wextra -g porg.c -o prog 
    	-fsanitize=address 
    ```
    1. `-std=c11` utilisation de C11.
    2. `-Wall et -Wextra` activation des warnings.
    3. `-fsanitize=…`  contrôles d’erreurs à l’exécution (coût en performance).
    4. `-g` symboles de débogages sont gardés.
    5. `-o` défini le fichier exécutable à produire en sortie.
    6. `-O1`, `-O2`, `-O3`: activation de divers degrés d'optimisation



# La simplicité de C?

## 32 mots-clé et c'est tout

---------------- -------------- ---------------- ---------------
`auto`{.C}       `double`{.C}   `int`{.C}        `struct`{.C}   
`break`{.C}      `else`{.C}     `long`{.C}       `switch`{.C}   
`case`{.C}       `enum`{.C}     `register`{.C}   `typedef`{.C}  
`char`{.C}       `extern`{.C}   `return`{.C}     `union`{.C}    
`const`{.C}      `float`{.C}    `short`{.C}      `unsigned`{.C} 
`continue`{.C}   `for`{.C}      `signed`{.C}     `void`{.C}
`default`{.C}    `goto`{.C}     `sizeof`{.C}     `volatile`{.C}
`do`{.C}         `if`{.C}       `static`{.C}     `while`{.C}
---------------- -------------- ---------------- ---------------

# Déclaration et typage

En C lorsqu'on veut utiliser une variable (ou une constante), on doit déclarer son type

```C
const double two = 2.0; // déclaration et init.
int x;   // déclaration (instruction)
char c;  // déclaration (instruction)
x = 1;   // affectation (expression)
c = 'a'; // affectation (expression)
int y = x; // déclaration et initialisation en même temps
int a, b, c; // déclarations multiples
a = b = c = 1; // init. multiples
```

# Les variables (1/2)

## Variables et portée

- Une variable est un identifiant, qui peut être liée à une valeur (un expression).
- Une variable a une **portée** qui définit où elle est *visible* (où elle peut être accédée).
- La portée est **globale** ou **locale**.
- Une variable est **globale** est accessible à tout endroit d'un programme et doit être déclarée en dehors de toute fonction.
- Une variable est **locale** lorsqu'elle est déclarée dans un **bloc**, `{...}`{.C}.
- Une variable est dans la portée **après** avoir été déclarée.

# Les variables (2/2)

## Exemple 

```C
float max; // variable globale accessible partout
int foo() {
    // max est visible ici
    float a = max; // valide
    // par contre les varibles du main() ne sont pas visibles
}
int main() {
    // max est visible ici
    int x = 1; // x est locale à main
    {
        // x est visible ici, y pas encore
        // on peut par exemple pas faire x = y;
        int y = 2;
    } // y est détruite à la sortie du bloc
} // x est à la sortie de main

```

<!-- TODO: quiz, compile, compile pas -->
<!-- ```C
int main() {
    global = 1;
} // COMPILE PAS
```

```C
int main() {
    int global = 1;
    {
        printf("global = %d", global);
    }
} // COMPILE
```

```C
int local;

int main() {
    local = 1;
    {
        printf("local = %d", local);
    }
} // COMPILE
```

```C
#include <stdio.h>
int local = 0;

int main() {
    int local = -1;
    {
        int local = 1;
        printf("local = %d\n", local);
    }
} // COMPILE
``` -->

# Quiz: compile ou compile pas?

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

# Types de base (1/4)

## Numériques

Type                               Signification (**gcc pour x86-64**)            
---------------------------------- ---------------------------------------------
`char`{.C}, `unsigned char`{.C}    Entier signé/non-signé 8-bit
`short`{.C}, `unsigned short`{.C}  Entier signé/non-signé 16-bit
`int`{.C}, `unsigned int`{.C}      Entier signé/non-signé 32-bit
`long`{.C}, `unsigned long`{.C}    Entier signé/non-signé 64-bit
`float`{.C}                        Nombre à virgule flottante, simple précision
`double`{.C}                       Nombre à virgule flottante, double précision
---------------------------------- ---------------------------------------------

**La signification de `short`{.C}, `int`{.C}, ... dépend du compilateur et de l'architecture.**

# Types de base (2/4)

Voir `<stdint.h>` pour des représentations **portables**

Type                               Signification
---------------------------------- ---------------------------------------------
`int8_t`{.C}, `uint8_t`{.C}        Entier signé/non-signé 8-bit
`int16_t`{.C}, `uint16_t`{.C}      Entier signé/non-signé 16-bit
`int32_t`{.C}, `uint32_t`{.C}      Entier signé/non-signé 32-bit
`int64_t`{.C}, `uint64_t`{.C}      Entier signé/non-signé 64-bit
---------------------------------- ---------------------------------------------

. . .

## Prenez l'habitude d'utiliser ces types-là!

# Types de base (3/4)

## Booléens

- Le ANSI C n'offre pas de booléens.
- L'entier `0`{.C} signifie *faux*, tout le reste *vrai*.
- Depuis C99, la librairie `stdbool` met à disposition un type `bool`{.C}.
- En réalité c'est un entier:
  - $1 \Rightarrow$ `true`{.C}
  - $0 \Rightarrow$ `false`{.C}
- On peut les manipuler comme des entier (les sommer, les multiplier, ...).

# Quiz: booléens

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

<!-- TODO Quiz en ligne -->
<!-- ```C
if (42) { /* vrai */ }

int x = 100;
if (x == 4) { /* faux */ }
if (x) { /* vrai */ }

int x = 100;
while (x−−) { /* répète tant que x est différent de 0 */ }

if (0) { /* faux */ }
if (i = 4) { /* vrai */ }
if (i = 0) { /* faux */ }

#include <stdbool.h>

bool x = true;
if (x) { /* vrai */ }
``` -->

# Types de base (4/4)

## Conversions

- Les conversions se font de manière:
  - Explicite:
    ```C
    int a = (int)2.8;
    double b = (double)a;
    int c = (int)(2.8+0.5);
    ```
  - Implicite:
    ```C
    int a = 2.8; // warning, si activés, avec clang
    double b = a + 0.5;
    char c = b; // pas de warning...
    int d = 'c';
    ```

# Quiz: conversions

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

<!-- TODO Quiz en ligne -->
<!-- ```C
int a = (int)2.8; // 2

double b = 2.85;
int c = b + 0.5; // 3

int d = a + 0.5; // 2

bool d = 2.78; // 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");
}
```
Original line number 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
matrice arbre_à_matrice(arbre)
    matrice = creer_matrice(nb_lignes(arbre), nb_colonnes(arbre))
    pour li de 0 à nb_lignes(matrice)
        pour co de 0 à nb_colonnes(matrice)
            noeud = position(li, co, arbre)
            matrice[co][li] = noeud.info
    retourne arbre
    retourne matrice
```

. . .

slides_2022/cours_2.md

0 → 100644
+317 −0
Original line number 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);
}
```



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

# La dynamique des corps célestes
Original line number Diff line number Diff line
@@ -157,7 +157,7 @@ booléen est_feuille(page)

entier position(page, valeur)
    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
    retourne i

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

:::: 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

* 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**.
* Un graphe sans cycles est dit **acyclique**.

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

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

## Définition

Original line number Diff line number Diff line
---
title: "Graphes - Plus court chemin"
date: "2023-05-24"
date: "2023-06-02"
---

# Rappel du dernier cours
@@ -29,9 +29,10 @@ date: "2023-05-24"

```C
initialiser(graphe) // tous sommets sont non-visités
file = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
file = visiter(sommet, vide) // sommet est un sommet 
                             // du graphe
tant que !est_vide(file)
    v = défiler(file)
    v = defiler(file)
    file = visiter(v, file)

file visiter(sommet, file)
@@ -58,7 +59,7 @@ file visiter(sommet, file)

* Étape 1: $\mathcal{O}(|V|)$,
* Étape 2: $\mathcal{O}(2|E|)$,
* Total: $\mathcal{O}(|V| + |2|E|)$.
* Total: $\mathcal{O}(|V| + 2|E|)$.

# Exercice

@@ -102,7 +103,8 @@ graph LR;

```C
initialiser(graphe) // tous sommets sont non-visités
pile = visiter(sommet, vide) // sommet est un sommet du graphe au hasard
pile = visiter(sommet, vide) // sommet est un 
                             // sommet du graphe
tant que !est_vide(pile)
    v = dépiler(pile)
    pile = visiter(v, pile)
@@ -261,100 +263,11 @@ si distance(u,v) > distance(u,w) + distance(w,v)
    on passe par w plutôt qu'aller directement
```

# Algorithme de Dijkstra

## Idée générale

* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres.
* Tous les noeuds sont marqués non-visités.
* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud.
* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité).
* Continuer avec le noeud à la distance la plus faible.
* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie.
# Algorithme de Dijkstra (1 à 5)

# Algorithme de Dijkstra

## Pseudo-code (5min, matrix)

. . .

```C
tab dijkstra(graph, s, t)
    pour chaque v dans graphe
        distance[v] = infini
        q = ajouter(q, v)
    distance[s] = 0
    tant que non_vide(q)
        u = min(q, distance) // plus petite distance dans q
        si u == t
            retourne distance
        q = remove(q, u)
        // voisin de u encore dans q
        pour chaque v dans voisinage(u, q) 
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
    retourne distance
```

# Algorithme de Dijkstra

* Cet algorithme, nous donne le plus court chemin mais...
* ne nous donne pas le chemin!

## Comment modifier l'algorithme pour avoir le chemin?

. . .

* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu!
* On a besoin d'un tableau `précédent`.

## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix)

# Algorithme de Dijkstra

```C
tab, tab dijkstra(graph, s, t)
    pour chaque v dans graphe
        distance[v] = infini
        précédent[v] = indéfini
        q = ajouter(q, v)
    distance[s] = 0
    tant que non_vide(q)
        u = min(q, distance) // plus petite distance dans q
        si u == t
            retourne distance
        q = remove(q, u)
        // voisin de u encore dans q
        pour chaque v dans voisinage(u, q) 
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
                précédent[v] = u
    retourne distance, précédent
```

# Algorithme de Dijkstra

## Comment reconstruire un chemin ?

. . .

```C
pile parcours(précédent, s, t)
    sommets = vide
    u = t
    // on a atteint t ou on ne connait pas de chemin
    si u != s && précédent[u] != indéfini 
        tant que vrai 
            sommets = empiler(sommets, u)
            u = précédent[u]
            si u == s // la source est atteinte
                retourne sommets
    retourne sommets
```

# Algorithme de Dijkstra
* $D$ est le tableau des distances au sommet $1$: $D[7]$ est la distance de 1 à 7.
* Le chemin est pas forcément direct.
* $S$ est le tableau des sommets visités.

::: columns

@@ -374,7 +287,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)

::: columns

@@ -395,7 +308,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)

::: columns

@@ -416,7 +329,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)


::: columns
@@ -438,7 +351,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)

::: columns

@@ -459,7 +372,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)

::: columns

@@ -480,7 +393,7 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra
# Algorithme de Dijkstra (1 à 5)

::: columns

@@ -500,6 +413,106 @@ pile parcours(précédent, s, t)

:::

# Algorithme de Dijkstra

## Idée générale

* On assigne à chaque noeud une distance $0$ pour $s$, $\infty$ pour les autres.
* Tous les noeuds sont marqués non-visités.
* Depuis du noeud courant, on suit chaque arête du noeud vers un sommet non visité et on calcule le poids du chemin à chaque voisin et on met à jour sa distance si elle est plus petite que la distance du noeud.
* Quand tous les voisins du noeud courant ont été visités, le noeud est mis à visité (il ne sera plus jamais visité).
* Continuer avec le noeud à la distance la plus faible.
* L'algorithme est terminé losrque le noeud de destination est marqué comme visité, ou qu'on a plus de noeuds qu'on peut visiter et que leur distance est infinie.

# Algorithme de Dijkstra

## Pseudo-code (5min, matrix)

\footnotesize

. . .

```C
tab dijkstra(graph, s, t)
    pour chaque v dans graphe
        distance[v] = infini
        q = ajouter(q, v)
    distance[s] = 0
    tant que non_vide(q)
    // sélection de u t.q. la distance dans q est min
        u = min(q, distance)
        si u == t // on a atteint la cible
            retourne distance
        q = remove(q, u)
        // voisin de u encore dans q
        pour chaque v dans voisinage(u, q)
        // on met à jour la distance du voisin en passant par u 
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
    retourne distance
```

# Algorithme de Dijkstra

* Cet algorithme, nous donne le plus court chemin mais...
* ne nous donne pas le chemin!

## Comment modifier l'algorithme pour avoir le chemin?

. . .

* Pour chaque nouveau noeud à visiter, il suffit d'enregistrer d'où on est venu!
* On a besoin d'un tableau `precedent`.

## Modifier le pseudo-code ci-dessus pour ce faire (3min matrix)

# Algorithme de Dijkstra

\footnotesize

```C
tab, tab dijkstra(graph, s, t)
    pour chaque v dans graphe
        distance[v] = infini
        precedent[v] = indéfini
        q = ajouter(q, v)
    distance[s] = 0
    tant que non_vide(q)
    // sélection de u t.q. la distance dans q est min
        u = min(q, distance) 
        si u == t
            retourne distance
        q = remove(q, u)
        // voisin de u encore dans q
        pour chaque v dans voisinage(u, q) 
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
                precedent[v] = u
    retourne distance, precedent
```

# Algorithme de Dijkstra

## Comment reconstruire un chemin ?

. . .

```C
pile parcours(precedent, s, t)
    sommets = vide
    u = t
    // on a atteint t ou on ne connait pas de chemin
    si u != s && precedent[u] != indéfini 
        tant que vrai 
            sommets = empiler(sommets, u)
            u = precedent[u]
            si u == s // la source est atteinte
                retourne sommets
    retourne sommets
```

# Algorithme de Dijkstra amélioré

## On peut améliorer l'algorithme
@@ -525,11 +538,11 @@ pile parcours(précédent, s, t)
## Trois fonction principales

```C
booléen est_vide(élément) // triviale
élément enfiler(élément, data, priorité)
data défiler(élément)
rien modifier_priorité(élément, data, priotié)
nombre priorité(data) // utilitaire
booléen est_vide(element) // triviale
element enfiler(element, data, priorite)
data defiler(element)
rien changer_priorite(element, data, priorite)
nombre priorite(element) // utilitaire
```

## Pseudo-implémentation: structure (1min)
@@ -537,10 +550,10 @@ nombre priorité(data) // utilitaire
. . .

```C
struct élément
struct element
    data
    priorité
    élément suivant
    priorite
    element suivant
```

# Les files de priorité
@@ -550,61 +563,61 @@ struct élément
. . .

```C
élément enfiler(élément, data, priorité)
    n_élément = créer_élément(data, priorité)
    si est_vide(élément)
        retourne n_élément
    si priorité(d) > priorité(e.d)
        n_élément.suivant = élément
        retourne n_élément
element enfiler(element, data, priorite)
    n_element = creer_element(data, priorite)
    si est_vide(element)
        retourne n_element
    si priorite(n_element) > priorite(element)
        n_element.suivant = element
        retourne n_element
    sinon
        tmp = élément
        préc = élément
        tant que !est_vide(tmp) && priorité < tmp.priorité
            préc = tmp
        tmp = element
        prec = element
        tant que !est_vide(tmp) && priorite < priorite(tmp)
            prec = tmp
            tmp = tmp.suivant
        prev.suivant = n_élément
        n_élément.suivant = tmp
        retourne élément           
        prev.suivant = n_element
        n_element.suivant = tmp
        retourne element           
```

# Les files de priorité

## Pseudo-implémentation: défiler (2min)
## Pseudo-implémentation: defiler (2min)

. . .

```C
data, élément défiler(élément)
    si est_vide(élément)
data, element defiler(element)
    si est_vide(element)
        retourne AARGL!
    sinon
        tmp = élément.data
        n_élément = élément.suivant
        libérer(élément)
        retourne tmp, n_élément
        tmp = element.data
        n_element = element.suivant
        liberer(element)
        retourne tmp, n_element
```

# Algorithme de Dijkstra avec file de priorité min

```C
distance, précédent dijkstra(graphe, s, t):
distance, precedent dijkstra(graphe, s, t):
    distance[source] = 0
    fp = file_p_vide()
    pour v dans sommets(graphe)
        si v != s
            distance[v] = infini
            précédent[v] = indéfini
            precedent[v] = indéfini
        fp = enfiler(fp, v, distance[v])
    tant que !est_vide(fp)
        u, fp = défiler(fp)
        u, fp = defiler(fp)
        pour v dans voisinage de u
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
                précédent[v] = u
                fp = changer_priorité(fp, v, n_distance)
    retourne distance, précédent
                precedent[v] = u
                fp = changer_priorite(fp, v, n_distance)
    retourne distance, precedent
```

# Algorithme de Dijkstra avec file
@@ -620,13 +633,13 @@ O(V) si v != s
O(V)        fp = enfiler(fp, v, distance[v]) // notre impl est nulle
------------------O(V * V)-------------------------------
    tant que !est_vide(fp)
O(1)    u, fp = défiler(fp)
O(1)    u, fp = defiler(fp)
---------------------------------------------------------
O(E)    pour v dans voisinage de u
            n_distance = distance[u] + w(u, v)
            si n_distance < distance[v]
                distance[v] = n_distance
O(V)            fp = changer_priorité(fp, v, n_distance)
O(V)            fp = changer_priorite(fp, v, n_distance)
---------------------------------------------------------
    retourne distance
```
@@ -654,7 +667,7 @@ O(V) fp = changer_priorité(fp, v, n_distance)
## A chaque étape donner:

* Le tableau des distances à `a`;
* Le tableau des prédécessueurs;
* Le tableau des prédécesseurs;
* L'état de la file de priorité.

# Algorithme de Dijkstra (corrigé) 
+1077 −0

File added.

Preview size limit exceeded, changes collapsed.

+10 −0
Original line number 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