def inputs_curve(): return [ Args(1, 2), Args(1, 2, 5), Args(1, 1), Args(1, 5), Args(2, 1, 10), Args(2, 2), Args(2, 3, 10), Args(4, 4), ]
########## dataset #1 fact_inputs = [ (0, ), (1, ), (5, ), ] def broken_fact(n): return 0 if n <= 0 \ else 1 if n == 1 \ else n*fact(n-1) compare_args_inputs.append(Args(broken_fact, factorial, fact_inputs)) ########## dataset #2 # addition can work too add_inputs = [(2, 3), (0, 4), (4, 5)] def plus_broken(x1, x2): if x1 != 0: return x1 + x2 else: return 1 + x2 compare_args_inputs.append(Args(add, plus_broken, add_inputs))
def correction(self, student_index, bateaux=abbreviated): self.datasets = [Args(bateaux)] return ExerciseFunction.correction(self, student_index)
# @BEG@ name=agenda more=regexp # l'exercice est basé sur re.match, ce qui signifie que # le match est cherché au début de la chaine # MAIS il nous faut bien mettre \Z à la fin de notre regexp, # sinon par exemple avec la cinquième entrée le nom 'Du Pré' # sera reconnu partiellement comme simplement 'Du' # au lieu d'être rejeté à cause de l'espace # # du coup pensez à bien toujours définir # vos regexps avec des raw-strings # # remarquez sinon l'utilisation à la fin de :? pour signifier qu'on peut # mettre ou non un deuxième séparateur ':' # agenda = r"\A(?P<prenom>[-\w]*):(?P<nom>[-\w]+):?\Z" # @END@ agenda_groups = ['nom', 'prenom'] exo_agenda = ExerciseRegexpGroups( 'agenda', agenda, agenda_groups, [Args(x) for x in agenda_strings], nb_examples = 0) agenda_ko = r"\A(?P<prenom>[-\w]*):(?P<nom>[-\w]+):?"
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args def minimum(a, b): if a < b: mini = a else: mini = b return mini inputs_minimum = [ Args(3, 8), Args(7, 4), Args(1.264, 1.283), Args(-3, -1), Args(2, 2) ] exo_minimum = ExerciseFunction(minimum, inputs_minimum)
(45_001, 150_000, 40), (150_001, math.inf, 45), ) def taxes_ter(income): due = 0 for floor, ceiling, rate in TaxRate2: due += (min(income, ceiling) - floor + 1) * rate / 100 if income <= ceiling: return int(due) def taxes_ko(income): return (income - 11_500) * 20 / 100 taxes_values = [ 0, 45_000, 11_500, 5_000, 16_500, 30_000, 100_000, 150_000, 200_000, 11_504 ] taxes_inputs = [Args(v) for v in taxes_values] exo_taxes = ExerciseFunction(taxes, taxes_inputs, nb_examples=2) if __name__ == '__main__': for value in taxes_values: tax = taxes(value) print(f"{value} -> {tax}")
# enfin on extrait la racine avec math.sqrt return math.sqrt(sum([x**2 for x in args])) # @END@ # ceci est testé mais je préfère ne pas l'exposer dans les corriges pour l'instant def distance_bis(*args): "idem mais avec une expression génératrice" # on n'a pas encore vu cette forme - cf Semaine 6 # mais pour vous donner un avant-goût d'une expression # génératrice: return math.sqrt(sum((x**2 for x in args))) distance_inputs = [ Args(), Args(1), Args(1, 1), Args(1, 1, 1), Args(1, 1, 1, 1), Args(*range(10)), ] exo_distance = ExerciseFunction(distance, distance_inputs, nb_examples=3) def distance_ko(*args): return sum([x**2 for x in args])
def correction(self, student_diff, extended=extended, abbreviated=abbreviated): self.datasets = [Args(extended, abbreviated).clone('deep')] return ExerciseFunction.correction(self, student_diff)
compare_all_inputs = [] # factoriel from operator import mul def fact(n): "une version de factoriel à base de reduce" return reduce(mul, range(1, n + 1), 1) from math import factorial fact_inputs = [0, 1, 5] compare_all_inputs.append(Args(fact, factorial, fact_inputs)) def broken_fact(n): return 0 if n <= 0 \ else 1 if n == 1 \ else n*fact(n-1) compare_all_inputs.append(Args(broken_fact, factorial, fact_inputs)) #################### the exercice instance exo_compare_all = ExerciseFunction(compare_all, compare_all_inputs, nb_examples=2, call_layout='truncate',
# Fonctions intermédiaires de sélection des données à vérifier def verifier_donnees(fichier, index): liste = importer_donnees(fichier) return liste[index] def verifier_aver_ages(fichier, index): liste = importer_donnees(fichier) moyennes = ages_moyens(liste) return int(moyennes[index][2]) # Liste des cas de test inputs_import = [ Args('nat2018_epured_5k.csv', 1045), Args('nat2018_r300.csv', 24), Args('nat2018_n20.csv', 12960), Args('nat2018_epured_5k.csv', 386), Args('nat2018_epured_5k.csv', 85033), Args('nat2018_r300.csv', 1043), Args('nat2018_r300.csv', 2011), Args('nat2018_n20.csv', 30082) ] inputs_averages = [ Args('nat2018_epured_5k.csv', 1045), Args('nat2018_r300.csv', 24), Args('nat2018_n20.csv', 58), Args('nat2018_epured_5k.csv', 386), Args('nat2018_epured_5k.csv', 1136),
liste.sort(reverse=reverse) # on retourne la liste de départ return listes # @END@ def multi_tri_reverse_ko(listes, reverses): for liste in listes: liste.sort() return listes inputs_multi_tri_reverse = [ Args([[1, 2], [3, 4]], [True, False]), Args([[1, 2], [3, 4]], (True, True)), Args([[1, 3, 2], [3, 4]], [False, True]), Args([[1, 2], [3, 5, 4]], [False, False]), Args([[1, 3], [9, 5], [4, 2]], (True, False, True)), Args( [[], ['a', 'z', 'c']], [False, True], ), ] exo_multi_tri_reverse = ExerciseFunction(multi_tri_reverse, inputs_multi_tri_reverse, layout_args=(24, 24, 24), nb_examples=2)
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args def difference(a, b): resultat = b - a return resultat inputs_difference = [Args(3, 7), Args(6, 2), Args(4, 4), Args(-5, 1)] exo_difference = ExerciseFunction(difference, inputs_difference)
germs = ['aa1', 'A1a', '1Aa'] pythonid_strings = [ 'a', '_', '__', '-', ] + germs[:] for germ in germs: for i in range(len(germ)): for seed in '-_': pythonid_strings.append(germ[:i] + seed + germ[i:]) # @BEG@ name=pythonid more=regexp # un identificateur commence par une lettre ou un underscore # et peut être suivi par n'importe quel nombre de # lettre, chiffre ou underscore, ce qui se trouve être \w # si on ne se met pas en mode unicode pythonid = "[a-zA-Z_]\w*" # @END@ # @BEG@ name=pythonid more=bis # on peut aussi bien sûr l'écrire en clair pythonid_bis = "[a-zA-Z_][a-zA-Z0-9_]*" # @END@ exo_pythonid = ExerciseRegexp('pythonid', pythonid, [Args(x) for x in pythonid_strings], nb_examples=8) pythonid_ko = "\w+"
from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args def wc(string): """ Basic implementation of the wc(1) UNIX command. """ nb_line = string.count('\n') nb_word = len(string.split()) nb_byte = len(string) return nb_line, nb_word, nb_byte wc_input = ( Args('''Python is a programming language that lets you work quickly and integrate systems more effectively.'''), Args(''), Args('abc'), Args('abc \t'), Args(' \tabc \n'), Args('a b c d e f g h i j k l m n o p q r s t u v w x y z\n'), Args('''The Zen of Python, by Tim Peters Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules.
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args # @BEG@ name=npmodif def npmodif(n, a, b): '''on va créer une arange(n) et transformer en leurs opposés les termes d'indices compris entre a et b. La fonction retourne le tableau np modifié''' import numpy as np Z = np.arange(n) Z[(a < Z) & (Z <= b)] *= -1 return list(Z) # @END@ inputs_npmodif = [ Args(10, 3, 5), Args(10, 2, 8), Args(5, 1, 3), Args(15, 10, 14), ] exo_npmodif = ExerciseFunction(npmodif, inputs_npmodif)
# @BEG@ name=divisible more=bis def divisible_bis(a, b): "renvoie True si un des deux arguments divise l'autre" # on n'a pas encore vu les opérateurs logiques, mais # on peut aussi faire tout simplement comme ça # sans faire de if du tout return a % b == 0 or b % a == 0 # @END@ def divisible_ko(a, b): return a % b == 0 inputs_divisible = [ Args(10, 30), Args(10, -30), Args(-10, 30), Args(-10, -30), Args(8, 12), Args(12, -8), Args(-12, 8), Args(-12, -8), Args(10, 1), Args(30, 10), Args(30, -10), Args(-30, 10), Args(-30, -10), ] exo_divisible = ExerciseFunction(
""" # Je vous laisse vous convaincre que ça fonctionne aussi # en utilisant le broadcasting # pour s'économiser une transposition explicite return (lambda x: x + x[:, np.newaxis])(taille - np.abs(range(-taille, taille + 1))) # @END@ def stairs_ko(taille): n = 2 * taille + 1 ix, iy = np.indices((n, n), dtype=np.float) return ((taille - 1) + 2 * taille - (np.abs(ix - taille) + np.abs(iy - taille))) stairs_inputs = [ Args(1), Args(2), Args(3), Args(4), ] exo_stairs = ExerciseFunctionNumpy( stairs, stairs_inputs, nb_examples=2, )
# @END@ def numbers_ko(liste): return ( # la builtin 'sum' renvoie la somme sum(liste), # les builtin 'min' et 'max' font ce qu'on veut aussi max(liste), min(liste), ) def numbers_input(): length = randint(2, 6) result = [] for i in range(length): result.append(randint(5, 15)) return result numbers_inputs = [Args(), Args(6)] + [Args(*numbers_input()) for i in range(4)] exo_numbers = ExerciseFunction( numbers, numbers_inputs, layout_args=(30, 25, 25), nb_examples=3, )
from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args from math import sqrt #------------ # Fonction solution du probleme def __estPair(n): return n % 2 == 0 # Jeu de donnees sur lequel la fonction de l'eleve sera testee inputs_estPair = [Args(1), Args(2), Args(3), Args(8), Args(17), Args(1001)] # Fabrication de l'instance pour l'autoevaluation sol_estPair = ExerciseFunction( __estPair, # La fonction solution du probleme inputs_estPair, # Le jeu de donnees ) #------------ # Fonction solution du probleme def __carre(x): return x**2 # Jeu de donnees sur lequel la fonction de l'eleve sera testee
# @BEG@ name=carre more=bis def carre_bis(line): # pareil mais avec, à la place des compréhensions # des expressions génératrices que - rassurez-vous - # l'on n'a pas vues encore, on en parlera en semaine 5 # le point que je veux illustrer ici c'est que c'est # exactement le même code mais avec () au lieu de [] line = line.replace(' ', '').replace('\t', '') entiers = (int(token) for token in line.split(";") if token) return ":".join(str(entier**2) for entier in entiers) # @END@ inputs_carre = [ Args("1;2;3"), Args(" 2 ; 5;6;"), Args("; 12 ; -23;\t60; 1\t"), Args("; -12 ; ; -23; 1 ;;\t"), ] exo_carre = ExerciseFunction(carre, inputs_carre, nb_examples=0, layout_args=(40, 20, 20)) def carre_ko(s): return ":".join(str(i**2) for i in (int(token) for token in s.split(';')))
# for i in range(len(iterable)): # ... iterable[i] def produit_scalaire_ter(X, Y): scalaire = 0 n = len(X) for i in range(n): scalaire += X[i] * Y[i] return scalaire # @END@ from fractions import Fraction inputs_produit_scalaire = [ Args((1, 2), (3, 4)), Args(range(3, 9), range(5, 11)), Args([-2, 10], [20, 4]), Args([Fraction(2, 15), Fraction(3, 4)], [Fraction(-7, 19), Fraction(4, 13)]), Args([], []), ] exo_produit_scalaire = ExerciseFunction( produit_scalaire, inputs_produit_scalaire, ) def produit_scalaire_ko(X, Y): return [x * y for x, y in zip(X, Y)]
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args inputs_dispatch1 = [Args(a, b) for a in range(3, 6) for b in range(7, 10)] # @BEG@ name=dispatch1 def dispatch1(a, b): """ dispatch1 comme spécifié """ # si les deux arguments sont pairs if a % 2 == 0 and b % 2 == 0: return a * a + b * b # si a est pair et b est impair elif a % 2 == 0 and b % 2 != 0: return a * (b - 1) # si a est impair et b est pair elif a % 2 != 0 and b % 2 == 0: return (a - 1) * b # sinon - c'est que a et b sont impairs else: return a * a - b * b # @END@ def dispatch1_ko(a, b, *args): return a * a + b * b
C'est plus court, mais on passe du temps à se convaincre que ça fonctionne bien comme demandé """ # si on n'aime pas les boucles sans fin # on peut faire aussi comme ceci while b: a, b = b, a % b return a # @END@ def pgcd_ko(a, b): return a % b inputs_pgcd = [ Args(0, 0), Args(0, 1), Args(1, 0), Args(15, 10), Args(10, 15), Args(3, 10), Args(10, 3), Args(10, 1), Args(1, 10), ] inputs_pgcd += [ Args(36 * 2**i * 3**j * 5**k, 36 * 2**j * 3**k * 5**i) for i in range(3) for j in range(3) for k in range(2) ]
# @END@ # @BEG@ name=morceaux more=ter # on peut aussi faire des tests d'intervalle # comme ceci 0 <= x <= 10 def morceaux_ter(x): if x <= -5: return -x - 5 elif -5 <= x <= 5: return 0 else: return x / 5 - 1 # @END@ inputs_morceaux = [Args(x) for x in (-10, 0, 10, -6, -5, -4, 4, 5, 20)] exo_morceaux = ExerciseFunction( morceaux, inputs_morceaux, nb_examples=3, ) def morceaux_ko(x): return morceaux(x) if x <= 15 else x
encore """ # à la Fortran; ça n'est pas forcément # la bonne approche ici bien sûr # mais si un élève a des envies de benchmarking... result = np.zeros(shape=(lines, columns), dtype=int) for i in range(lines): for j in range(columns): result[i, j] = 100 * i + 10 * j + offset return result # @END@ def hundreds_ko(lines, columns, offset): result = np.ones(shape=(lines, columns), dtype=float) return result hundreds_inputs = [ Args(2, 4, 0), Args(3, 3, 1), ] exo_hundreds = ExerciseFunctionNumpy( hundreds, hundreds_inputs, nb_examples=2, )
# @END@ # @BEG@ name=url more=bis # merci à sizeof qui a pointé l'utilisation de re.X # https://docs.python.org/fr/3/library/re.html#re.X # ce qui donne une présentation beaucoup plus compacte protos_list = ['http', 'https', 'ftp', 'ssh', ] url_bis = rf"""(?x) # verbose mode (?i) # ignore case (?P<proto>{"|".join(protos_list)}) # http|https|... :// # separator ((?P<user>\w+){password}@)? # optional user/password (?P<hostname>[\w\.]+) # mandatory hostname (:(?P<port>\d+))? # optional port /(?P<path>.*) # mandatory path """ # @END@ groups = [ 'proto', 'user', 'password', 'hostname', 'port', 'path' ] exo_url = ExerciseRegexpGroups( 'url', url, groups, [Args(x) for x in url_strings], nb_examples=0, font_size='x-small', header_font_size='small', ) url_ko = i_flag + protos + "://" + hostname + '/' + path
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args def seuilSomme(seuil): m = 150 n = 0 while m <= seuil: m = m + 3 n = n + 1 return n inputs_seuilSomme = [Args(1000), Args(2000), Args(150), Args(3000)] exo_seuilSomme = ExerciseFunction(seuilSomme, inputs_seuilSomme) def seuilProduit(seuil): m = 150 n = 0 while m <= seuil: m = m * 2 n = n + 1 return n inputs_seuilProduit = [Args(7000), Args(100000), Args(150), Args(4800)] exo_seuilProduit = ExerciseFunction(seuilProduit, inputs_seuilProduit)
# -*- coding: utf-8 -*- from nbautoeval.exercise_function import ExerciseFunction from nbautoeval.args import Args from math import sqrt def isPrime(n): if n==2 or n==3: return True if n%2 == 0 or n<=1: return False d=3 while n%d!=0 and d <= sqrt(n): d+=2 return n%d!=0 inputs_isPrime = [ Args(1), Args(2), Args(3), Args(5), Args(17), Args(1001) ] exo_isPrime = ExerciseFunction( isPrime, inputs_isPrime, layout='pprint', layout_args=(40, 25, 25), )
def correction(self, student_merge, extended=extended, abbreviated=abbreviated): self.datasets = [Args(extended, abbreviated)] return ExerciseFunction.correction(self, student_merge)
if sum(sample) == target: matches += 1 return matches # @END@ def dice_ko(target, nb_dice=2, sides=6): return sides**(nb_dice - 1) SIDES = 5 dice_inputs = [ Args(7), Args(2), Args(20, sides=10), Args(3, nb_dice=3), Args(4, nb_dice=3), Args(50, nb_dice=8), ] + [ Args(target, sides=SIDES, nb_dice=3) for target in range(3, 3 * SIDES + 1) ] exo_dice = ExerciseFunctionNumpy( dice, dice_inputs, nb_examples=5, layout_args=(50, 10, 10), )