diff --git a/slides/cours_8.md b/slides/cours_8.md index f131bdf2e0e52aa711391e2dacab0c7e63e1441b..570d7c4e47487f204344ea247eb03a360e2f74d2 100644 --- a/slides/cours_8.md +++ b/slides/cours_8.md @@ -603,494 +603,3 @@ $$ $$ -# Tri à bulle (1/4) - -## Algorithme - -* Parcours du tableau et comparaison des éléments consécutifs: - - Si deux éléments consécutifs ne sont pas dans l'ordre, ils sont échangés. -* On recommence depuis le début du tableau jusqu'à avoir plus d'échanges à - faire. - -## Que peut-on dire sur le dernier élément du tableau après un parcours? - -. . . - -* Le plus grand élément est **à la fin** du tableau. - * Plus besoin de le traiter. -* A chaque parcours on s'arrête un élément plus tôt. - -# Tri à bulle (2/4) - -## Exemple - - - - -# Tri à bulle (3/4) - -## Exercice: écrire l'algorithme (poster le résultat sur matrix) - -. . . - -```C -rien tri_a_bulles(entier tableau[]) - pour i de longueur(tableau)-1 à 1: - trié = vrai - pour j de 0 à i-1: - si (tableau[j] > tableau[j+1]) - échanger(tableau[j], tableau[j+1]) - trié = faux - - si trié - retourner -``` - -# Tri à bulle (4/4) - -## Quelle est la complexité du tri à bulles? - -. . . - -* Dans le meilleurs des cas: - * Le tableau est déjà trié: $\mathcal{O}(N)$ comparaisons. -* Dans le pire des cas, $N\cdot (N-1)/2\sim\mathcal{O}(N^2)$: -$$ -\sum_{i=1}^{N-1}i\mbox{ comparaison et }3\sum_{i=1}^{N-1}i \mbox{ affectations -(swap)}\Rightarrow \mathcal{O}(N^2). -$$ -* En moyenne, $\mathcal{O}(N^2)$ ($N^2/2$ comparaisons). - -# L'algorithme à la main - -## Exercice *sur papier* - -* Trier par tri à bulles le tableau `[5, -2, 1, 3, 10, 15, 7, 4]` - -```C - - - - - - - - - - - - - -``` - -# Tri par insertion (1/3) - -## But - -* trier un tableau par ordre croissant - -## Algorithme - -Prendre un élément du tableau et le mettre à sa place parmi les éléments déjà -triés du tableau. - - - -# Tri par insertion (2/3) - -## Exercice: Proposer un algorithme (en C) - -. . . - -```C -void tri_insertion(int N, int tab[N]) { - for (int i = 1; i < N; i++) { - int tmp = tab[i]; - int pos = i; - while (pos > 0 && tab[pos - 1] > tmp) { - tab[pos] = tab[pos - 1]; - pos = pos - 1; - } - tab[pos] = tmp; - } -} -``` - -# Tri par insertion (3/3) - -## Question: Quelle est la complexité? - -. . . - -* Parcours de tous les éléments ($N-1$ passages dans la boucle) - * Placer: en moyenne $i$ comparaisons et affectations à l'étape $i$ -* Moyenne: $\mathcal{O}(N^2)$ - -. . . - -* Pire des cas, liste triée à l'envers: $\mathcal{O}(N^2)$ -* Meilleurs des cas, liste déjà triée: $\mathcal{O}(N)$ - -# L'algorithme à la main - -## Exercice *sur papier* - -* Trier par insertion le tableau `[5, -2, 1, 3, 10]` - -```C - - - - - - - - - - - - - -``` - -# Complexité algorithmique du radix-sort (1/2) - -## Pseudo-code - -```python -rien radix_sort(entier taille, entier tab[taille]): -# initialisation - entier val_min = valeur_min(taille, tab) - entier val_max = valeur_max(taille, tab) - decaler(taille, tab, val_min) - entier nb_bits = nombre_de_bits(val_max - val_min) -# algo - entier tab_tmp[taille] - pour pos de 0 à nb_bits: - alveole_0(taille, tab, tab_tmp, pos) # 0 -> taille - alveole_1(taille, tab, tab_tmp, pos) # taille -> 0 - echanger(tab, tab_tmp) -# post-traitement - decaler(taille, tab, -val_min) -``` - -# Complexité algorithmique du radix-sort (2/2) - -\footnotesize - -<!-- Voici une liste de parcours utilitaires de tableau: - -1. Recherche de la valeur minimum ```val_min``` -2. Recherche de la valeur maximum ```val_max``` -3. Décalage des valeurs dans l'intervalle ```0..val_max-val_min``` -4. Décalage inverse pour revenir dans l'intervalle ```val_min..val_max``` -5. Copie éventuelle du tableau temporaire dans le tableau originel - -On a donc un nombre de parcours fixe (4 ou 5) qui se font en $\mathcal{O}(N)$ où $N$ est la taille du tableau. - -La partie du tri à proprement parler est une boucle sur le nombre de bits *b* de ```val_min..val_max```. - -A chaque passage à travers la boucle, on parcourt 2 fois le tableau: la 1ère fois pour s'occuper des éléments dont le bit courant à 0; la 2ème pour ceux dont le bit courant est à 1. - -A noter que le nombre d'opérations est de l'ordre de *b* pour la lecture d'un bit et constant pour la fonction ```swap_ptr()```. - -Ainsi, la complexité du tri par base est $\mathcal{O}(b\cdot N)$. --> - -## Pseudo-code - -```python -rien radix_sort(entier taille, entier tab[taille]): -# initialisation - entier val_min = valeur_min(taille, tab) # O(taille) - entier val_max = valeur_max(taille, tab) # O(taille) - decaler(taille, tab, val_min) # O(taille) - entier nb_bits = - nombre_de_bits(val_max - val_min) # O(nb_bits) -# algo - entier tab_tmp[taille] - pour pos de 0 à nb_bits: # O(nb_bits) - alveole_0(taille, tab, tab_tmp, pos) # O(taille) - alveole_1(taille, tab, tab_tmp, pos) # O(taille) - echanger(tab, tab_tmp) # O(1) -# post-traitement - decaler(taille, tab, -val_min) # O(N) -``` - -. . . - -* Au final: $\mathcal{O}(N\cdot (b+4))$. - -# Complexité algorithmique du merge-sort (1/2) - -## Pseudo-code - -```python -rien tri_fusion(entier taille, entier tab[taille]) - entier tab_tmp[taille]; - entier nb_etapes = log_2(taille) + 1; - pour etape de 0 a nb_etapes - 1: - entier gauche = 0; - entier t_tranche = 2**etape; - tant que (gauche < taille): - fusion( - tab[gauche..gauche+t_tranche-1], - tab[gauche+t_tranche..gauche+2*t_tranche-1], - tab_tmp[gauche..gauche+2*t_tranche-1]); - gauche += 2*t_tranche; - echanger(tab, tab_tmp); -``` - -# Complexité algorithmique du merge-sort (2/2) - -## Pseudo-code - -```python -rien tri_fusion(entier taille, entier tab[taille]) - entier tab_tmp[taille] - entier nb_etapes = log_2(taille) + 1 - pour etape de 0 a nb_etapes - 1: # O(log2(taille)) - entier gauche = 0; - entier t_tranche = 2**etape - tant que (gauche < taille): # O(taille) - fusion( - tab[gauche..gauche+t_tranche-1], - tab[gauche+t_tranche..gauche+2*t_tranche-1], - tab_tmp[gauche..gauche+2*t_tranche-1]) - gauche += 2*t_tranche - echanger(tab, tab_tmp) -``` - -. . . - -* Au final: $\mathcal{O}(N\log_2(N))$. - -# Complexité algorithmique du quick-sort (1/2) - -## Pseudocode: quicksort - -```python -rien quicksort(entier tableau[], entier ind_min, entier ind_max) - si (longueur(tab) > 1) - ind_pivot = partition(tableau, ind_min, ind_max) - si (longueur(tableau[ind_min:ind_pivot-1]) != 0) - quicksort(tableau, ind_min, pivot_ind - 1) - si (longueur(tableau[ind_pivot+1:ind_max-1]) != 0) - quicksort(tableau, ind_pivot + 1, ind_max) -``` - - - -# Complexité algorithmique du quick-sort (2/2) - -## Quelle est la complexité du tri rapide? - -. . . - -* Pire des cas: $\mathcal{O}(N^2)$ - * Quand le pivot sépare toujours le tableau de façon déséquilibrée ($N-1$ - éléments d'un côté $1$ de l'autre). - * $N$ boucles et $N$ comparaisons $\Rightarrow N^2$. -* Meilleur des cas (toujours le meilleur pivot): $\mathcal{O}(N\cdot \log_2(N))$. - * Chaque fois le tableau est séparé en $2$ parties égales. - * On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot - \log_2(N)$. -* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$. - -# Le problème des 8-reines - -\Huge Le problème des 8-reines - -# Problème des 8-reines - -* Placer 8 reines sur un échiquier de $8 \times 8$. -* Sans que les reines ne puissent se menacer mutuellement (92 solutions). - -## Conséquence - -* Deux reines ne partagent pas la même rangée, colonne, ou diagonale. -* Donc chaque solution a **une** reine **par colonne** ou **ligne**. - -## Généralisation - -* Placer $N$ reines sur un échiquier de $N \times - N$. -- Exemple de **backtracking** (retour en arrière) $\Rightarrow$ récursivité. - -](./figs/fig_recursivite_8_reines.png){width=35%} - -# Problème des 2-reines - -{width=50%} - -# Comment trouver les solutions? - -* On pose la première reine sur la première case disponible. -* On rend inaccessibles toutes les cases menacées. -* On pose la reine suivante sur la prochaine case non-menacée. -* Jusqu'à ce qu'on puisse plus poser de reine. -* On revient alors en arrière jusqu'au dernier coup où il y avait plus qu'une - possibilité de poser une reine. -* On recommence depuis là. - -. . . - -* Le jeu prend fin quand on a énuméré *toutes* les possibilités de poser les - reines. - -# Problème des 3-reines - - - -# Problème des 4-reines - - - -# Problème des 4-reines, symétrie - - - -# Problème des 5 reines - -## Exercice: Trouver une solution au problème des 5 reines - -* Faire une capture d'écran / une photo de votre solution et la poster sur - matrix. - -```C - - - - - - - - - - - - - -``` - -# Quelques observations sur le problème - -* Une reine par colonne au plus. -* On place les reines sur des colonnes successives. -* On a pas besoin de "regarder en arrière" (on place "devant" uniquement). -* Trois étapes: - * On place une reine dans une case libre. - * On met à jour le tableau. - * Quand on a plus de cases libres on "revient dans le temps" ou c'est qu'on - a réussi. - -# Le code du problème des 8 reines (1/5) - -## Quelle structure de données? - -. . . - -Une matrice de booléens fera l'affaire: - -```C -bool board[n][n]; -``` - -## Quelles fonctionnalités? - -. . . - -```C -// Pour chaque ligne placer la reine sur toutes les colonnes -// et compter les solutions -void nbr_solutions(board, column, counter); -// Copier un tableau dans un autre -void copy(board_in, board_out); -// Placer la reine à li, co et rendre inaccessible devant -void placer_devant(board, li, co); -``` - -# Le code du problème des 8 reines (2/5) - -## Le calcul du nombre de solutions - -```C -// Calcule le nombre de solutions au problème des <n> reines -rien nbr_solutions(board, column, count) - pour chaque ligne - si la case libre - si column < n - 1 - copier board dans un "new" board, - y poser une reine - et mettre à jour ce "new" board - nbr_solutions(new_board, column+1, count) - sinon - on a posé la n-ème et on a gagné - count += 1 -``` - -# Le code du problème des 8 reines (3/5) - -## Le calcul du nombre de solutions - -```C -// Placer une reine et mettre à jour -rien placer_devant(board, ligne, colonne) - board est occupé à ligne/colonne - toutes les cases des colonnes - suivantes sont mises à jour -``` - -# Le code du problème des 8 reines (4/5) - -## Compris? Alors écrivez le code et postez le! - -. . . - -## Le nombre de solutions - -\footnotesize - -```C -// Calcule le nombre de solutions au problème des <n> reines -void nb_sol(int n, bool board[n][n], int co, int *ptr_cpt) { - for (int li = 0; li < n; li++) { - if (board[li][co]) { - if (co < n-1) { - bool new_board[n][n]; // alloué à chaque nouvelle tentative - copy(n, board, new_board); - prises_devant(n, new_board, li, co); - nb_sol(n, new_board, co+1, ptr_cpt); - } else { - *ptr_cpt = (*ptr_cpt)+1; - } - } - } -} -``` - - -# Le code du problème des 8 reines (5/5) - -\footnotesize - -## Placer devant - -```C -// Retourne une copie du tableau <board> complété avec les positions -// prises sur la droite droite par une reine placée en <board(li,co)> -void placer_devant(int n, bool board[n][n], int li, int co) { - board[li][co] = false; // position de la reine - for (int j = 1; j < n-co; j++) { - // horizontale et diagonales à droite de la reine - if (j <= li) { - board[li-j][co+j] = false; - } - board[li][co+j] = false; - if (li+j < n) { - board[li+j][co+j] = false; - } - } -} -``` diff --git a/slides/cours_9.md b/slides/cours_9.md new file mode 100644 index 0000000000000000000000000000000000000000..71d4667ee32090f753e2271d2136ffb87dd94fd0 --- /dev/null +++ b/slides/cours_9.md @@ -0,0 +1,725 @@ +--- +title: "Tris, complexité, backtracking et assertions" +date: "2024-11-25" +header-includes: | + \usepackage{xcolor} +--- + +# Le tri à bulle + +# Tri à bulle (1/4) + +## Algorithme + +* Parcours du tableau et comparaison des éléments consécutifs: + - Si deux éléments consécutifs ne sont pas dans l'ordre, ils sont échangés. +* On recommence depuis le début du tableau jusqu'à avoir plus d'échanges à + faire. + +## Que peut-on dire sur le dernier élément du tableau après un parcours? + +. . . + +* Le plus grand élément est **à la fin** du tableau. + * Plus besoin de le traiter. +* A chaque parcours on s'arrête un élément plus tôt. + +# Tri à bulle (2/4) + +## Exemple + + + + +# Tri à bulle (3/4) + +## Exercice: écrire l'algorithme (poster le résultat sur matrix) + +. . . + +```C +rien tri_a_bulles(entier tableau[]) + pour i de longueur(tableau)-1 à 1: + trié = vrai + pour j de 0 à i-1: + si (tableau[j] > tableau[j+1]) + échanger(tableau[j], tableau[j+1]) + trié = faux + + si trié + retourner +``` + +# Tri à bulle (4/4) + +## Quelle est la complexité du tri à bulles? + +. . . + +* Dans le meilleurs des cas: + * Le tableau est déjà trié: $\mathcal{O}(N)$ comparaisons. +* Dans le pire des cas, $N\cdot (N-1)/2\sim\mathcal{O}(N^2)$: +$$ +\sum_{i=1}^{N-1}i\mbox{ comparaison et }3\sum_{i=1}^{N-1}i \mbox{ affectations +(swap)}\Rightarrow \mathcal{O}(N^2). +$$ +* En moyenne, $\mathcal{O}(N^2)$ ($N^2/2$ comparaisons). + +# L'algorithme à la main + +## Exercice *sur papier* + +* Trier par tri à bulles le tableau `[5, -2, 1, 3, 10, 15, 7, 4]` + +```C + + + + + + + + + + + + + +``` + +# Tri par insertion (1/3) + +## But + +* trier un tableau par ordre croissant + +## Algorithme + +Prendre un élément du tableau et le mettre à sa place parmi les éléments déjà +triés du tableau. + + + +# Tri par insertion (2/3) + +## Exercice: Proposer un algorithme (en C) + +. . . + +```C +void tri_insertion(int N, int tab[N]) { + for (int i = 1; i < N; i++) { + int tmp = tab[i]; + int pos = i; + while (pos > 0 && tab[pos - 1] > tmp) { + tab[pos] = tab[pos - 1]; + pos = pos - 1; + } + tab[pos] = tmp; + } +} +``` + +# Tri par insertion (3/3) + +## Question: Quelle est la complexité? + +. . . + +* Parcours de tous les éléments ($N-1$ passages dans la boucle) + * Placer: en moyenne $i$ comparaisons et affectations à l'étape $i$ +* Moyenne: $\mathcal{O}(N^2)$ + +. . . + +* Pire des cas, liste triée à l'envers: $\mathcal{O}(N^2)$ +* Meilleurs des cas, liste déjà triée: $\mathcal{O}(N)$ + +# L'algorithme à la main + +## Exercice *sur papier* + +* Trier par insertion le tableau `[5, -2, 1, 3, 10]` + +```C + + + + + + + + + + + + + +``` + +# Complexité algorithmique du radix-sort (1/2) + +## Pseudo-code + +```python +rien radix_sort(entier taille, entier tab[taille]): +# initialisation + entier val_min = valeur_min(taille, tab) + entier val_max = valeur_max(taille, tab) + decaler(taille, tab, val_min) + entier nb_bits = nombre_de_bits(val_max - val_min) +# algo + entier tab_tmp[taille] + pour pos de 0 à nb_bits: + alveole_0(taille, tab, tab_tmp, pos) # 0 -> taille + alveole_1(taille, tab, tab_tmp, pos) # taille -> 0 + echanger(tab, tab_tmp) +# post-traitement + decaler(taille, tab, -val_min) +``` + +# Complexité algorithmique du radix-sort (2/2) + +\footnotesize + +<!-- Voici une liste de parcours utilitaires de tableau: + +1. Recherche de la valeur minimum ```val_min``` +2. Recherche de la valeur maximum ```val_max``` +3. Décalage des valeurs dans l'intervalle ```0..val_max-val_min``` +4. Décalage inverse pour revenir dans l'intervalle ```val_min..val_max``` +5. Copie éventuelle du tableau temporaire dans le tableau originel + +On a donc un nombre de parcours fixe (4 ou 5) qui se font en $\mathcal{O}(N)$ où $N$ est la taille du tableau. + +La partie du tri à proprement parler est une boucle sur le nombre de bits *b* de ```val_min..val_max```. + +A chaque passage à travers la boucle, on parcourt 2 fois le tableau: la 1ère fois pour s'occuper des éléments dont le bit courant à 0; la 2ème pour ceux dont le bit courant est à 1. + +A noter que le nombre d'opérations est de l'ordre de *b* pour la lecture d'un bit et constant pour la fonction ```swap_ptr()```. + +Ainsi, la complexité du tri par base est $\mathcal{O}(b\cdot N)$. --> + +## Pseudo-code + +```python +rien radix_sort(entier taille, entier tab[taille]): +# initialisation + entier val_min = valeur_min(taille, tab) # O(taille) + entier val_max = valeur_max(taille, tab) # O(taille) + decaler(taille, tab, val_min) # O(taille) + entier nb_bits = + nombre_de_bits(val_max - val_min) # O(nb_bits) +# algo + entier tab_tmp[taille] + pour pos de 0 à nb_bits: # O(nb_bits) + alveole_0(taille, tab, tab_tmp, pos) # O(taille) + alveole_1(taille, tab, tab_tmp, pos) # O(taille) + echanger(tab, tab_tmp) # O(1) +# post-traitement + decaler(taille, tab, -val_min) # O(N) +``` + +. . . + +* Au final: $\mathcal{O}(N\cdot (b+4))$. + +# Complexité algorithmique du merge-sort (1/2) + +## Pseudo-code + +```python +rien tri_fusion(entier taille, entier tab[taille]) + entier tab_tmp[taille]; + entier nb_etapes = log_2(taille) + 1; + pour etape de 0 a nb_etapes - 1: + entier gauche = 0; + entier t_tranche = 2**etape; + tant que (gauche < taille): + fusion( + tab[gauche..gauche+t_tranche-1], + tab[gauche+t_tranche..gauche+2*t_tranche-1], + tab_tmp[gauche..gauche+2*t_tranche-1]); + gauche += 2*t_tranche; + echanger(tab, tab_tmp); +``` + +# Complexité algorithmique du merge-sort (2/2) + +## Pseudo-code + +```python +rien tri_fusion(entier taille, entier tab[taille]) + entier tab_tmp[taille] + entier nb_etapes = log_2(taille) + 1 + pour etape de 0 a nb_etapes - 1: # O(log2(taille)) + entier gauche = 0; + entier t_tranche = 2**etape + tant que (gauche < taille): # O(taille) + fusion( + tab[gauche..gauche+t_tranche-1], + tab[gauche+t_tranche..gauche+2*t_tranche-1], + tab_tmp[gauche..gauche+2*t_tranche-1]) + gauche += 2*t_tranche + echanger(tab, tab_tmp) +``` + +. . . + +* Au final: $\mathcal{O}(N\log_2(N))$. + +# Complexité algorithmique du quick-sort (1/2) + +## Pseudocode: quicksort + +```python +rien quicksort(entier tableau[], entier ind_min, entier ind_max) + si (longueur(tab) > 1) + ind_pivot = partition(tableau, ind_min, ind_max) + si (longueur(tableau[ind_min:ind_pivot-1]) != 0) + quicksort(tableau, ind_min, pivot_ind - 1) + si (longueur(tableau[ind_pivot+1:ind_max-1]) != 0) + quicksort(tableau, ind_pivot + 1, ind_max) +``` + + + +# Complexité algorithmique du quick-sort (2/2) + +## Quelle est la complexité du tri rapide? + +. . . + +* Pire des cas: $\mathcal{O}(N^2)$ + * Quand le pivot sépare toujours le tableau de façon déséquilibrée ($N-1$ + éléments d'un côté $1$ de l'autre). + * $N$ boucles et $N$ comparaisons $\Rightarrow N^2$. +* Meilleur des cas (toujours le meilleur pivot): $\mathcal{O}(N\cdot \log_2(N))$. + * Chaque fois le tableau est séparé en $2$ parties égales. + * On a $\log_2(N)$ partitions, et $N$ boucles $\Rightarrow N\cdot + \log_2(N)$. +* En moyenne: $\mathcal{O}(N\cdot \log_2(N))$. + +# Le problème des 8-reines + +\Huge Le problème des 8-reines + +# Problème des 8-reines + +* Placer 8 reines sur un échiquier de $8 \times 8$. +* Sans que les reines ne puissent se menacer mutuellement (92 solutions). + +## Conséquence + +* Deux reines ne partagent pas la même rangée, colonne, ou diagonale. +* Donc chaque solution a **une** reine **par colonne** ou **ligne**. + +## Généralisation + +* Placer $N$ reines sur un échiquier de $N \times + N$. +- Exemple de **backtracking** (retour en arrière) $\Rightarrow$ récursivité. + +](./figs/fig_recursivite_8_reines.png){width=35%} + +# Problème des 2-reines + +{width=50%} + +# Comment trouver les solutions? + +* On pose la première reine sur la première case disponible. +* On rend inaccessibles toutes les cases menacées. +* On pose la reine suivante sur la prochaine case non-menacée. +* Jusqu'à ce qu'on puisse plus poser de reine. +* On revient alors en arrière jusqu'au dernier coup où il y avait plus qu'une + possibilité de poser une reine. +* On recommence depuis là. + +. . . + +* Le jeu prend fin quand on a énuméré *toutes* les possibilités de poser les + reines. + +# Problème des 3-reines + + + +# Problème des 4-reines + + + +# Problème des 4-reines, symétrie + + + +# Problème des 5 reines + +## Exercice: Trouver une solution au problème des 5 reines + +* Faire une capture d'écran / une photo de votre solution et la poster sur + matrix. + +```C + + + + + + + + + + + + + +``` + +# Quelques observations sur le problème + +* Une reine par colonne au plus. +* On place les reines sur des colonnes successives. +* On a pas besoin de "regarder en arrière" (on place "devant" uniquement). +* Trois étapes: + * On place une reine dans une case libre. + * On met à jour le tableau. + * Quand on a plus de cases libres on "revient dans le temps" ou c'est qu'on + a réussi. + +# Le code du problème des 8 reines (1/5) + +## Quelle structure de données? + +. . . + +Une matrice de booléens fera l'affaire: + +```C +bool board[n][n]; +``` + +## Quelles fonctionnalités? + +. . . + +```C +// Pour chaque ligne placer la reine sur toutes les colonnes +// et compter les solutions +void nbr_solutions(board, column, counter); +// Copier un tableau dans un autre +void copy(board_in, board_out); +// Placer la reine à li, co et rendre inaccessible devant +void placer_devant(board, li, co); +``` + +# Le code du problème des 8 reines (2/5) + +## Le calcul du nombre de solutions + +```C +// Calcule le nombre de solutions au problème des <n> reines +rien nbr_solutions(board, column, count) + pour chaque ligne + si la case libre + si column < n - 1 + copier board dans un "new" board, + y poser une reine + et mettre à jour ce "new" board + nbr_solutions(new_board, column+1, count) + sinon + on a posé la n-ème et on a gagné + count += 1 +``` + +# Le code du problème des 8 reines (3/5) + +## Le calcul du nombre de solutions + +```C +// Placer une reine et mettre à jour +rien placer_devant(board, ligne, colonne) + board est occupé à ligne/colonne + toutes les cases des colonnes + suivantes sont mises à jour +``` + +# Le code du problème des 8 reines (4/5) + +## Compris? Alors écrivez le code et postez le! + +. . . + +## Le nombre de solutions + +\footnotesize + +```C +// Calcule le nombre de solutions au problème des <n> reines +void nb_sol(int n, bool board[n][n], int co, int *ptr_cpt) { + for (int li = 0; li < n; li++) { + if (board[li][co]) { + if (co < n-1) { + bool new_board[n][n]; // alloué à chaque nouvelle tentative + copy(n, board, new_board); + prises_devant(n, new_board, li, co); + nb_sol(n, new_board, co+1, ptr_cpt); + } else { + *ptr_cpt = (*ptr_cpt)+1; + } + } + } +} +``` + + +# Le code du problème des 8 reines (5/5) + +\footnotesize + +## Placer devant + +```C +// Retourne une copie du tableau <board> complété avec les positions +// prises sur la droite droite par une reine placée en <board(li,co)> +void placer_devant(int n, bool board[n][n], int li, int co) { + board[li][co] = false; // position de la reine + for (int j = 1; j < n-co; j++) { + // horizontale et diagonales à droite de la reine + if (j <= li) { + board[li-j][co+j] = false; + } + board[li][co+j] = false; + if (li+j < n) { + board[li+j][co+j] = false; + } + } +} +``` + +# Les piles + +\Huge Les piles + +# Les piles (1/5) + +## Qu'est-ce donc? + +* Structure de données abstraite... + +. . . + +* de type `LIFO` (*Last in first out*). + +_LIFO.svg)](figs/Stack.svg){width=70%} + +## Des exemples de la vraie vie + +. . . + +* Pile d'assiettes, de livres, ... +* Adresses visitées par un navigateur web. +* Les calculatrices du passé (en polonaise inverse). +* Les boutons *undo* de vos éditeurs de texte (aka *u* dans vim). + +# Les piles (2/5) + +## Fonctionnalités + +. . . + +1. Empiler (push): ajouter un élément sur la pile. +2. Dépiler (pop): retirer l'élément du sommet de la pile et le retourner. +3. Liste vide? (is_empty?). + +. . . + +4. Jeter un œil (peek): retourner l'élément du sommet de la pile (sans le dépiler). +5. Nombre d'éléments (length). + +## Comment faire les 4, 5 à partir de 1 à 3? + +. . . + +4. Dépiler l'élément, le copier, puis l'empiler à nouveau. +5. Dépiler jusqu'à ce que la pile soit vide, puis empiler à nouveau. + +. . . + +## Existe en deux goûts + +* Pile avec ou sans limite de capacité (à concurrence de la taille de la +mémoire). + +# Les piles (3/5) + +## Implémentation + +* Jusqu'ici on n'a pas du tout parlé d'implémentation (d'où le nom de structure + abstraite). +* Pas de choix unique d'implémentation. + +## Quelle structure de données allons nous utiliser? + +. . . + +Et oui vous avez deviné: un tableau! + +## La structure: de quoi avons-nous besoin (pile de taille fixe)? + +. . . + +```C +#define MAX_CAPACITY 500 +typedef struct _stack { + int data[MAX_CAPACITY]; // les données + int top; // indice du sommet +} stack; +``` + +# Les piles (4/5) + +## Initialisation + +. . . + +```C +void stack_init(stack *s) { + s->top = -1; +} +``` + +## Est vide? + +. . . + +```C +bool stack_is_empty(stack s) { + return s.top == -1; +} +``` + +## Empiler (ajouter un élément au sommet) + +. . . + +```C +void stack_push(stack *s, int val) { + s->top += 1; + s->data[s->top] = val; +} +``` + +# Les piles (5/5) + +## Dépiler (enlever l'élément du sommet) + +. . . + +```C +int stack_pop(stack *s) { + s->top -= 1; + return s->data[s->top+1]; +} +``` + +## Jeter un oeil (regarder le sommet) + +. . . + +```C +int stack_peek(stack s) { + return s.data[s.top]; +} +``` + +## Quelle est la complexité de ces opérations? + +. . . + +## Voyez-vous des problèmes potentiels avec cette implémentation? + +. . . + +* Empiler avec une pile pleine. +* Dépiler avec une pile vide. +* Jeter un oeil au sommet d'une pile vide. + +# Gestion d'erreur, level 0 + +* Il y a plusieurs façon de traiter les erreur: + * Ne rien faire (laisser la responsabilité à l'utilisateur). + * Faire paniquer le programme (il plante plus ou moins violemment). + * Utiliser des codes d'erreurs. + +## La panique + +* En C, on a les `assert()` pour faire paniquer un programme. + +# Les assertions + +\Huge Les assertions + +# Assertions (1/3) + +```C +#include <assert.h> +void assert(int expression); +``` + +## Qu'est-ce donc? + +- Macro permettant de tester une condition lors de l'exécution d'un programme: + - Si `expression == 0`{.C} (condition fausse), `assert()`{.C} affiche un message d'erreur sur `stderr`{.C} et termine l'exécution du programme. + - Sinon l'exécution se poursuit normalement. + - Peuvent être désactivés à la compilation avec `-DNDEBUG` (équivalent à `#define NDEBUG`) + +## À quoi ça sert? + +- Permet de réaliser des tests unitaires. +- Permet de tester des conditions catastrophiques d'un programme. +- **Ne permet pas** de gérer les erreurs. + +# Assertions (2/3) + +<!-- \footnotesize --> + +## Exemple + +```C +#include <assert.h> +void stack_push(stack *s, int val) { + assert(s->top < MAX_CAPACITY-1); + s->top += 1; + s->data[s->top] = val; +} +int stack_pop(stack *s) { + assert(s->top >= 0); + s->top -= 1; + return s->data[s->top+1]; +} +int stack_peek(stack *s) { + assert(s->top >= 0); + return s->data[s->top]; +} +``` + +# Assertions (3/3) + +## Cas typiques d'utilisation + +- Vérification de la validité des pointeurs (typiquement `!= NULL`{.C}). +- Vérification du domaine des indices (dépassement de tableau). + +## Bug vs. erreur de *runtime* + +- Les assertions sont là pour détecter les bugs (erreurs d'implémentation). +- Les assertions ne sont pas là pour gérer les problèmes externes au programme (allocation mémoire qui échoue, mauvais paramètre d'entrée passé par l'utilisateur, ...). + +. . . + +- Mais peuvent être pratiques quand même pour ça... +- Typiquement désactivées dans le code de production. diff --git a/slides/figs/Stack.svg b/slides/figs/Stack.svg new file mode 100644 index 0000000000000000000000000000000000000000..49629d25e44c9e81d41487e0a5c803d5b321430b --- /dev/null +++ b/slides/figs/Stack.svg @@ -0,0 +1,723 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="877.8725" + height="238.06184" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)" + sodipodi:docname="Stack.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape" + version="1.0"> + <defs + id="defs4"> + <marker + inkscape:stockid="Arrow1Lstart" + orient="auto" + refY="0" + refX="0" + id="Arrow1Lstart" + style="overflow:visible"> + <path + id="path3595" + d="M 0,0 5,-5 -12.5,0 5,5 Z" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none" + transform="matrix(0.8,0,0,0.8,10,0)" + inkscape:connector-curvature="0" /> + </marker> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <inkscape:perspective + id="perspective2390" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 526.18109 : 1" + sodipodi:type="inkscape:persp3d" /> + <inkscape:perspective + id="perspective2397" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 526.18109 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + gridtolerance="10000" + guidetolerance="10" + objecttolerance="10" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.49497475" + inkscape:cx="82.441629" + inkscape:cy="51.169001" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:window-width="944" + inkscape:window-height="334" + inkscape:window-x="14" + inkscape:window-y="732" + inkscape:snap-bbox="true" + inkscape:object-paths="true" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" + inkscape:window-maximized="0"> + <inkscape:grid + type="xygrid" + id="grid2396" + visible="true" + enabled="false" + originx="-10.936806" + originy="-30.969077" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-22.931711,-813.82583)"> + <g + id="g5578" + transform="translate(-23.246306,-18.180276)"> + <path + id="rect2392" + d="M 61.055945,1044.6512 H 196.05595 v 24.6667 H 61.055945 Z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="M 61.055945,1019.9845 H 196.05595 v 24.6667 H 61.055945 Z" + id="path3165" + inkscape:connector-curvature="0" /> + <path + id="path3167" + d="M 61.055945,994.98453 H 196.05595 v 24.66667 H 61.055945 Z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + id="text3169" + y="1039.6512" + x="46.568642" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1039.6512" + x="46.568642" + id="tspan3171" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">1</tspan></text> + <text + id="text3173" + y="1014.6512" + x="46.055946" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1014.6512" + x="46.055946" + id="tspan3175" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">2</tspan></text> + <text + id="text3177" + y="989.52429" + x="45.855751" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="989.52429" + x="45.855751" + id="tspan3179" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">3</tspan></text> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="M 61.055945,969.98453 H 196.05595 v 24.66672 H 61.055945 Z" + id="path2403" + inkscape:connector-curvature="0" /> + <path + id="path2405" + d="M 61.055945,944.98453 H 196.05595 v 24.66672 H 61.055945 Z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="46.178017" + y="964.62195" + id="text2407"><tspan + sodipodi:role="line" + id="tspan2409" + x="46.178017" + y="964.62195" + style="font-size:20px;line-height:1.25">4</tspan><tspan + id="tspan2415" + sodipodi:role="line" + x="46.178017" + y="989.62195" + style="font-size:20px;line-height:1.25"> </tspan></text> + <text + id="text2411" + y="1064.1959" + x="45.885048" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1959" + x="45.885048" + id="tspan2413" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">0</tspan></text> + <path + id="path2544" + d="m 242.8671,1044.6512 h 135 v 24.6667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 242.8671,1019.9845 h 135 v 24.6667 h -135 z" + id="path2546" + inkscape:connector-curvature="0" /> + <path + id="path2548" + d="m 242.8671,994.98453 h 135 v 24.66667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + id="text2550" + y="1039.6512" + x="228.37979" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1039.6512" + x="228.37979" + id="tspan2552" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">1</tspan></text> + <text + id="text2554" + y="1014.6512" + x="227.8671" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1014.6512" + x="227.8671" + id="tspan2556" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">2</tspan></text> + <text + id="text2558" + y="989.52429" + x="227.6669" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="989.52429" + x="227.6669" + id="tspan2560" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">3</tspan></text> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 242.8671,969.98453 h 135 v 24.66672 h -135 z" + id="path2562" + inkscape:connector-curvature="0" /> + <path + id="path2564" + d="m 242.86711,944.98453 h 135 v 24.66672 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="227.98917" + y="964.62195" + id="text2566"><tspan + sodipodi:role="line" + id="tspan2568" + x="227.98917" + y="964.62195" + style="font-size:20px;line-height:1.25">4</tspan><tspan + id="tspan2570" + sodipodi:role="line" + x="227.98917" + y="989.62195" + style="font-size:20px;line-height:1.25"> </tspan></text> + <text + id="text2572" + y="1064.1959" + x="227.6962" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1959" + x="227.6962" + id="tspan2574" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">0</tspan></text> + <path + id="path2580" + d="m 424.67822,1044.6512 h 135 v 24.6667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 424.67822,1019.9845 h 135 v 24.6667 h -135 z" + id="path2582" + inkscape:connector-curvature="0" /> + <path + id="path2584" + d="m 424.67822,994.98453 h 135 v 24.66667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + id="text2586" + y="1039.6512" + x="410.19092" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1039.6512" + x="410.19092" + id="tspan2588" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">1</tspan></text> + <text + id="text2590" + y="1014.6512" + x="409.67822" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1014.6512" + x="409.67822" + id="tspan2592" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">2</tspan></text> + <text + id="text2594" + y="989.52429" + x="409.47803" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="989.52429" + x="409.47803" + id="tspan2596" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">3</tspan></text> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 424.67822,969.98453 h 135 v 24.66672 h -135 z" + id="path2598" + inkscape:connector-curvature="0" /> + <path + id="path2600" + d="m 424.67822,944.98453 h 135 v 24.66672 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="409.80029" + y="964.62195" + id="text2602"><tspan + sodipodi:role="line" + id="tspan2604" + x="409.80029" + y="964.62195" + style="font-size:20px;line-height:1.25">4</tspan><tspan + id="tspan2606" + sodipodi:role="line" + x="409.80029" + y="989.62195" + style="font-size:20px;line-height:1.25"> </tspan></text> + <text + id="text2608" + y="1064.1959" + x="409.50732" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1959" + x="409.50732" + id="tspan2610" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">0</tspan></text> + <path + id="path2616" + d="m 606.48937,1044.6512 h 135 v 24.6667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 606.48937,1019.9845 h 135 v 24.6667 h -135 z" + id="path2618" + inkscape:connector-curvature="0" /> + <path + id="path2620" + d="m 606.48937,994.98453 h 135 v 24.66667 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + id="text2622" + y="1039.6512" + x="592.00208" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1039.6512" + x="592.00208" + id="tspan2624" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">1</tspan></text> + <text + id="text2626" + y="1014.6512" + x="591.48938" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1014.6512" + x="591.48938" + id="tspan2628" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">2</tspan></text> + <text + id="text2630" + y="989.52429" + x="591.28918" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="989.52429" + x="591.28918" + id="tspan2632" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">3</tspan></text> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 606.48937,969.98453 h 135 v 24.66672 h -135 z" + id="path2634" + inkscape:connector-curvature="0" /> + <path + id="path2636" + d="m 606.48937,944.98453 h 135 v 24.66672 h -135 z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="591.61145" + y="964.62195" + id="text2638"><tspan + sodipodi:role="line" + id="tspan2640" + x="591.61145" + y="964.62195" + style="font-size:20px;line-height:1.25">4</tspan><tspan + id="tspan2642" + sodipodi:role="line" + x="591.61145" + y="989.62195" + style="font-size:20px;line-height:1.25"> </tspan></text> + <text + id="text2644" + y="1064.1959" + x="591.31848" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1959" + x="591.31848" + id="tspan2646" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">0</tspan></text> + <g + transform="translate(769.3005,38.058349)" + id="g2650"> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="m 19,1006.5929 h 135 v 24.6667 H 19 Z" + id="path2652" + inkscape:connector-curvature="0" /> + <path + id="path2654" + d="m 19,981.92618 h 135 v 24.66672 H 19 Z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="M 19,956.92618 H 154 V 981.5929 H 19 Z" + id="path2656" + inkscape:connector-curvature="0" /> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="4.5126953" + y="1001.5929" + id="text2658"><tspan + sodipodi:role="line" + id="tspan2660" + x="4.5126953" + y="1001.5929" + style="font-size:20px;line-height:1.25">1</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="4" + y="976.5929" + id="text2662"><tspan + sodipodi:role="line" + id="tspan2664" + x="4" + y="976.5929" + style="font-size:20px;line-height:1.25">2</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="3.7998047" + y="951.46594" + id="text2666"><tspan + sodipodi:role="line" + id="tspan2668" + x="3.7998047" + y="951.46594" + style="font-size:20px;line-height:1.25">3</tspan></text> + <path + id="path2670" + d="M 19,931.92618 H 154 V 956.5929 H 19 Z" + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + inkscape:connector-curvature="0" /> + <path + style="display:inline;overflow:visible;visibility:visible;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;enable-background:accumulate" + d="M 19,906.92618 H 154 V 931.5929 H 19 Z" + id="path2672" + inkscape:connector-curvature="0" /> + <text + id="text2674" + y="926.5636" + x="4.1220703" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="926.5636" + x="4.1220703" + id="tspan2676" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">4</tspan><tspan + y="951.5636" + x="4.1220703" + sodipodi:role="line" + id="tspan2678" + style="font-size:20px;line-height:1.25"> </tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="3.8291016" + y="1026.1376" + id="text2680"><tspan + sodipodi:role="line" + id="tspan2682" + x="3.8291016" + y="1026.1376" + style="font-size:20px;line-height:1.25">0</tspan></text> + </g> + <text + id="text2684" + y="1064.1427" + x="303.69717" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1427" + x="303.69717" + id="tspan2686" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">A</tspan></text> + <text + id="text2688" + y="1039.4761" + x="485.30811" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1039.4761" + x="485.30811" + id="tspan2690" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">B</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="485.5083" + y="1064.1427" + id="text2763"><tspan + sodipodi:role="line" + id="tspan2765" + x="485.5083" + y="1064.1427" + style="font-size:20px;line-height:1.25">A</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="121.88602" + y="846.32251" + id="text2816"><tspan + sodipodi:role="line" + id="tspan2818" + x="121.88602" + y="846.32251" + style="font-size:20px;line-height:1.25">A</tspan></text> + <g + transform="translate(-110.82003,-12.8571)" + id="g5458"> + <g + id="g5454"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none" + d="m 239.37598,930.5929 v -45" + id="path4887" + sodipodi:nodetypes="cs" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + transform="translate(4.3759766,771.5929)" + id="path5452" + d="m 230,149 5,10 5,-10" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + inkscape:connector-curvature="0" /> + </g> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="303.49698" + y="846.32251" + id="text5496"><tspan + sodipodi:role="line" + id="tspan5498" + x="303.49698" + y="846.32251" + style="font-size:20px;line-height:1.25">B</tspan></text> + <g + id="g5500" + transform="translate(70.991133,-12.8571)"> + <g + id="g5502"> + <path + sodipodi:nodetypes="cs" + id="path5504" + d="m 239.37598,930.5929 v -45" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 230,149 5,10 5,-10" + id="path5506" + transform="translate(4.3759766,771.5929)" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + </g> + </g> + <text + id="text5508" + y="846.32251" + x="485.30811" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="846.32251" + x="485.30811" + id="tspan5510" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">B</tspan></text> + <g + transform="matrix(1,0,0,-1,252.80224,1803.3287)" + id="g5512"> + <g + id="g5514"> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none" + d="m 239.37598,930.5929 v -45" + id="path5516" + sodipodi:nodetypes="cs" + inkscape:connector-curvature="0" /> + <path + sodipodi:nodetypes="ccc" + transform="translate(4.3759766,771.5929)" + id="path5518" + d="m 230,149 5,10 5,-10" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + inkscape:connector-curvature="0" /> + </g> + </g> + <text + id="text5520" + y="1064.1427" + x="485.5083" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + xml:space="preserve"><tspan + y="1064.1427" + x="485.5083" + id="tspan5522" + sodipodi:role="line" + style="font-size:20px;line-height:1.25">A</tspan></text> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="667.31946" + y="1064.1427" + id="text5558"><tspan + sodipodi:role="line" + id="tspan5560" + x="667.31946" + y="1064.1427" + style="font-size:20px;line-height:1.25">A</tspan></text> + <g + id="g5566" + transform="matrix(1,0,0,-1,434.61339,1803.3287)"> + <g + id="g5568"> + <path + sodipodi:nodetypes="cs" + id="path5570" + d="m 239.37598,930.5929 v -45" + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none" + inkscape:connector-curvature="0" /> + <path + style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 230,149 5,10 5,-10" + id="path5572" + transform="translate(4.3759766,771.5929)" + sodipodi:nodetypes="ccc" + inkscape:connector-curvature="0" /> + </g> + </g> + <text + xml:space="preserve" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:0%;font-family:Arial;-inkscape-font-specification:Arial;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + x="667.31946" + y="846.32251" + id="text5574"><tspan + sodipodi:role="line" + id="tspan5576" + x="667.31946" + y="846.32251" + style="font-size:20px;line-height:1.25">A</tspan></text> + </g> + </g> +</svg>