Valeurs aléatoires AMC

Bonjour,
je voulais savoir si l'on pouvait générer des valeurs aléatoires dans AMC, lorsqu'on ne passe pas par Latex pour éditer les sujets, mais qu'on utilise TextEdit.
J'obtiens des valeurs aléatoires, mais identiques d'un sujet à l'autre en insérant dans le préambule les commandes de la doc.
Merci pour votre aide.

Réponses

  • Même avec TextEdit, quand tu compiles, c'est LaTeX qui travaille, n'est-ce pas ?
  • Dans la documentation, l'utilisation des valeurs aléatoires est décrite dans la section 5 (source au format Latex). J'imaginais que le problème pouvait venir de là.
  • Concrètement, comment puis-je faire pour générer des nombres "aléatoires" qui soient différents d'un sujet à l'autre ?
  • Bonjour,

    Quel genre de nombre ? Entier ? Décimal entre 0 et 1 ?.. \usepackage{xfp} fonctionne-t-il dans AMC ?
    \documentclass{article}
    \usepackage{xfp}
    
    \begin{document}
    
    \fpeval{randint(1, 20)}
    
    \fpeval{rand()}
    
    \end{document}
    
    112302
  • Merci. En fait, j'aurais aimé à terme pouvoir incorporer dans mes QCM des exercices sur les sommes ou produits de fractions (par exemple) avec des fractions distinctes d'un sujet à un autre. Avec en plus la possibilité d'obtenir la forme irréductible.
    En incorporant le code de la doc AMC directement dans l'exercice en question, cela fonctionne.
    \FPeval\VQa{trunc(1+random*8,0)}
    \FPeval\VQb{trunc(4+random*5,0)}
    \FPeval\VQsomme{clip(VQa+VQb)}
    \FPeval\VQnonA{clip(VQa+VQb-1)}
    \FPeval\VQnonB{clip(VQa*VQb)}
    \FPeval\VQnonC{clip(VQa-VQb)}
    
  • Pour les opérations de base sur les fractions, on peut programmer un peu de « calcul formel » :
    \documentclass{article}
    \usepackage{xparse}             % Pas nécessaire avec LaTeX >= 2020-10-01
    \usepackage{xfp}                % Juste pour l'exemple avec \fpeval
    \usepackage{siunitx}
    \sisetup{
      output-decimal-marker = {,},  % virgule comme séparateur décimal
      group-minimum-digits = 4,     % groupes de trois chiffres
    }
    % Pour que les cellules soient assez hautes dans le tableau de l'exemple :
    \usepackage[column=O]{cellspace}
    \setlength{\cellspacetoplimit}{4pt}
    \setlength{\cellspacebottomlimit}{4pt}
    
    \ExplSyntaxOn
    \int_new:N \l__raskol_numerateur_int
    \int_new:N \l__raskol_denominateur_int
    \int_new:N \l__raskol_pgcd_num_denom_int
    \int_new:N \l__raskol_tmpa_int
    \int_new:N \l__raskol_tmpb_int
    \int_new:N \l__raskol_tmpc_int
    \int_new:N \l__raskol_tmpd_int
    
    \cs_new_protected:Npn \__raskol_ecrit_fraction_ou_entier:nn #1#2
      {
        \int_set:Nn \l__raskol_tmpa_int {#1} % on stocke résultat pour économiser CPU
        \int_set:Nn \l__raskol_tmpb_int {#2}
        % Signe moins devant la fraction, si besoin
        \int_compare:nNnT
          { \int_sign:n { \l__raskol_tmpa_int * \l__raskol_tmpb_int } } = { -1 }
          { - }
        \int_compare:nNnTF { \int_abs:n { \l__raskol_tmpb_int } } = { 1 }
          { \num { \int_abs:n { \l__raskol_tmpa_int } } } % juste le numérateur
          {
            \frac { \num { \int_abs:n { \l__raskol_tmpa_int } } }
                  { \num { \int_abs:n { \l__raskol_tmpb_int } } }
          }
      }
    
    \cs_new_protected:Npn \__raskol_operation_fractions:nnnnnnn #1#2#3#4#5#6#7
      {
        \cs_set:Npn \__raskol_expr_formatage:nnnn ##1##2##3##4 {#1}
        \cs_set:Npn \__raskol_calcul_numerateur:nnnn ##1##2##3##4 {#2}
        \cs_set:Npn \__raskol_calcul_denominateur:nnnn ##1##2##3##4 {#3}
    
        \int_set:Nn \l__raskol_numerateur_int
          { \__raskol_calcul_numerateur:nnnn {#4} {#5} {#6} {#7} }
        \int_set:Nn \l__raskol_denominateur_int
          { \__raskol_calcul_denominateur:nnnn {#4} {#5} {#6} {#7} }
        \int_set:Nn \l__raskol_pgcd_num_denom_int
          {
            \raskol_pgcd:nn
              { \l__raskol_numerateur_int }
              { \l__raskol_denominateur_int }
          }
    
        % L'égalité
        \__raskol_expr_formatage:nnnn {#4} {#5} {#6} {#7}
        =
        \__raskol_ecrit_fraction_ou_entier:nn
          { \l__raskol_numerateur_int   / \l__raskol_pgcd_num_denom_int }
          { \l__raskol_denominateur_int / \l__raskol_pgcd_num_denom_int }
      }
    
    \cs_generate_variant:Nn \__raskol_operation_fractions:nnnnnnn { o }
    
    \cs_new:Npn \__raskol_formatage_operation_simple:n #1
      { \frac{ \num{##1} } { \num{##2} } #1 \frac{ \num{##3} } { \num{##4} } }
    
    \cs_new_protected:Npn \raskol_somme_frac:nnnn #1#2#3#4
      {
        % 1 “expansion step” sur le premier argument
        \__raskol_operation_fractions:onnnnnn
          { \__raskol_formatage_operation_simple:n { + } }
          { (##1)*(##4) + (##2)*(##3) } % ad + bc
          { (##2)*(##4) }               % bd
          {#1} {#2} {#3} {#4}
      }
    
    \cs_new_protected:Npn \raskol_difference_frac:nnnn #1#2#3#4
      {
        \__raskol_operation_fractions:onnnnnn
          { \__raskol_formatage_operation_simple:n { - } }
          { (##1)*(##4) - (##2)*(##3) } % ad - bc
          { (##2)*(##4) }               % bd
          {#1} {#2} {#3} {#4}
      }
    
    \cs_new_protected:Npn \raskol_produit_frac:nnnn #1#2#3#4
      {
        \__raskol_operation_fractions:onnnnnn
          { \__raskol_formatage_operation_simple:n { \times } }
          { (##1)*(##3) }           % ac
          { (##2)*(##4) }           % bd
          {#1} {#2} {#3} {#4}
      }
    
    \cs_new_protected:Npn \raskol_quotient_frac:nnnn #1#2#3#4
      {
        \__raskol_operation_fractions:nnnnnnn
          {
            \frac { \frac{ \num{##1} } { \num{##2} } }
                  { \frac{ \num{##3} } { \num{##4} } }
          }
          { (##1)*(##4) }           % ad
          { (##2)*(##3) }           % bc
          {#1} {#2} {#3} {#4}
      }
    
    \cs_generate_variant:Nn \raskol_somme_frac:nnnn      { VVVV }
    \cs_generate_variant:Nn \raskol_difference_frac:nnnn { VVVV }
    \cs_generate_variant:Nn \raskol_produit_frac:nnnn    { VVVV }
    \cs_generate_variant:Nn \raskol_quotient_frac:nnnn   { VVVV }
    
    \cs_new_eq:NN \somme      \raskol_somme_frac:nnnn
    \cs_new_eq:NN \difference \raskol_difference_frac:nnnn
    \cs_new_eq:NN \produit    \raskol_produit_frac:nnnn
    \cs_new_eq:NN \quotient   \raskol_quotient_frac:nnnn
    
    % #3, #4 : (min, max) pour les numérateurs
    % #5, #6 : (min, max) pour les dénominateurs
    \cs_new_protected:Npn \__raskol_rand_simple_op:Nnnnnn #1#2#3#4#5#6
      {
        \int_set:Nn \l__raskol_tmpa_int { \int_rand:nn {#3} {#4} }
    
        \bool_do_until:nn
          { ! \int_compare_p:nNn { \l__raskol_tmpb_int } = { 0 } }
          { \int_set:Nn \l__raskol_tmpb_int { \int_rand:nn {#5} {#6} } }
    
        % Si l'expression booléenne #2 est vraie , on fait en sorte que
        % \l__raskol_tmpc_int (numérateur 2e fraction) soit non nul.
        \bool_if:nTF {#2}
          {
            \bool_do_until:nn
              { ! \int_compare_p:nNn { \l__raskol_tmpc_int } = { 0 } }
              { \int_set:Nn \l__raskol_tmpc_int { \int_rand:nn {#3} {#4} } }
          }
          { \int_set:Nn \l__raskol_tmpc_int { \int_rand:nn {#3} {#4} } }
    
        \bool_do_until:nn
          { ! \int_compare_p:nNn { \l__raskol_tmpd_int } = { 0 } }
          { \int_set:Nn \l__raskol_tmpd_int { \int_rand:nn {#5} {#6} } }
    
        % Appel de la macro #1 avec les quatre entiers pseudo-aléatoires calculés
        #1 \l__raskol_tmpa_int \l__raskol_tmpb_int \l__raskol_tmpc_int
           \l__raskol_tmpd_int
      }
    
    \cs_generate_variant:Nn \__raskol_rand_simple_op:Nnnnnn { c }
    
    \clist_map_inline:nn {somme, difference, produit}
      {
        \cs_new_protected:cpn { raskol_rand_#1_frac:nnnn } ##1##2##3##4
          {
            \__raskol_rand_simple_op:cnnnnn { raskol_#1_frac:VVVV }
              % Le numérateur de la deuxième fraction a le droit d'être nul.
              { \c_false_bool }
              {##1} {##2} {##3} {##4}
          }
      }
    
    \cs_new_protected:Npn \raskol_rand_quotient_frac:nnnn #1#2#3#4
      {
        \__raskol_rand_simple_op:Nnnnnn \raskol_quotient_frac:VVVV
          % Le numérateur de la deuxième fraction n'a pas le droit d'être nul.
          { \c_true_bool }
          {#1} {#2} {#3} {#4}
      }
    
    \cs_new_eq:NN \randsomme      \raskol_rand_somme_frac:nnnn
    \cs_new_eq:NN \randdifference \raskol_rand_difference_frac:nnnn
    \cs_new_eq:NN \randproduit    \raskol_rand_produit_frac:nnnn
    \cs_new_eq:NN \randquotient   \raskol_rand_quotient_frac:nnnn
    
    % Code d'egreg <https://tex.stackexchange.com/a/529914/73317> un peu amélioré :
    \cs_new:Npn \raskol_pgcd:nn #1#2
      {
        \int_compare:nNnTF {#1} < {#2}
          { \__raskol_pgcd_recurs:nn {#1} {#2} }
          { \__raskol_pgcd_recurs:nn {#2} {#1} }
      }
    
    \cs_new:Npn \__raskol_pgcd_recurs:nn #1#2
      {
        \int_compare:nNnTF {#1} = { 0 }
          {#2}
          { \__raskol_pgcd_recurs:fn { \int_mod:nn {#2} {#1} } {#1} }
      }
    
    \cs_generate_variant:Nn \__raskol_pgcd_recurs:nn { f }
    \ExplSyntaxOff
    
    \begin{document}
    
    $\somme{2}{3}{4}{5}$\qquad $\randdifference{-10}{10}{-10}{10}$\qquad
    $\randproduit{-10}{10}{-5}{5}$, etc.
    \[
      \begin{array}{@{} *{3}{>{$}Ol<{$} @{\hspace{2em}}} >{$}Ol<{$} @{}}
        \somme{8}{20}{10}{7}                   &
        \difference{2}{3}{10}{3}               &
        \difference{2}{3}{11}{3}               &
        \difference{\fpeval{2*7-3}}{3}{4}{6}   \\
        \randsomme{-10}{10}{-5}{5}             &
        \randsomme{-10}{10}{-5}{5}             &
        \randsomme{-10}{10}{-5}{5}             &
        \randdifference{-10}{10}{-5}{5}        \\
        \randproduit{-10}{10}{-5}{5}           &
        \randproduit{-10}{10}{-5}{5}           &
        \randquotient{-10}{10}{-8}{8}          &
        \randquotient{-3000}{3000}{-5}{5}
      \end{array}
    \]
    
    \end{document}
    
    Edit : algorithme de calcul du PGCD plus efficace.112314
  • Merci beaucoup.
  • De rien. Je viens d'enlever deux petits trucs qui ne servaient à rien mais ne peux pas retester pour le moment (téléphone). Edit : c'est bon.
  • J'ai amélioré l'algorithme de calcul du PGCD : celui d'egreg ne calculait pas le modulo assez tôt, ce qui le rendait peu efficace avec des nombres « un peu grands ».
  • Encore merci pour tout ce travail.
Connectez-vous ou Inscrivez-vous pour répondre.