Casse tête CE2

Bonsoir,

je viens de tomber sur ce problème
casse tête
Le titre de l'article est vraiment...

Je reproduis le problème ici:
Image-1024-1024-112469.jpg
il faut remplir les cases avec des chiffres de $1$ à $9$ sachant que chaque chiffre n'intervient qu'une seule fois.

J'ai fait un petit programme pour le résoudre, je trouve $20$ solutions dans le cas où chacune des deux divisions doit donner un résultat entier et $128$ solutions sinon.

Ce problème me parait vraiment dur au niveau CE2. D'ailleurs, à partir de quel niveau les élèves sont sensés être à l'aise avec la notion de nombre premier? Pensez vous que ce soit intéressant de le proposer à une de vos classes de collège (lycée)?

Je pense que je le proposerai à mes étudiants, à chaque fois qu'ils doivent écrire un programme ils ont une facheuse tendance à se jeter sur l'ordinateur pour l'écrire sans commencer par réfléchir au préalable.

enki.

Réponses

  • Bonjour,

    J'ai l'impression que le lien contient une contradiction dans l'article descriptif (au sujet des priorités de calculs) :

    On lit d'abord "...Le but est de remplir les cases vides de la grille avec des chiffres de 1 à 9 (qu’il ne faut utiliser qu’une fois chacun) en suivant l’ordre des opérations de façon à obtenir, comme résultat final, le nombre 66."

    Puis plus loin "...Et si vous releviez le défi ? Au préalable, n’oubliez pas que les multiplications et les divisions sont prioritaires..."

    Je pinaille ou ce n'est pas clair ?

    En tout cas c'est intéressant dans tous les niveaux, même post-bac.
    Merci bien pour cette énigme.

    Cordialement.
  • En effet, je me suis posé la question à la première lecture. Mais, celui qui a proposé cette énigme est un prof de math donc ça me parait clair que l'ordre de priorité des opération doit être respecté. Je pense que l'incertitude est certainement due à l'auteur de l'article.
  • Il a donné ça à des CE2. En CE2, les priorités opératoires... Au Viet-Nam, peut-être, mais en France, j'ai de très bons 6èmes qui les ignorent complètement (étant donné qu'on ne les voit qu'en 5ème).
  • J'aimerais bien voir le code du programme si possible ?
  • On peut imaginer un code brutal qui essaye toutes les combinaisons possibles et qui dit "oui" pour le resultat 66.
    9! = 362880 c'est long de nos jours où pas ?

    Faut qu'j'm'y r'mette...
  • @kioups: oui c'est à des CE2, j'ai lu un peu trop vite, je corrige mon premier message, d'ailleurs si un modérateur pouvait changer le titre de la discussion ce serait sympa. Du coup ça me semble encore moins faisable. L'ordre des priorités c'est vraiment le minimum pour se lancer dans ce genre de casse tête, je pense que pour le faire à la main il faut aussi connaitre la décomposition des eniers en nombres premier histoire de ne pas tester toutes les combinaisons.

    @Dom: c'est exactement ce que j'ai fait, un code brutal sans me poser (trop) de questions et pas du tout optimisé. Le temps d'execution est de moins de $10$ secondes sur mon pc qui n'est pas une bête de course.

    @enrouement: pas de problème, voici mon code qui est en matlab. J'ai renommé le fichier en .tex (à la place de .m) car sinon le forum ne l'accepte pas.
  • Ça me laisse penser que du coup il faut effectuer les calculs sans tenir compte des priorités...

    Bon, quelle que soit la règle, c'est pas simple.
  • Moins d'une demi-seconde en Python chez moi à l'instant.
    from itertools import permutations
    
    n=0
    
    for p in permutations([1,2,3,4,5,6,7,8,9]):	
    	c=p[0]+13*p[1]/p[2]+p[3]+12*p[4]-p[5]-11+p[6]*p[7]/p[8]-10
    	if c==66:
    		print(p)
    		n+=1
    print("nombre de solutions=",n)
    
    J'obtiens bien 128 solutions comme annoncés.
  • Il y a strictement plus de 128 solutions (je compte 136). Le test d'égalité à 66 de Baggins n'est pas le bon car le calcul qu'il effectue est un calcul en flottant (qui peut faire sortir des 66.000000001 ou des 65.999999999...).
  • Ah, merci ! Je venais de faire le programme sous Xcas et celui-ci me donnait 136 solutions et me demandais où était mon erreur.

    Du coup, Enki s'est aussi trompé.
  • A mon avis, il n'y a que 6 "vraies" solutions : les 6 pour lesquelles les deux divisions "tombent juste" (sont entières), puisque c'est un "problème CE2"...
  • Bien vu Nîmes-man, oui j'ai fait la même erreur. En corrigeant le test d'égalité je trouve bien 136 solutions également.

    Je pense aussi que c'est sous entendu que les divisions tombent juste.
  • J’en ai un beaucoup moins car je tue les calculs rationnels.
    #!/usr/bin/python                                                                                                                     
    # -*- coding: utf-8 -*-                                                                                                               
    
    from itertools import permutations                                                                                                    
    
    ch="%s+13*%s/%s+%s+12*%s-%s-11+%s*%s/%s-10"
    
    for liste in permutations(range(1,10)):
      if liste[1]%liste[2]!=0 or liste[6]*liste[7]%liste[8]!=0:
        continue
      calcul=eval(ch % liste)
      if calcul==66:
        print(ch % liste)
    

    Avec un module (ou une classe créée ad hoc), je devrais les trouver.
    Avec les fractions, j’ai 276 solutions.
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • Ah, oui, j'ai considéré la division prioritaire sur la multiplication, ce qui doit expliquer la différence (6 vs 20) avec enki.
  • Nicolas Patrois a écrit:
    Avec les fractions, j’ai 276 solutions.

    Que veux-tu dire par là ?
  • Avec une classe sur les fractions, j’ai ça :
    > ../algo/exovietnamien.py|wc -l                                                           
    276
    

    Il doit y avoir un bugue quelque part…
    Algebraic symbols are used when you do not know what you are talking about.
            -- Schnoebelen, Philippe
  • une sécance trouvable à la main : (5, 9, 3, 6, 2, 1, 7, 8, 4)

    on teste la suite 123456789 puis on permute le (9;4) et (2;6) pour avoir des divisions justes. On est trop grand, on permute le (5;2), trop petit, (6,9), on est tout près, (1;5) : bingo.
    Dans le journal à coté des mots croisés.
  • Joli, c'est sûrement une méthode semblable que conseille l'instit vietnamien à ses élèves.
    J'ai repris le code d'enki en c++, les puristes le trouveront sûrement à corriger un max.
    Ca trouve seulement 21 solutions, dont celle proposée par tâtonnement, en pj.

    Bonne soirée.
  • Avec un code très similaire à celui de nicolas.patrois, je n'ai trouvé que 20 solutions donnant des divisions qui tombent juste.
    On peut d'ailleurs diviser par 4 le nombre de solutions trouvées puisque la commutativité de l'addition et de la multiplication font que l'on peut toujours permuter le 1er nombre avec le 4ème ainsi que le 7ème avec le 8ème.
    On est ramené à 5 solutions distinctes :
    (3, 2, 1, 5, 4, 7, 8, 9, 6)
    (5, 3, 1, 7, 2, 6, 8, 9, 4)
    (5, 4, 1, 9, 2, 7, 3, 8, 6)
    (5, 9, 3, 6, 2, 1, 7, 8, 4)
    (6, 3, 1, 9, 2, 5, 7, 8, 4)

    Le code :
    import itertools
    
    def findall():
        solutions = []
        envisageables = 0
        for p in itertools.permutations(range(1,10)):
            if p[1] % p[2] == 0 and (p[6]*p[7]) % p[8] == 0 and p[0] < p[3] and p[6] < p[7]:
               envisageables += 1
               if p[0] + 13*p[1]//p[2] + p[3] + 12*p[4] - p[5] - 11 + p[6]*p[7]//p[8] - 10 == 66:
                   solutions.append(p)
        print("Nombre de permutations envisageables : 4 *", envisageables)
        print("Nombre de solutions distinctes (à permutation près) : ", len(solutions))
        return solutions
    
  • Intéressant,

    Et un programme sur TI82 Est-ce envisageable ?
    Je ne vois pas trop comment le programmer ?

    Bonne journée,


    gauss
  • Bonjour,

    Et voilà, c'était couru, honte sur moi : le compteur qui est incrémenté LA fois de trop, c'est pas la première fois que ça m'arrive, merci bisam, d'avoir corrigé.

    @+
    Denise
  • @gauss : sur TI-82 ? tu veux sans doute dire sur TI-82 stats.fr car la TI-82 a bientôt 30 ans !
    C'est faisable en théorie... mais difficile à mettre en oeuvre car il faut trouver un moyen d'énumérer les 9! permutations de l'ensemble {1,2,3,4,5,6,7,8,9}.
    On peut bien sûr le faire avec moults boucles et tests... mais c'est loin d'être une bonne méthode.

    De toute façon, même si on y arrive, le langage de cette calculette est bien trop lent pour énumérer toutes les possibilités en un temps raisonnable.

    Sur une TI89 titanium, c'est déjà plus envisageable car l'on peut créer des fonctions récursives bien plus facilement et car le processeur est plus rapide.
    Sur TI Nspire, cela passe sans problème.
  • Ok Bisam, c'est bien ce qu'il me semblait. Oui, sur TI82stats.fr.

    merci,

    gauss
  • 20 solutions si on tient compte de la priorité des opérateurs, 119 sans en tenir compte.

    Le programme scala utilisé, avec un type numérique en précision infinie :

      type NUM = BigDecimal
      val NUM = BigDecimal                            //> NUM  : math.BigDecimal.type = scala.math.BigDecimal$@52ed6f9
    
      def fctA(ds: List[NUM]) = {
        val List(a, b, c, d, e, f, g, h, i) = ds
        a + NUM(13) * b / c + d + NUM(12) * e - f - NUM(11) + g * h / i - NUM(10)
      }                                               //> fctA: (ds: List[Vietation.NUM])scala.math.BigDecimal
    
      def fctB(ds: List[NUM]) = {
        val List(a, b, c, d, e, f, g, h, i) = ds
        (((((((((((a + NUM(13)) * b) / c) + d) + NUM(12)) * e) - f) - NUM(11)) + g) * h) / i) - NUM(10)
      }                                               //> fctB: (ds: List[Vietation.NUM])scala.math.BigDecimal
    
      val digits = List(1, 2, 3, 4, 5, 6, 7, 8, 9).map(x => NUM(x))
                                                      //> digits  : List[scala.math.BigDecimal] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
    
      def isSolution(fct:List[NUM]=>NUM)(candidate:List[NUM]):Boolean = {
        val r = fct(candidate)
        r == 66 && r.scale == 0
      }                                               //> isSolution: (fct: List[Vietation.NUM] => Vietation.NUM)(candidate: List[Viet
                                                      //| ation.NUM])Boolean
      
      digits
        .permutations
        .filter(isSolution(fctA))
        .size                                         //> res0: Int = 20
    
    
      digits
        .permutations
        .filter(isSolution(fctB))
        .size                                         //> res1: Int = 119
    
Connectez-vous ou Inscrivez-vous pour répondre.