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
  • added_codes
2 results

Target

Select target project
No results found
Select Git revision
  • master
1 result
Show changes
1000 files
+ 189096
1792
Compare changes
  • Side-by-side
  • Inline

Files

+5 −0
Original line number Diff line number Diff line
*.o
*.xopp*
slides/package-lock.json
slides/package.json
slides/.vscode/settings.json
.vscode/settings.json
slides/node_modules/.package-lock.json

README.md

0 → 100644
+17 −0
Original line number Diff line number Diff line
# Remerciements et contributions

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

* P. Albuquerque
* 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
+470 −0
Original line number Diff line number Diff line
@charset "UTF-8";

/* Import ET Book styles
   adapted from https://github.com/edwardtufte/et-book/blob/gh-pages/et-book.css */

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot");
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.woff") format("woff"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.ttf") format("truetype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot");
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.woff") format("woff"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.ttf") format("truetype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot");
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.woff") format("woff"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.ttf") format("truetype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.svg#etbookromanosf") format("svg");
    font-weight: bold;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book-roman-old-style";
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot");
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.woff") format("woff"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.ttf") format("truetype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

/* Tufte CSS styles */
html {
    font-size: 15px;
}

body {
    width: 87.5%;
    margin-left: auto;
    margin-right: auto;
    padding-left: 12.5%;
    font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
    background-color: #fffff8;
    color: #111;
    max-width: 1400px;
    counter-reset: sidenote-counter;
}

h1 {
    font-weight: 400;
    margin-top: 4rem;
    margin-bottom: 1.5rem;
    font-size: 3.2rem;
    line-height: 1;
}

h2 {
    font-style: italic;
    font-weight: 400;
    margin-top: 2.1rem;
    margin-bottom: 1.4rem;
    font-size: 2.2rem;
    line-height: 1;
}

h3 {
    font-style: italic;
    font-weight: 400;
    font-size: 1.7rem;
    margin-top: 2rem;
    margin-bottom: 1.4rem;
    line-height: 1;
}

hr {
    display: block;
    height: 1px;
    width: 55%;
    border: 0;
    border-top: 1px solid #ccc;
    margin: 1em 0;
    padding: 0;
}

p.subtitle {
    font-style: italic;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-size: 1.8rem;
    display: block;
    line-height: 1;
}

.numeral {
    font-family: et-book-roman-old-style;
}

.danger {
    color: red;
}

article {
    padding: 5rem 0rem;
}

section {
    padding-top: 1rem;
    padding-bottom: 1rem;
}

p,
dl,
ol,
ul {
    font-size: 1.4rem;
    line-height: 2rem;
}

p {
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    padding-right: 0;
    vertical-align: baseline;
}

/* Chapter Epigraphs */
div.epigraph {
    margin: 5em 0;
}

div.epigraph > blockquote {
    margin-top: 3em;
    margin-bottom: 3em;
}

div.epigraph > blockquote,
div.epigraph > blockquote > p {
    font-style: italic;
}

div.epigraph > blockquote > footer {
    font-style: normal;
}

div.epigraph > blockquote > footer > cite {
    font-style: italic;
}
/* end chapter epigraphs styles */

blockquote {
    font-size: 1.4rem;
}

blockquote p {
    width: 55%;
    margin-right: 40px;
}

blockquote footer {
    width: 55%;
    font-size: 1.1rem;
    text-align: right;
}

section > p,
section > footer,
section > table {
    width: 55%;
}

/* 50 + 5 == 55, to be the same width as paragraph */
section > dl,
section > ol,
section > ul {
    width: 50%;
    -webkit-padding-start: 5%;
}

dt:not(:first-child),
li:not(:first-child) {
    margin-top: 0.25rem;
}

figure {
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
    max-width: 55%;
    -webkit-margin-start: 0;
    -webkit-margin-end: 0;
    margin: 0 0 3em 0;
}

figcaption {
    float: right;
    clear: right;
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.6;
    vertical-align: baseline;
    position: relative;
    max-width: 40%;
}

figure.fullwidth figcaption {
    margin-right: 24%;
}

/* Links: replicate underline that clears descenders */
a:link,
a:visited {
    color: inherit;
}

.no-tufte-underline:link {
    background: unset;
    text-shadow: unset;
}

a:link, .tufte-underline, .hover-tufte-underline:hover {
    text-decoration: none;
    background: -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(currentColor, currentColor);
    background: linear-gradient(#fffff8, #fffff8), linear-gradient(#fffff8, #fffff8), linear-gradient(currentColor, currentColor);
    -webkit-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    -moz-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-repeat: no-repeat, no-repeat, repeat-x;
    text-shadow: 0.03em 0 #fffff8, -0.03em 0 #fffff8, 0 0.03em #fffff8, 0 -0.03em #fffff8, 0.06em 0 #fffff8, -0.06em 0 #fffff8, 0.09em 0 #fffff8, -0.09em 0 #fffff8, 0.12em 0 #fffff8, -0.12em 0 #fffff8, 0.15em 0 #fffff8, -0.15em 0 #fffff8;
    background-position: 0% 93%, 100% 93%, 0% 93%;
}

@media screen and (-webkit-min-device-pixel-ratio: 0) {
    a:link, .tufte-underline, .hover-tufte-underline:hover {
        background-position-y: 87%, 87%, 87%;
    }
}

a:link::selection,
a:link::-moz-selection {
    text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
    background: #b4d5fe;
}

/* Sidenotes, margin notes, figures, captions */
img {
    max-width: 100%;
}

.sidenote,
.marginnote {
    float: right;
    clear: right;
    margin-right: -60%;
    width: 50%;
    margin-top: 0.3rem;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.3;
    vertical-align: baseline;
    position: relative;
}

.sidenote-number {
    counter-increment: sidenote-counter;
}

.sidenote-number:after,
.sidenote:before {
    font-family: et-book-roman-old-style;
    position: relative;
    vertical-align: baseline;
}

.sidenote-number:after {
    content: counter(sidenote-counter);
    font-size: 1rem;
    top: -0.5rem;
    left: 0.1rem;
}

.sidenote:before {
    content: counter(sidenote-counter) " ";
    font-size: 1rem;
    top: -0.5rem;
}

blockquote .sidenote,
blockquote .marginnote {
    margin-right: -82%;
    min-width: 59%;
    text-align: left;
}

div.fullwidth,
table.fullwidth {
    width: 100%;
}

div.table-wrapper {
    overflow-x: auto;
    font-family: "Trebuchet MS", "Gill Sans", "Gill Sans MT", sans-serif;
}

.sans {
    font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
    letter-spacing: .03em;
}

code, pre > code {
    font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
    font-size: 1.0rem;
    line-height: 1.42;
    -webkit-text-size-adjust: 100%; /* Prevent adjustments of font size after orientation changes in iOS. See https://github.com/edwardtufte/tufte-css/issues/81#issuecomment-261953409 */
}

.sans > code {
    font-size: 1.2rem;
}

h1 > code,
h2 > code,
h3 > code {
    font-size: 0.80em;
}

.marginnote > code,
.sidenote > code {
    font-size: 1rem;
}

pre > code {
    font-size: 0.9rem;
    width: 52.5%;
    margin-left: 2.5%;
    overflow-x: auto;
    display: block;
}

pre.fullwidth > code {
    width: 90%;
}

.fullwidth {
    max-width: 90%;
    clear:both;
}

span.newthought {
    font-variant: small-caps;
    font-size: 1.2em;
}

input.margin-toggle {
    display: none;
}

label.sidenote-number {
    display: inline;
}

label.margin-toggle:not(.sidenote-number) {
    display: none;
}

.iframe-wrapper {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    padding-top: 25px;
    height: 0;
}

.iframe-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

@media (max-width: 760px) {
    body {
        width: 84%;
        padding-left: 8%;
        padding-right: 8%;
    }

    hr,
    section > p,
    section > footer,
    section > table {
        width: 100%;
    }

    pre > code {
        width: 97%;
    }

    section > dl,
    section > ol,
    section > ul {
        width: 90%;
    }

    figure {
        max-width: 90%;
    }

    figcaption,
    figure.fullwidth figcaption {
        margin-right: 0%;
        max-width: none;
    }

    blockquote {
        margin-left: 1.5em;
        margin-right: 0em;
    }

    blockquote p,
    blockquote footer {
        width: 100%;
    }

    label.margin-toggle:not(.sidenote-number) {
        display: inline;
    }

    .sidenote,
    .marginnote {
        display: none;
    }

    .margin-toggle:checked + .sidenote,
    .margin-toggle:checked + .marginnote {
        display: block;
        float: left;
        left: 1rem;
        clear: both;
        width: 95%;
        margin: 1rem 2.5%;
        vertical-align: baseline;
        position: relative;
    }

    label {
        cursor: pointer;
    }

    div.table-wrapper,
    table {
        width: 85%;
    }

    img {
        width: 100%;
    }
}
Original line number Diff line number Diff line
*.pdf
*.json
*.err
*.markdown
*.html
index.md
.puppeteer.json
+14 −22
Original line number Diff line number Diff line
@@ -8,46 +8,37 @@ PDFOPTIONS += -V themeoptions:numbering=none -V themeoptions:progressbar=foot
PDFOPTIONS += -V fontsize=smaller
PDFOPTIONS += -V urlcolor=blue

REVEALOPTIONS = -t revealjs
REVEALOPTIONS += -F mermaid-filter
REVEALOPTIONS += --self-contained
REVEALOPTIONS += -V revealjs-url=reveal.js
REVEALOPTIONS += -V theme=white
REVEALOPTIONS += -V width=1920
REVEALOPTIONS += -V margin=0
REVEALOPTIONS += --slide-level=1

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) $(HTML) # La cible par défaut (all) exécute les cibles %.pdf
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 make puppeteer -k || true
	docker-compose run slides make all -k || true
	docker compose run slides

docker_clean: docker-compose.yml
	docker-compose run slides make clean -k || true
	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)

index:
	rm -f index.md
	./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 $@ $^

%.html: %.md metadata.yaml
	pandoc -s $(OPTIONS) $(REVEALOPTIONS) -o $@ $^

%.markdown: %.md metadata.yaml yq
	sed '1 { /^---/ { :a N; /\n---/! ba; d} }' $< > no_header
	grep -v -F -x -f  no_header $< > header.yaml
@@ -60,11 +51,12 @@ 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 
deploy: all index.html
	mkdir -p algo_cours
	cp *.pdf algo_cours
	cp index.html algo_cours

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

.PHONY:	clean index puppeteer yq
.PHONY:	clean index.md puppeteer yq
+19 −363
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2021-09-22"
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;
@@ -57,14 +57,12 @@ Nombre premier: nombre possédant deux diviseurs entiers distincts.
## Algorithme naïf (problème)

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

. . .
@@ -80,14 +78,12 @@ est_premier(nombre) {
## Algorithme naïf (une solution)

```C
est_premier(nombre) { // fonction
    soit i := 2;       // variable, type, assignation
    tant que i < nombre { // boucle
        si nombre modulo i = 0 { // expression typée
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
    }
        i = i + 1
    retourne vrai // expression typée
```

@@ -103,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;
}
@@ -125,9 +121,9 @@ 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 -fsanitize=address 
    -fsanitize=leak -fsanitize=undefined
    ```console
    $ gcc -O1 -std=c11 -Wall -Wextra -g prog.c -o prog 
    	-fsanitize=address 
    ```
    1. `-std=c11` utilisation de C11.
    2. `-Wall et -Wextra` activation des warnings.
@@ -244,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)

@@ -292,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
@@ -336,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
@@ -351,343 +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");
}
```

# 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

. . .

```C
int factorielle(int n) {
    i = 1;
    fact = 1;
    pour i <= n {
        fact *= i;
        i += 1;
    }
}
```

# 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++;
   }
}
```

. . .

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


# Entrées/sorties: `printf()`{.C} (1/2)

## Généralités

- La fonction `printf()`{.C} permet d'afficher du texte sur le terminal:

    ```C
    int printf(const char *format, ...);
    ```
- Nombre d'arguments variables.
- `format`{.C} est le texte, ainsi que le format (type) des variables à afficher.
- Les arguments suivants sont les expressions à afficher.

# Entrées/sorties: `printf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Hello world.\n");
    int val = 1;
    printf("Hello world %d time.\n", val);
    printf("%f squared is equal to %f.\n", 2.5, 2.5*2.5);
    return EXIT_SUCCESS;
}
```

# Entrées/sorties: `scanf()`{.C} (1/2)

## Généralités

- La fonction `scanf()`{.C} permet de lire du texte formaté entré au clavier:

    ```C
    int scanf(const char *format, ...);
    ```

- `format`{.C} est le format des variables à lire (comme `printf()`{.C}).
- Les arguments suivants sont les variables où sont stockées les valeurs lues.

# Entrées/sorties: `scanf()`{.C} (2/2)

## Exemple

```C
#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("Enter 3 numbers: \n");
    int i, j, k;
    scanf("%d %d %d", &i, &j, &k);
    printf("You entered: %d %d %d\n", i, j, k);
    
    return EXIT_SUCCESS;
}
```

# Exercice: la factorielle en mieux

## Individuellement

1. Ajoutez des fonctionnalités à votre code.
2. Écrivez l'algorithme de calcul de deux façon différentes.
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!

+302 −159
Original line number Diff line number Diff line
---
title: "Introduction aux algorithmes"
date: "2021-09-29"
title: "Introduction aux algorithmes II"
date: "2025-09-23"
---

# Rappel

* 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;
}
```

# 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=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");
}
```


# 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 la dernière fois:
## 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?
@@ -159,12 +457,6 @@ Par groupe de 3 (5-10min):
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`.

<!-- Si un nombre, $p$, est multiple de $a$ et de $b$ alors il peut s'écrire -->
<!-- $$ -->
<!-- p = a \cdot i = b \cdot j, -->
<!-- $$ -->
<!-- ou encore $p / a = i$ et $p / b = j$. -->

. . .

## Pseudo-code
@@ -172,7 +464,7 @@ Si un nombre, `p`, est multiple de `a` et de `b` alors il peut s'écrire `p = a
```C
int ppcm(int a, int b) {
    for (i in [1, b]) {
        if a * i is divisible by b {
        if a * i est divisible par b {
            return a * i
        }
    }
@@ -191,7 +483,6 @@ int ppcm(int a, int b) {
```C
#include <stdio.h>
#include <stdlib.h> 

int main() { 
   int n = 15, m = 12;
   int i = 1;
@@ -209,7 +500,6 @@ int main() {
```C
#include <stdio.h>
#include <stdlib.h> 

int main() { 
   int res = n*m;
   for (int i = 2; i <= m; i++) {
@@ -222,153 +512,6 @@ int main() {
}
```

# Le calcul du PGCD (1/5)

## Définition

Le plus grand commun diviseur (PGCD) de deux nombres entiers non nuls est le
plus grand entier qui les divise en même temps. 

## Exemples:

```C
PGCD(3, 4) = 1,
PGCD(4, 6) = 2,
PGCD(5, 15) = 5.
```

. . .

## 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 basse
$$
PGCD(36, 90)=2^{\min{1,2}}\cdot 3^{\min{2,2}}\cdot 5^{\min{0,1}}=18.
$$

# Le calcul du PGCD (2/5)

## Algorithme

Par groupe de 3 (5-10min):

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

. . .

## Exemple d'algorithme

```C
PGCD(36, 90):
90 % 36 != 0 // otherwise 36 would be PGCD
90 % 35 != 0 // otherwise 35 would be PGCD
90 % 34 != 0 // otherwise 34 would be PGCD
...
90 % 19 != 0 // otherwise 19 would be PGCD
90 % 18 == 0 // The end!
```

* 18 modulos, 18 assignations, et 18 comparaisons.

# Le calcul du PGCD (3/5)

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

. . .

## Optimisation

* Combien d'additions / comparaisons au pire?
* Un moyen de le rendre plus efficace?

. . .

## Tentative de correction

```C
void main() {
   int n = 90, m = 78;
   int gcd = 1;
   for (int div = n; div >= 2; div--) { // div = m, sqrt(n)
      if (n % div == 0 && m % div == 0) {
         gcd = div;
         break;
      }
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, gcd);
}
```

# Le calcul du PGCD (4/5)

## Réusinage: l'algorithme d'Euclide

`Dividende = Diviseur * Quotient + Reste`

```C
PGCD(35, 60):
35 = 60 * 0 + 35 // 60 -> 35, 35 -> 60
60 = 35 * 1 + 25 // 35 -> 60, 25 -> 35
35 = 25 * 1 + 10 // 25 -> 35, 20 -> 25
25 = 10 * 2 +  5 // 10 -> 25, 5  -> 10
10 =  5 * 2 +  0 // PGCD = 5!
```

. . .

## Algorithme

Par groupe de 3 (5-10min):

* analysez l'exemple ci-dessus;
* transcrivez le en pseudo-code.

# Le calcul du PGCD (5/5)

## Pseudo-code

```C
int pgcd(int a, int b) {
    tmp_n = n
    tmp_m = m
    while (tmp_m does not divide tmp_n) {
        tmp   = tmp_n
        tmp_n = tmp_m
        tmp_m = tmp modulo tmp_m
    }
    return tmp_m
}
```

# Le code du PGCD de 2 nombres

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

. . .

## Un corrigé possible

```C
#include <stdio.h>
void main() {
   int n = 90;
   int m = 78;
   printf("n = %d et m = %d\n", n, m);
   int tmp_n = n;
   int tmp_m = m;
   while (tmp_n%tmp_m > 0) {
      int tmp = tmp_n;
      tmp_n = tmp_m;
      tmp_m = tmp % tmp_m;
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, tmp_m);
}
```

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

# Quelques algorithmes simples
# Rappel (1/2)

## Quelques algorithmes supplémentaires
## Quels algos avons-nous vu la semaine passée?

* Remplissage d'un tableau et recherche de la valeur minimal
* Anagrammes
* Palindromes
* Crible d'ératosthène
. . .

# Collections: tableaux statiques
* L'algorithme de la factorielle.
* L'algorithme du PPCM.

* Objets de même type: leur nombre est **connu à la compilation**;
* Stockés contigüement en mémoire (très efficace);
# Rappel (2/2)

    ```C
    #define SIZE 10
    int entiers[] = {2, 1, 4, 5, 7}; // taille 5, initialisé
    int tab[3]; // taille 3, non initialisé
    float many_floats[SIZE]; // taille 10, non initialisé
    ```
* Les indices sont numérotés de `0` à `taille-1`;
## Algorithme du PPCM?

    ```C
    int premier = entier[0]; // premier = 2
    int dernier = entier[4]; // dernier = 7
    ```
* Les tableaux sont **non-initialisés** par défaut;
* Les bornes ne sont **jamais** vérifiées.
. . .

```C
    int indetermine_1 = tab[1];     // undefined behavior
    int indetermine_2 = entiers[5]; // UB
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);
}
```

# Remarques

* Depuis  `C99` possibilité d'avoir des tableaux dont la taille est *inconnue à
  la compilation*;
# Le calcul du PPCM (1/2)

    ```C
    int size;
    scanf("%d", &size);
    char string[size];
    ```
## Réusinage: Comment décrire une fonction qui ferait ce calcul (arguments, sorties)?

. . .

* 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
  cas-là (spoiler du futur du cours).

# Initialisation

* Les variables ne sont **jamais** initialisées en `C` par défaut.
* Question: Que contient le tableau suivant?
En `C` on pourrait la décrire comme

```C
    double tab[4];
int ppcm(int a, int b); // La **signature** de cette fonction
```

. . .

* Réponse: On en sait absolument rien!
* Comment initialiser un tableau?
## Algorithme

. . .
Par groupe de 3 (5-10min):

```C
#define SIZE 10
double tab[SIZE];
for (int i = 0; i < SIZE; ++i) {
    tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0; 
    // tab[i] contient un double dans [-5;5]
}
```
* réfléchissez à un algorithme alternatif donnant le PPCM de deux nombres;
* écrivez l'algorithme en pseudo-code.

# Recherche du minimum dans un tableau (1/2)
. . .

## Problématique
* 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`.

Trouver la valeur minimale contenue dans un tableau et l'indice de l'élément le plus petit.

## Écrire un pseudo-code résolvant ce problème (groupe de 3), 2min
# Le calcul du PPCM (2/2)

. . .

## Pseudo-code

```C
index = 0
min   = tab[0]
for i in [1; SIZE] {
    if min > tab[i] {
        min = tab[i]
        index = i
int ppcm(int a, int b) {
    for (i in [1, b]) {
        if a * i est divisible par b {
            return a * i
        }
    }
}
```

# Recherche du minimum dans un tableau (2/2)
# Le code du PPCM de 2 nombres (1/2)

## Implémenter ce bout de code en C (groupe de 3), 4min
## Implémentez le pseudo-code et postez le code sur matrix (5min).

. . .

## Un corrigé possible


```C
int index = 0;
float min = tab[0];
for (int i = 1; i < SIZE; ++i) {
    if min > tab[i] {
        min = tab[i];
        index = i;
#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);
}
```

# Tri par sélection (1/2)

## Problématique

Trier un tableau par ordre croissant.
# Le code du PPCM de 2 nombres (2/2)

## Idée d'algorithme
## Corrigé alternatif

```C
ind = 0
boucle (ind < SIZE-1) {
    Trouver le minimum du tableau, tab_min[ind:SIZE].
    Échanger tab_min avec tab[ind]
    ind += 1
#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);
}
```

# 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é.

# Un type de tableau particulier

## Les chaînes de caractères
# Le calcul du PGCD (1/5)

```C
string = tableau + char + magie noire
```
## Définition

# Le type `char`{.C}
Le plus grand commun diviseur (PGCD) de deux nombres entiers non nuls est le
plus grand entier qui les divise en même temps. 

- Le type `char`{.C} est utilisé pour représenter un caractère.
- C'est un entier 8 bits signé.
- En particulier:
    - Écrire
## Exemples:

```C
        char c = 'A';
PGCD(3, 4) = 1,
PGCD(4, 6) = 2,
PGCD(5, 15) = 5.
```
    - Est équivalent à:

        ```C
        char c = 65;
        ```
- Les fonctions d'affichage interprètent le nombre comme sa valeur ASCII.
. . .

# Chaînes de caractères (strings)
## Mathématiquement

- Chaîne de caractère `==` tableau de caractères **terminé par la valeur** `'\0'`{.C} ou `0`{.C}.
Décomposition en nombres premiers:

## Exemple
$$
36 = 2^2\cdot 3^2,\quad 90=2\cdot 5\cdot 3^2,
$$
On garde tous les premiers à la puissance la plus basse
$$
PGCD(36, 90)=2^{\min{1,2}}\cdot 3^{\min{2,2}}\cdot 5^{\min{0,1}}=18.
$$

# Le calcul du PGCD (2/5)

## Algorithme

Par groupe de 3 (5-10min):

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

. . .

## Exemple d'algorithme

```C
char *str  = "HELLO !";
char str[] = "HELLO !";
PGCD(36, 90):
90 % 36 != 0 // otherwise 36 would be PGCD
90 % 35 != 0 // otherwise 35 would be PGCD
90 % 34 != 0 // otherwise 34 would be PGCD
...
90 % 19 != 0 // otherwise 19 would be PGCD
90 % 18 == 0 // The end!
```

Est représenté par
* 18 modulos, 18 assignations, et 18 comparaisons.

| `char`  | `H`  | `E`  | `L`  | `L`  | `O`  |      | `!`  | `\0`|
|---------|------|------|------|------|------|------|------|-----|
| `ASCII` | `72` | `69` | `76` | `76` | `79` | `32` | `33` | `0` |
# Le calcul du PGCD (3/5)

. . .
\footnotesize

## A quoi sert le `\0`?
## Transcrivez cet exemple en algorithme et codez-le (5-10min)!

. . .

Permet de connaître la fin de la chaîne de caractères (pas le cas des autres
sortes de tableaux).
## Optimisation

# Syntaxe
* Combien d'additions / comparaisons au pire?
* Un moyen de le rendre plus efficace?

. . .

## Tentative de correction

```C
char name[5];
name[0] = 'P';  // = 70;
name[1] = 'a';  // = 97;
name[2] = 'u';  // = 117;
name[3] = 'l';  // = 108;
name[4] = '\0'; // = 0;
char name[] = {'P', 'a', 'u', 'l', '\0'};
char name[5] = "Paul";
char name[] = "Paul";
char name[100] = "Paul is not 100 characters long.";
void main() {
   int n = 90, m = 78;
   int gcd = 1;
   for (int div = n; div >= 2; div--) { // div = m, sqrt(n)
      if (n % div == 0 && m % div == 0) {
         gcd = div;
         break;
      }
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, gcd);
}
```

# Fonctions
# Le calcul du PGCD (4/5)

## Réusinage: l'algorithme d'Euclide

- Il existe une grande quantités de fonction pour la manipulation de chaînes de caractères dans `string.h`.
- Fonctions principales:
`Dividende = Diviseur * Quotient + Reste`

```C
    // longueur de la chaîne (sans le \0)
    size_t strlen(char *str);
    // copie jusqu'à un \0
    char *strcpy(char *dest, const char *src);
     // copie len char
    char *strncpy(char *dest, const char *src, size_t len);
    // compare len chars
    int strncmp(char *str1, char *str2, size_t len);
    // compare jusqu'à un \0
    int strcmp(char *str1, char *str2);
PGCD(35, 60):
35 = 60 * 0 + 35 // 60 -> 35, 35 -> 60
60 = 35 * 1 + 25 // 35 -> 60, 25 -> 35
35 = 25 * 1 + 10 // 25 -> 35, 20 -> 25
25 = 10 * 2 +  5 // 10 -> 25, 5  -> 10
10 =  5 * 2 +  0 // PGCD = 5!
```

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

. . .

## Quels problèmes peuvent se produire avec `strlen`, `strcpy`, `strcmp`?
## Algorithme

# Les anagrammes
Par groupe de 3 (5-10min):

## Définition

Deux mots sont des anagrammes l'un de l'autre quand ils contiennent les mêmes 
lettres mais dans un ordre différent.
* analysez l'exemple ci-dessus;
* transcrivez le en pseudo-code.

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

| `t`  | `u`  | `t`  | `u`  | `t`  | `\0` | ` `  | ` ` |
|------|------|------|------|------|------|------|-----|
| `t`  | `u`  | `t`  | `t`  | `u`  | `\0` | ` `  | ` ` |
## Pseudo-code

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

## Problème: Trouvez un algorithme pour déterminer si deux mots sont des anagrammes.
```

# Les anagrammes
# Le code du PGCD de 2 nombres

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

1. Trier les deux mots.
2. Vérifier s'ils contiennent les mêmes lettres.
. . .

## Implémentation en live (offerte par HepiaVPN)
## Un corrigé possible

```C
int main() { // pseudo C
    tri(mot1);
    tri(mot2);
    if egalite(mot1, mot2) {
        // anagrammes
    } else {
        // pas anagrammes
#include <stdio.h>
void main() {
   int n = 90;
   int m = 78;
   printf("n = %d et m = %d\n", n, m);
   int tmp_n = n;
   int tmp_m = m;
   while (tmp_n%tmp_m > 0) {
      int tmp = tmp_n;
      tmp_n = tmp_m;
      tmp_m = tmp % tmp_m;
   }
   printf("Le pgcd de %d et %d est %d\n", n, m, tmp_m);
}
```

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

# Les palindromes
# Quelques algorithmes simples

Mot qui se lit pareil de droite à gauche que de gauche à droite:
* Stockage d'une liste de nombre et recherche de la valeur minimale
* Anagrammes
* Palindromes
* Crible d’Ératosthène

. . .

* rotor, kayak, ressasser, ...
* Ces algorithme nécessitent d'utiliser des **tableaux**.

# Collections: tableaux statiques

\footnotesize

## Problème: proposer un algorithme pour détecter un palindrome
* Objets de même type: leur nombre est **connu à la compilation**
* Stockés de façon contiguë en mémoire (très efficace)

    ```C
    #define SIZE 10
    int entiers[] = {2, 1, 4, 5, 7}; // taille 5, initialisé
    int tab[3]; // taille 3, non initialisé
    float many_floats[SIZE]; // taille 10, non initialisé
    ```
* Les indices sont numérotés de `0` à `taille-1`;

    ```C
    int premier = entier[0]; // premier = 2
    int dernier = entier[4]; // dernier = 7
    ```
* Les tableaux sont **non-initialisés** par défaut;
* Les bornes ne sont **jamais** vérifiées.

    ```C
    int indetermine_1 = tab[1];     // undefined behavior
    int indetermine_2 = entiers[5]; // UB
    ```

# Remarques

* Depuis  `C99` la taille peut être *inconnue à la compilation* (VLA);

    ```C
    int size;
    scanf("%d", &size);
    char string[size];
    ```

 . . .

## Solution 1
* 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 cas-là (spoiler du futur du cours).

# Initialisation

* Les variables ne sont **jamais** initialisées en `C` par défaut.
* Question: Que contient le tableau suivant?

    ```C
while (first_index < last_index {
    if (mot[first_index] != mot [last_index]) {
        return false;
    }
    first_index += 1;
    last_index -= 1;
}
return true;
    double tab[4];
    ```

. . .

## Solution 2
* Réponse: On en sait absolument rien!
* Comment initialiser un tableau?

. . .

```C
mot_tmp = revert(mot);
return mot == mot_tmp;
#define SIZE 10
double tab[SIZE];
for (int i = 0; i < SIZE; ++i) {
    tab[i] = rand() / (double)RAND_MAX * 10.0 - 5.0; 
    // tab[i] contient un double dans [-5;5]
}
int other_tab[4] = {0}; // pareil que {0, 0, 0, 0}
```

# Crible d'Ératosthène
# Recherche du minimum dans un tableau (1/2)

## Problématique

Algorithme de génération de nombres premiers.
Trouver la valeur minimale contenue dans un tableau et l'indice de l'élément le plus petit.

## Exercice
## Écrire un pseudo-code résolvant ce problème (groupe de 3), 2min

* À l'aide d'un tableau de booléens,
* Générer les nombres premiers plus petits qu'un nombre $N$
. . .

## Pseudo-code
```C
index = 0
min   = tab[0]
pour i de 1 à SIZE - 1
    si min > tab[i]
        min = tab[i]
        index = i
```

* Par groupe de trois, réfléchir à un algorithme.
# Recherche du minimum dans un tableau (2/2)

## Programme en C
## Implémenter ce bout de code en C (groupe de 3), 4min

* Implémenter l'algorithme et le poster sur le salon `Element`.
. . .

```C
int index = 0;
float min = tab[0];
for (int i = 1; i < SIZE; ++i) {
    if (min > tab[i]) {
        min = tab[i];
        index = i;
    }
}
```