498 views
 owned this note
--- title: Sur l'épreuve pratique NSI — sujet n°35, 2023 langs: fr-fr tags: c3i, ep ... # Sur l'épreuve pratique NSI — sujet n°35, 2023 > C3I : commission inter-IREM informatique > [univ-irem.fr/c3i](https://www.univ-irem.fr/spip.php?rubrique506) > [c3i-contact@groupes.renater.fr](mailto:c3i-contact@groupes.renater.fr) > 28 janvier 2023 _Ce sujet est une évolution du sujet n°20 de 2022 que nous avons analysé dans [codimd.math.cnrs.fr/s/C3WQ4L4s8](https://codimd.math.cnrs.fr/s/C3WQ4L4s8#)._ - Thème de l'exercice 1 : L'opérateur « ou exclusif » entre deux bits - Thème de l'exercice 2 : Carré « semi-magique » ## Introduction Ce document propose une analyse des deux exercices du sujet n°35 de l'épreuve pratique de Numériques et sciences informatiques (NSI) du baccalauréat 2023 (il s'agit d'une mise à jour du sujet n°20 de 2022). Nous proposons pour chaque exercice une transcription de l'énoncé, des solutions possibles, une analyse des notions en jeu et de leur présentation dans l'exercice, et des suggestions éventuelles d'énoncés alternatifs. ## Exercice 1 **Mots-clés :** ou exclusif, tableaux ### Énoncé :::info EXERCICE 1 (4 points) L'opérateur « ou exclusif » entre deux bits renvoie 0 si les deux bits sont égaux et 1 s'ils sont différents. Il est symbolisé par le caractère ⊕. Ainsi : * 0 ⊕ 0 = 0 * 0 ⊕ 1 = 1 * 1 ⊕ 0 = 1 * 1 ⊕ 1 = 0 On représente ici une suite de bits par un tableau contenant des 0 et des 1. Exemples : ```python a = [1, 0, 1, 0, 1, 1, 0, 1] b = [0, 1, 1, 1, 0, 1, 0, 0] c = [1, 1, 0, 1] d = [0, 0, 1, 1] ``` Écrire la fonction `ou_exclusif` qui prend en paramètres deux tableaux de même longueur et qui renvoie un tableau où l’élément situé à position `i` est le résultat, par l’opérateur « ou exclusif », des éléments à la position `i` des tableaux passés en paramètres. En considérant les quatre exemples ci-dessus, cette fonction donne : ```python >>> ou_exclusif(a, b) [1, 1, 0, 1, 1, 0, 0, 1] >>> ou_exclusif(c, d) [1, 1, 1, 0] ``` ::: ### Propositions de solutions Version avec les listes en compréhension et le modulo : ```python def ou_exclusif(a, b): return [(a[i] + b[i]) % 2 for i in range(len(a))] ``` Versions à la main probablement attendues : ```python def ou_exclusif(a, b): resultat = [] for i in range(len(a)): if a[i] == b[i]: resultat.append(0) else: resultat.append(1) return resultat ``` ```python def ou_exclusif(a, b): resultat = [] for i in range(len(a)): resultat.append(a[i]^b[i]) return resultat ``` ```python def ou_exclusif(a, b): longueur = len(a) resultat = [0]*longueur for i in range(longueur): resultat[i] = a[i]^b[i] return resultat ``` Versions en passant par les booléens : ```python def ou_exclusif(a, b): return [int(a[i] != b[i]) for i in range(len(a))] ``` ```python from operator import xor def ou_exclusif(a, b): return [xor(a[i], b[i]) for i in range(len(a))] ``` En contournant l'itération : ```python from operator import xor def ou_exclusif(a, b): return list(map(xor, a, b)) ``` ### Analyse L'opérateur *ou exclusif* est à la fois un opérateur logique qui s'applique aux valeurs de vérité et un opérateur qui s'applique aux bits et aux chaînes de bits selon la convention décrite dans l'énoncé. À ce titre, il s'applique aussi aux entiers positifs en considérant leur écriture binaire. Python fournit l'opérateur binaire `^` (et la fonction `operator.xor`) pour représenter cette opération sur les booléens et les entiers. Par exemple : ```python >>> 5 ^ 6 3 >>> (2**100 + 1) ^ 2**100 1 ``` Dans le premier cas, le résultat est $3$ parce que $5$ et $6$ s'écrivent respectivement $(101)_2$ et $(110)_2$ en binaire. Le ou exclusif bit par bit donne donc $(011)_2$ qui est une écriture binaire de $3$. Voici un exemple qui rend ce fonctionnement plus explicite: ```python >>> 0b101 ^ 0b110 3 >>> bin(0b101 ^ 0b110) '0b11' ``` L'opérateur de comparaison `!=`, suggéré par la première phrase de l'énoncé, coïncide avec `^` lorsqu'il est appliqué aux valeurs booléennes, et uniquement dans ce cas. Pour représenter des chaînes de bits, on a habituellement recours à des entiers. Cet énoncé utilise des tableaux de bits. L'intention est donc bien de travailler la notion de tableau pour elle-même, avec les savoirs associés: parcours, accès à un élément par son indice, construction ou modification d'un tableau, etc. Par ailleurs, la référence à un indice `i` dans l'énoncé suggère l'usage de l'itération. Si l'on considère l'opération demandée sur les tableaux, indépendamment du calcul du ou exclusif, on a affaire à un cas particulier de la fonction `map` qui consiste à appliquer une fonction donnée à chaque élément d'un ou plusieurs tableaux, en combinant les éléments de même rang. ```python >>> list(map(operator.xor, [1, 0, 1], [1, 1, 0])) [0, 1, 1] >>> list(map(operator.add, [1, 2, 3, 4], [5, 6, 10, -4])) [6, 8, 13, 0] ``` Le schéma qui consiste à appliquer une même opération à chacun des éléments d'une liste est tellement fréquent que Python fournit la syntaxe spécifique des listes en compréhension pour l'exprimer : `[f(x) for x in liste]` est équivalent à `map(f, liste)`. ### Comparaison avec la version de 2022 - La présentation en liste de l'opérateur $\oplus$ est plus lisible. - L'utilisation de `assert`, critiquable, a été supprimée. ### Suggestions Extensions envisageables, questions que l'on peut poser - produire la liste des indices où les listes ne coïncident pas. On oblige alors la création dynamique de la liste résultat dont la longueur sera fonction des valeurs des paramètres. La manipulation de listes d'indices est un savoir-faire souhaitable. - changer l'opérateur "ou exclusif" pour un autre, par exemple le produit d'entiers. Cet opérateur pourrait même être défini par une fonction. L'exercice consiste alors à écrire la fonction `map()`. - que se passe-t-il si on passe des listes de tailles différentes ? Pourquoi l'énoncé donne-t-il comme prérequis l'égalité des longeurs des tableaux ? Reformulation possible de l'énoncé : :::warning L'opérateur « ou exclusif » entre deux bits renvoie 0 si les deux bits sont égaux et 1 s'ils sont différents. Il est symbolisé par le caractère ⊕. Ainsi : * 0 ⊕ 0 = 0 * 0 ⊕ 1 = 1 * 1 ⊕ 0 = 1 * 1 ⊕ 1 = 0 On représente ici une suite de bits par un tableau contenant des 0 et des 1. Exemples : ```python a = [1, 0, 1, 0, 1, 1, 0, 1] b = [0, 1, 1, 1, 0, 1, 0, 0] c = [1, 1, 0, 1] d = [0, 0, 1, 1] ``` Écrire une fonction `ou_exclusif` qui prend en entrée deux tableaux de même longueur contenant des 0 et des 1 et qui renvoie un tableau de même longueur que les entrées. Dans le tableau résultat, l’élément d'indice `i` est le résultat du « ou exclusif » appliqué aux éléments de même indice des tableaux passés en entrée. Les doctests suivants permettent de valider la fonction : ```python def ou_exclusif(a, b): """ >>> a = [1, 0, 1, 0, 1, 1, 0, 1] >>> b = [0, 1, 1, 1, 0, 1, 0, 0] >>> c = [1, 1, 0, 1] >>> d = [0, 0, 1, 1] >>> ou_exclusif(a, b) [1, 1, 0, 1, 1, 0, 0, 1] >>> ou_exclusif(c, d) [1, 1, 1, 0] """ ... return ... ``` ::: ## Exercice 2 **Mots-clés :** programmation orientée objet, tableaux à deux dimensions. ### Énoncé :::info EXERCICE 2 (4 points) Dans cet exercice, on appelle carré d’ordre $n$ un tableau de $n$ lignes et $n$ colonnes dont chaque case contient un entier naturel. Exemples : ![](https://codimd.math.cnrs.fr/uploads/upload_98ce540236b5c7a7c5e12517ad8423dd.png) Un carré est dit semimagique lorsque les sommes des éléments situés sur chaque ligne, chaque colonne et chaque diagonale sont égales. * Ainsi c2 et c3 sont semimagiques car la somme de chaque ligne et chaque colonne est égale à $8$ pour c2 et $12$ pour c3. * Le carré c3bis n'est pas semimagiques car la somme de la première ligne est égale à $15$ alors que celle de la deuxième ligne est égale à $10$. La classe `Carre` en page suivante contient des méthodes qui permettent de manipuler des carrés : * La méthode constructeur crée un carré sous forme d'un tableau à deux dimensions à partir d'une liste d'entiers, et d'un ordre. * La méthode `affiche` permet d'afficher le carré créé. Exemple : ```python >>> liste = (3, 4, 5, 4, 4, 4, 5, 4, 3) >>> c3 = Carre(liste, 3) >>> c3.affiche() [3, 4, 5] [4, 4, 4] [5, 4, 3] ``` Compléter la méthode `est_semimagique` qui renvoie `True` si le carré est semimagique, `False` sinon. Puis tester la fonction `est_semimagique` sur les carrés c2, c3 et c3bis. ```python class Carre: def __init__(self, liste, n): self.ordre = n self.tableau = [[liste[i + j * n] for i in range(n)] for j in range(n)] def affiche(self): '''Affiche un carré''' for i in range(self.ordre): print(self.tableau[i]) def somme_ligne(self, i): '''Calcule la somme des valeurs de la ligne i''' somme = 0 for j in range(self.ordre): somme = somme + self.tableau[i][j] return somme def somme_col(self, j): '''Calcule la somme des valeurs de la colonne j''' somme = 0 for i in range(self.ordre): somme = somme + self.tableau[i][j] return somme def est_semimagique(self): s = self.somme_ligne(0) #test de la somme de chaque ligne for i in range(...): if ... != s: return ... #test de la somme de chaque colonne for j in range(...): if ... != s: return ... return ... ``` ::: ### Proposition de solution ```python def est_semimagique(self): s = self.somme_ligne(0) #test de la somme de chaque ligne for i in range(self.ordre): if self.somme_ligne(i) != s: return False #test de la somme de chaque colonne for j in range(self.ordre): if self.somme_col(j) != s: return False return True ``` Et le test de la fonction sur les trois carrés donnés en exemple : ```python c2 = Carre([1, 1, 1, 1]) c3 = Carre([2, 9, 4, 7, 5, 3, 6, 1, 8]) c3bis = Carre([2, 9, 4, 7, 0, 3, 6, 1, 8]) >>> est_semimagique(c2) True >>> est_semimagique(c3) True >>> est_semimagique(c3bis) False ``` ### Analyse Cet exercice porte sur l'utilisation de classes fournies et la création d'objets. On notera l'utilisation de listes en compréhension. Les compétences informatiques à mettre en jeu pour répondre à l'exercice sont limitées, en effet il n'y a que quelques expressions à compléter. Il y a deux fois la même chose à écrire, puisque le cas des lignes et le cas des colonnes sont essentiellement identiques. On peut regretter que la création des objets nécessaires aux tests soit donnée dans l'énoncé. Ce sujet est une évolution du sujet n°20 de 2022. L'essentiel des points problématiques de cette version antérieure a été corrigé. En contrepartie, l'exercice est devenu nettement plus simple. ### Suggestions De possibles questions pour l'oral sont * de questionner la représentation en ligne ou en colonne du carré * d'éviter la comparaison entre `s` et `somme_ligne(0)` lors de la 1re itération de la boucle dans `est_semicarre()` ```python #test de la somme de chaque ligne for i in range(self.ordre-1): if somme_ligne(i+1) != s: return ... ``` ou ```python #test de la somme de chaque ligne for i in range(1, self.ordre): if somme_ligne(i) != s: return ... ``` * de vérifier que la somme des valeurs de la diagonale est égale à la somme du carré ### Conclusion Un exercice de compréhension de la programmation objet, sans autre enjeu ou ouverture.