cours CI

Première partie : les pyBox

I. Les autotests : tester les variables ou les fonctions, aléatoire ou choisi

A) pour tester le contenu d'une variable

[pyBox
slug='auto_a'
title='exemple1'

defaultcode='# ecrire un code qui crée une variable x et lui affecte la valeur 3
votre code ne doit produire aucune sortie en console
'
solver='x=3'
autotests='x'
] Testez avec rien, puis avec x=1 puis avec x=3 dans le code

[/pyBox]
L'autotest génèrera une erreur si la variable x est non définie dans le code élève ou si elle n'a pas la même valeur que lors de l'exécution du solver.

Exercice de code : exemple1
Testez avec rien, puis avec x=1 puis avec x=3 dans le code

On peut cumuler l'autotest avec une sortie console. par exemple :

[pyBox
slug='auto_a2'
defaultcode='# ecrire un code qui crée une variable x et lui affecte la valeur 3
votre code doit ensuite afficher : x = 3
'
solver='x=3
print("x = ",x)
'
autotests='x'
] Testez avec x=3 dans le code, sans le print, puis avec le print.
[/pyBox]
En plus de l'autotests, les sorties consoles sont testées aussi.

Exercice de code
Testez avec x=3 dans le code, sans le print, puis avec le print.

B) pour tester une fonction

C'est ce que j'utilise le plus, sauf début d'année en première (évidement).

[pyBox
slug='auto_b'
defaultcode='def ma_fonction(n:int) -> int:
    # votre code ici
'
solver='def ma_fonction(n):
    return n**2
'
autotests='ma_fonction(3)
ma_fonction(2)
ma_fonction(_rint(3,9))
'
] Ecrire une fonction qui prend en paramètre un entier n et renvoi la valeur de n2.

On peut aussi utiliser des balises latex : [latex size=2](\frac{3}{2})^2[/latex]
[/pyBox]
L'autotests va appeler le solver avec les appels définis, et comparer avec les résultats fournis par le code élève pour les mêmes appels.

Exercice de code
Ecrire une fonction qui prend en paramètre un entier n et renvoi la valeur de n2.
On peut aussi utiliser des balises latex : (\frac{3}{2})^2

vous noterez bien la ligne : ma_fonction(_rint(3,9))

_rint est un raccourci pour random.randint et on a pas besoin d'importer random. Ce test sera donc aléatoire, ce qui évite dans certains cas des codes qui affichent ou renvoi la bonne réponse sans faire vraiment le code !

(quoique... j'ai vu un élève faire ça puis m'appeler pour valider, sa boite était verte, mais si on exécutait ça marchait une fois sur 10....)

II. le precode

C'est un code qui sera excuté, aussi bien avant le solver qu'avant le code de l'élève. On peut y mettre des import, des fonctions, des variables.

Les variables et les fonctions qu'on nomme avec un _ : _truc ne seront pas visibles pour l'élèves même à l'exécution.

[pyBox
title="précode"
slug='precode'
precode = 'def afficher(val,name):
print(name,"=",val)
var = 1
_var = _rint(1,100)
'
defaultcode='# votre code doit créer une variable x qui vaut 2
et l\'afficher en utilisant la fonction afficher
Vous afficherez ensuite le contenu de deux variables prédéfinies
dans le précode nommées var et _var
'
solver='x = 2
afficher(x,"x")
afficher(var,"var")
afficher(_var,"_var")
'
autotests='afficher(3,"x")
afficher(_rint(3,9),"valeur aléatoire")
'
]Dans cet exercice on a prédéfini (dans le précode) une fonction afficher(valeur,nom) qui affiche la valeur d\'une variable sous la forme nom = valeur.

Exemple (si x vaut 2) : afficher(x,"x") affichera x = 2


le code définit également deux variables, var et _var, que vous devez afficher de la même façon avec la fonction afficher.
[/pyBox]
Exercice de code : précode
Dans cet exercice on a prédéfini (dans le précode) une fonction afficher(valeur,nom) qui affiche la valeur d\'une variable sous la forme nom = valeur.
Exemple (si x vaut 2) : afficher(x,"x") affichera x = 2

le code définit également deux variables, var et _var, que vous devez afficher de la même façon avec la fonction afficher.

Attention : l'autotests exécute les appels, mais ici la fonction ne revoie rien mais affiche en console. Le test sera pris en compte mais via les sorties console.

Notez bien aussi :

Before running your code: We defined a function afficher and var equal to 1.

la variable _var n'est pas montrée, mais elle existe.

III. repeats avec generator : Tests aléatoires

On ajoute un élément generator qui génère une (ou plusieurs) valeur(s) qui sera(ont) utilisée(s) par input().

repeats permet de définir combien de test on va faire, ce n'est intéressant que si le générator contient de l'aléatoire.

Ici j'ai ajouté un taboo et je ne met aucun defaultcode, la boite sera donc vide.

[pyBox
slug='absolute'
title="repeats + generator (quand il y a des input)"
generator="print(_rint(-100, 100))"
repeats=3
solver='print(abs(int(input())))
'
taboo="abs"
] Votre code doit lire (avec input) un nombre entier et afficher la valeur absolue de ce nombre.


CONTRAINTE : Vous ne devez pas utiliser la fonction abs() de python. [/pyBox]
Exercice de code : repeats + generator (quand il y a des input)
Votre code doit lire (avec input) un nombre entier et afficher la valeur absolue de ce nombre.

CONTRAINTE : Vous ne devez pas utiliser la fonction abs() de python.

Inconvénient : on ne maitrise pas les tests. Dans l'exemple ci-dessus, il faudrait tester avec un négatif, un positif et avec 0, mais générator ne me permet pas de le faire....

parfois ça peut quand même servir, si on a pas de cas particulier à tester. exemple :

[pyBox
slug='plus_grand'
generator="print(_rint(-100, 100))
print(_rint(-100, 100))"
repeats=3
solver='print( max( int(input()),int(input()) ) )
'
taboo='max'
] Votre code doit lire (avec input) 2 nombres entiers et afficher la valeur du plus grand.


CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python. [/pyBox]
Exercice de code
Votre code doit lire (avec input) 2 nombres entiers et afficher la valeur du plus grand.

CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python.

mais même ici, on ne teste pas le cas ou a = b. Si l'élève écrit :

a = int(input())
b = int(input())
if a>b :
   print(a)
if b>a :
   print(b)
dans le cas a = b le code ne produira rien, mais ce cas n'est pas testé et le correcteur dira que c'est correct...

IV. input au lieu de generator+repeats : Tests choisis, pas d'aléatoire

C'est assez similaire mais ici on défini les tests. Inconvénient, je n'arrive pas à mettre un test aléatoire dans ce cas...

[pyBox
slug=′plus_grand_2′
input1="1\n2"
input2="2\n2"
input3="3\n2"
solver='print( max( int(input()),int(input()) ) )
'
taboo='max'
] Votre code doit lire (avec input) 2 nombres entier et afficher la valeur du plus grand.


CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python. [/pyBox]
Exercice de code
Votre code doit lire (avec input) 2 nombres entier et afficher la valeur du plus grand.

CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python.

pyScramble

[pyScramble 
slug="scramble"
solver="a=1\nb=a+1\nc=b+1"
] Arrangez les lignes dans le bon ordre, pour que le code s'exécute sans erreur.[/pyScramble]

Exercice mêlé
Arrangez les lignes dans le bon ordre, pour que le code s'exécute sans erreur.
  • b=a+1
  • c=b+1
  • a=1

V. Des codes utilisant random

Ces codes posent un problème : il faut initialiser le générateur aléatoire dans le solver et dans le code élève de la même façon.

Prenons cet exemple, qui ne fonctionne pas bien :

[pyBox
slug="plus_grand_3"
title="exemple qui ne fonctionne pas…"
generator='print(_rint(3,8))'
repeats=3
solver='a = int(input())
b = _rint(0,10)
print("le plus grand de ",a,"et",b,"est", max(a,b) )
'
taboo='max'
] Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez aléatoirement entre 1 et 10.


CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python. [/pyBox]
Exercice de code : exemple qui ne fonctionne pas...
Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez aléatoirement entre 1 et 10.

CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python.

le code élève correct :

import random
a=int(input())
b = random.randint(0,10)
if a>= b:
   print(a)
else :
   print(b)
Ce code devrait donner la même chose que le solver (même si, dans le solver, je m'autorise _rint() et max() parce que je suis feignant, le taboo c'est seulement pour les élèves...)

En fait il faut initialiser le générateur aléatoire. J'ai tenté ceci : l'initialiser à un nombre fixe dans un précode écrit ainsi :

precode = "import random as _rd
_rd.seed(5)
"
ce qui donne ce pyBox :

[pyBox
slug="plus_grand_4"
title="exemple qui ne fonctionne toujours pas…"
precode = "import random as _rd
_rd.seed(5)
"
generator='print(_rint(3,8))'
repeats=1
solver='a = int(input())
b = _rint(0,10)
print("le plus grand de ",a,"et",b,"est", max(a,b) )
'
taboo='max'
] Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez alétoirement entre 1 et 10.


CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python. ][/pyBox]
Exercice de code : exemple qui ne fonctionne pas...
Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez alétoirement entre 1 et 10.

CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python.

D'une part, ça ne génère pas vraiment des tests aléatoires, les nombre générés sont toujours les mêmes à chaque exécution. Mais pire, les deux codes (solver et élève) n'obtiennent pas la même chose (il semble donc que precode n'est exécuté qu'une seule fois...)

Il faut donc se résoudre à faire le random.seed dans le code (dans le solver et dans le code élève). Ca perturbe les élèves et on perd du temps.

Depuis peu j'ai choisit de créer dans le précode une fonction d'initalisation :

precode = "import random as _rd
def _initialisation_exercice():
   _rd.seed(_codeInitRandom)
_codeInitRandom = _rint(3,10)
"
je génère un nombre aléatoire caché _codeInitRandom qui sera bien le même dans les deux codes. j'appelle dans les deux code la fonction initialisation_exercice() que je met dans le defaultcode évidement...

exemple :

[pyBox
slug="plus_grand_5"
title="et finalement, je contourne le problème"
precode = "import random as _rd
def _initialisation_exercice():
    _rd.seed(_codeInitRandom)

_codeInitRandom = _rint(3,10)
"
generator='print(_rint(3,8))'
repeats=3
solver='_rd.seed(_codeInitRandom)
a = int(input())
b = _rint(0,10)
print("le plus grand de ",a,"et",b,"est", max(a,b) )
'
defaultcode='#La ligne ci-dessous est requise pour la validation automatique, laissez là mais ignorez la
_initialisation_exercice()
import random
'
taboo='max'
] Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez alétoirement entre 1 et 10.


CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python. [/pyBox]
Exercice de code
Votre code doit lire (avec input) 1 nombres entier et afficher la valeur du plus grand entre ce nombre et un autre que vous générez alétoirement entre 1 et 10.

CONTRAINTE : Vous ne devez pas utiliser la fonction max() de python.

Notez bien que la fonction et le code d'initialisation sont cachés, cela évite des affichages inutiles lorsque l'élève exécute le code.

De même j'ai importé random as _rd. Le import random est donc indispable dans le code élève. (ici je l'ai mis dans le defaultcode mais je pourrais ne pas le mettre...)

SOS la boite ou même tout le collapsible ne s'affiche plus

La cause la plus fréquente est un problème de guillements.

Par exemple :

[pyBox
slug="bidon"
defaultcode="def ma_fct():
   """
   docstring
   """
   # faire afficher hello
"
solver="def ma_fct():
   """
   docstring
   """
   print('hello')
"]L'énoncé[/pyBox]
Exercice de code
L'enoncé

Dans ce cas vous pouvez avoir un message d'erreur, ou bien un affichage incomplet (dans l'exemple ci-dessus, le defaultcode ne s'affiche pas bien).

Mais testez. Remplacez le code par un code valide, par exemple mettez pass dans la fonction et exécutez.... vous obtenez une boite jaune avec ce message :

PyBox error: unknown option docstring
Il a voulu exécuter le solver, mais il ne l'a pas trouvé. Le default code c'est arrété aux " puis il a lu "" dont il ne fait rien, puis le mot docstring, qu'il ne comprend pas....

Pour éviter cela, il vaut mieux utiliser des ' plutot que " pour délimiter les codes, puis des " dans le code :

[pyBox
slug='bidon'
defaultcode = 'def ma_fct():
   """
   docstring
   """
   # faire afficher hello
'
solver = 'def ma_fct():
   """
   docstring
   """ 
   print("hello")
'
]L'enoncé[/pyBox]
Exercice de code
L'enoncé

Mais même ainsi il vous arrivera cela :

[pyBox
slug='bidon'
defaultcode = 'def ma_fct():
   """
   docstring
   """
   # faire afficher l'expression hello
'
solver = 'def ma_fct():
   """
   docstring
   """ 
   print("hello")
'
]L'enoncé[/pyBox]
je ne vous montre pas ce que ça donne car ça met un gros bordel.... Le [/pyBox] n'a pas été lu, et du coup votre boite pyBox reste ouverte jusqu'à ce qu'on rencontre un /pyBox.... qui se trouvera dans un autre exo et tout sera fusionné en une seule boite plus ou moins lisible (plutot moins que plus).

bref, vous n'y comprendrez rien, et c'est juste que vous avez oublié d'échapper l'apostrophe.

plus vicieux, l'oubli d'un <

[pyBox
slug="bidon2"
defaultcode="
"
solver="if 3 < 2:
   print(a)
"]
[/pyBox]
Exercice de code

la boite ne s'est purement et simplement pas affichée.... le comportement peut être variable mais il y aura forcément souci.

Rectifions :

[pyBox
slug="bidon2"
defaultcode="
"
solver="if 3 &lt; 2:
   print(a)
"]
[/pyBox]
Exercice de code

Les comportements peuvent varier suivant le contexte, l'oubli d'échappement d'une apostrophe peut impliquer la non lecture d'un [/collapsible] et du coup plus rien ne s'affiche, ou ne s'affiche pas dans le collapsible ou je ne sais quels effets les plus déroutants qui soient...

bref....

Quand ça ne marche pas regardez bien vos " et vos ', pensez aussi aux <, et sinon il reste la possibilité d'un code trop long, il y a une limite à chaque code et à la boite totale.

Deuxième partie : les pyHint pyWarn images latex etc...

pyHint

le pyHint peut figure dans le texte d'un exercice ou seul, dans une boite html personalisé comme un pyBox.

exemple si on met seul :

[pyHint hint="Aide"]le texte de l'aide [/pyHint]
Aide

et dans un pyBox :

[pyBox
slug='blabla'
solver='le code'
]L'enoncer de l'exercice.<br>
[pyHint hint="Aide"]le texte de l'aide [/pyHint]
[/pyBox]
Exercice de code
L'enoncer de l'exercice.
le texte de l'aide

pyWarn

[pyWarn]le texte du warning [/pyWarn]
le texte du warning

comme pyHint, pyWarn peut s'utiliser dans un pyBox.

images

Lorsque vous ajoutez un bloc image vous obtenez ceci :

vous pouvez televerser une image depuis votre ordi, elle sera visible et en même temps, ajoutée à la bibliothèque.

Vous pouvez aussi choisir une image de la bibliothèque, ou un lien vers une image.

Pour insérer une image dans un pyBox :

commencez par ajouter un bloc image, et mettez votre image. Puis convertissez ce bloc en html et copiez le code html, qui doit ressembler à ça :

<figure class="wp-block-image size-large">
<img src="https://cscircles.cemc.uwaterloo.ca/wp-content/uploads/img-CI.jpg" alt="" class="wp-image-15151"/>
</figure>
que vous collez dans l'énoncé de votre exercice. Vous supprimerez ensuite le bloc image.

latex

comme les pyWarn et pyHint le code latex peut être inséré dans l'énoncé d'un pyBox ou pyExample, ou dans un paragraphe.

[latex size=2]\sum\limits_{j=1}^k A_{\alpha_j}[/latex]
\sum\limits_{j=1}^k A_{\alpha_j}