Partage
  • Partager sur Facebook
  • Partager sur Twitter

Défi TURING

Problème 110

Sujet résolu
    18 juin 2024 à 11:18:23

    Bonjour.

    Je cherche à résoudre le problème n°110 du défi TURING.

    J'ai bien trouvé une réponse qui valide le calcul de la probabilité (0.5) et le nombre de boules total supérieur à 10 milliards mais celle-ci n'est pas validée.

    Voici le code (d'après les deux exemples donnés dans l'énoncé, j'ai estimé le nombre de boules bleues de départ à la racine carrée de 0.5 multipliée par le nombre total de boules) :

    def proba(nb_total, nb_bleues):
        return (nb_bleues / nb_total) * ((nb_bleues - 1) / (nb_total - 1))
    
    
    nb_total = int(10 * 10**9)
    nb_bleues = int(round(nb_total * 0.5 ** (1 / 2)))
    P = proba(nb_total, nb_bleues)
    
    while not P == 0.5:
    
        if P < 0.5:
            nb_bleues += 1
        else:
            nb_total += 1
            nb_bleues = int(round(nb_total * 0.5 ** (1 / 2)))
    
        P = proba(nb_total, nb_bleues)
    
    
    print(f"La réponse est {nb_bleues} (Total = {nb_total}).")

    En sortie, j'ai la réponse suivante :

    La réponse est 7073354024 (Total = 10003233192).

    Je dois dire que je sèche sur le truc qui cloche dans mon raisonnement. je m'en remets donc à vous pour m'aiguiller vers le bon chemin !!!

    -
    Edité par PB68 18 juin 2024 à 11:19:51

    • Partager sur Facebook
    • Partager sur Twitter

    PB68

      18 juin 2024 à 14:23:46

      Bonjour,

      Je vois déjà un problème qu'il faudra régler et c'est la précision des calculs et la manière dont vous comparez P à la valeur 0,5

      Il faudrait appliquer une tolérance

      while not abs(P - 0.5) < tolerance:

      sinon la condition de la boucle while peut ne jamais être satisfaite en raison des approximations avec les flottants.

      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        18 juin 2024 à 16:54:12

        fred1599 a écrit:

        Bonjour,

        Je vois déjà un problème qu'il faudra régler et c'est la précision des calculs et la manière dont vous comparez P à la valeur 0,5

        Il faudrait appliquer une tolérance

        while not abs(P - 0.5) < tolerance:

        sinon la condition de la boucle while peut ne jamais être satisfaite en raison des approximations avec les flottants.


        Après ma petite recherche sur la comparaison de 2 nombres "float", je suis tombé sur "isclose" du module "math", mon code devient donc :

        from math import isclose
        
        
        def proba(nb_total, nb_bleues):
            return (nb_bleues / nb_total) * ((nb_bleues - 1) / (nb_total - 1))
        
        
        nb_total = int(10 * 10**9) + 1
        nb_bleues = int(nb_total * 0.5 ** (1 / 2))
        P = proba(nb_total, nb_bleues)
        
        while not isclose(abs(P - 0.5), 0):
        
            if P < 0.5:
                nb_bleues += 1
            else:
                nb_total += 1
                nb_bleues = int(nb_total * 0.5 ** (1 / 2))
        
            P = proba(nb_total, nb_bleues)
        
        
        print(f"La réponse est {nb_bleues} (Total = {nb_total}).")

        Pas de mystère, j'arrive sur le même résultat final qui ne correspond pas à la réponse souhaitée.

        -
        Edité par PB68 18 juin 2024 à 16:54:51

        • Partager sur Facebook
        • Partager sur Twitter

        PB68

          18 juin 2024 à 17:11:52

          j'aurai plutôt mis

          while not math.isclose(P, 0.5):

          je pense que le paramètre abs_tol permet d'éviter la fonction abs.

          else:
              nb_total += 1
              nb_bleues = int(nb_total * 0.5 ** (1 / 2))
          

          Là j'aurai plutôt mis

          else:
              nb_bleues -= 1

          pour diminuer la probabilité, mais comme je suis une bille dans ce genre d'exercices, je préfère pas m'avancer.

          • Partager sur Facebook
          • Partager sur Twitter

          Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
          La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

            18 juin 2024 à 19:29:07

            Je n'ai pas encore fait cet exercice précis.

            Qu'est-ce que ça donnerait si tu ramenait tout à une fraction simple.

            Dans l'exemple, on donne 15/21 * 14 / 20 = 210 / 420.

            Il faut que le dénominateur soit le double du numérateur.

            Bien sûr, les nombres sont très grands dans ce cas.

            -
            Si on a  (bleu * (bleu-1)) / (total * (total-1)) = 1 / 2
            2 * bleu * (bleu-1) = total * (total-1)
            2 * bleu*bleu - 2 * bleu - total * (total-1) = 0
            Équation du second degré:
            Il faut trouver total tel que  2*total*total-1) + 1  soit un carré.
            J'en suis là ...

            -
            Edité par PierrotLeFou 19 juin 2024 à 1:25:39

            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              19 juin 2024 à 10:40:26

              Bonjour,

              Oui, c'est bien une équation du 2nd degré:

              soit x le nombre de boules bleues et k =10 milliards

              La probabilité est:

              (x / k) * (x-1 / k-1) = 0.5

              Ce qui peut se ramener à :

              x^2 - x - 0.5*k^2 + 0.5 * k = 0

              donc les coefficients a,b,c de l'équation sont:

              a=1

              b=-1

              c= 0.5*k^2 + 0.5 * k  qui est bien une constante car on connait sa valeur

              • Partager sur Facebook
              • Partager sur Twitter
                19 juin 2024 à 13:28:44

                je pense que la condition voulue est 0.5 exactement, on peut réécrire cette condition comme b*(b-1)*2=t*(t-1) (b étant le nombre de boules bleues et t le nombre de totale de boules)

                En comparant ces 2 termes, on s'affranchirait des problèmes liés aux flottants résultant de la division.

                • Partager sur Facebook
                • Partager sur Twitter
                  19 juin 2024 à 16:05:41

                  L'expression  n*(n-1)  est le double de la somme des nombres de 1 à n-1.

                  Je pense néanmoins que ce n'est pas la bonne approche. Voici ce que j'ai fait:

                  -


                  from time import perf_counter
                  begin = perf_counter()
                  t = 10**10
                  b = int(((2*t*(t-1))**0.5-1)/2)
                  st = t*(t+1) // 2
                  sb = b*(b+1) // 2
                  while True:
                      ds = 2*sb - st
                      if abs(ds) < 5: break
                      elif ds < 0:
                          b += 1
                          sb += b
                      else:
                          t += 1
                          st += t
                  print(round(perf_counter() - begin, 3), "secondes")
                  print(b)
                  print(t)
                  print(2*sb-st)
                  """ Ce qui donne:
                  962.326 secondes
                  8301239105
                  11739724927
                  2
                  """

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Le Tout est souvent plus grand que la somme de ses parties.

                    19 juin 2024 à 16:43:09

                    n'oubliez pas que vous pouvez tester avec les 2 exemples de l'énoncé du défi (en partant par exemple avec un total initiale de 10 puis de 30)
                    • Partager sur Facebook
                    • Partager sur Twitter
                      19 juin 2024 à 17:28:27

                      En tous cas, mon équation du 2nd degré fonctionne

                      Exemple avec 15 bleues + 6 rouges = 21

                      x**2 - x - (0.5*(21**2) - 0.5*21)

                      15**2 - 15 -210 = 0

                      Le code ci-dessous donne un total de 7071080646 boules bleues pour

                      plus de 10 milliards de boules au total:

                      x, total = 0.99, 10**10
                      while(x-int(x) != 0):
                          total += 1
                          a, b, c = 1, -1, -(0.5*total**2 - 0.5*total)
                          delta = b**2 - 4*a*c
                          x = (-b+sqrt(delta))/(2*a)
                      
                      print('{} boules bleues {} boules rouges'.format(int(x), int(total)-int(x)))



                      -
                      Edité par Phil_1857 19 juin 2024 à 17:59:39

                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 juin 2024 à 18:29:25

                        Désolé Phil_1857, je viens de tester et le site refuse ta réponse. :)

                        Ça ne respecte pas le fait que 2 * bleu * (bleu-1) == total * (total-1)

                        Il paraît que le site ne fait pas d'erreur ...

                        -
                        Edité par PierrotLeFou 19 juin 2024 à 18:56:54

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Le Tout est souvent plus grand que la somme de ses parties.

                          19 juin 2024 à 19:16:59

                          en rajoutant le test au code de Phil

                          from math import sqrt
                          x, total = 0.99, 10**10
                          while(x-int(x) != 0):
                              total += 1
                              a, b, c = 1, -1, -0.5*total*(total-1)
                              delta = b**2 - 4*a*c
                              if delta >=0:
                                  x = (-b+sqrt(delta))/(2*a)
                                  if 2*x*(x-1)==total*(total-1):
                                      break
                          print('{} boules bleues {} boules rouges {} total'.format(int(x), int(total)-int(x),total))
                          

                          j'obtiens 
                          7071072880 boules bleues 2928934288 boules rouges 10000007168 total
                          Edit: je dois être passer à côté d'un truc en fait, ce n'est pas bon non plus

                          -
                          Edité par umfred 19 juin 2024 à 19:36:13

                          • Partager sur Facebook
                          • Partager sur Twitter
                            20 juin 2024 à 10:12:03

                            Bonjour Pierrot,

                            Si tu initialises total à 10**10 tu obtiens:

                            7071080646 boules bleues + 2928937504 boules rouges = 10000018150 au total

                            Si tu initialises total à 10 tu obtiens:

                            15 boules bleues + 6 boules rouges = 21 au total : c'est le 1er exemple du site

                            Si tu initialises total à 30 tu obtiens:

                            85 boules bleues + 35 boules rouges = 120 au total : c'est le 2eme exemple du site

                            Donc ca fonctionne bien: on ne voit pas pourquoi c'est refusé ....

                            • Partager sur Facebook
                            • Partager sur Twitter
                              20 juin 2024 à 10:32:42

                              parce que ça ne tombe pas juste, il y a 10 d'écarts entre les 2 termes, et donc la proba vaut 0.49999999999999994

                              En réadaptant le code de Phil

                              from math import sqrt
                              x, total = 0.99, 10**10
                              while( not x.is_integer() or not(2*x*(x-1)==total*(total-1))):
                                  total += 1
                                  a, b, c = 1, -1, -0.5*total*(total-1)
                                  delta = b**2 - 4*a*c
                                  if delta >=0:
                                      x = (-b+sqrt(delta))/(2*a)
                              
                              print('{} boules bleues {} boules rouges {} total'.format(int(x), int(total)-int(x),total))
                              

                              j'obtiens le résultat
                              14297851353 boules bleues 5922363943 boules rouges 20220215296 total
                              qui lui semble juste

                              • Partager sur Facebook
                              • Partager sur Twitter
                                20 juin 2024 à 11:25:03

                                Bonjour.

                                Ouh là, je vois que ma problématique a déchainé la foule depuis mardi !!!

                                Punaise, au final, à un moment donné je suis parti sur la résolution de l'équation du second degré mais je n'avais pas poursuivi !!! La cause, une erreur de calcul toute bête. Pour éviter le 0.5 de la probabilité, j'ai tout multiplié par 10 sauf que les coefficients de l'équation, je les ai multiplié par 5 !!! Pourquoi, mystère !!!

                                Je vais actualisé mon code avec les bons coeffs et vous tiens au courant de la validation de la réponse.

                                Merci à tous.

                                Edit : Malheureusement, le nombre de boules bleues trouvé (14 297 851 353) n'est pas validé comme solution à ce problème.

                                -
                                Edité par PB68 20 juin 2024 à 14:58:23

                                • Partager sur Facebook
                                • Partager sur Twitter

                                PB68

                                  20 juin 2024 à 18:58:36

                                  Je vais simplifier un peu l'expression:
                                  Est-ce que vous êtes d'accord avec ceci?
                                  2 * b * (b-1) = t * (t-1)
                                  2*b*(b-1) = 2 * b**2 - 2*b
                                  Le delta vaut 4 + 4*2*t*(t-1)
                                  Si on extrait le 4 pour donner 2 à l'extérieur de la racine:
                                  delta = 1 + 2*t*(t-1)
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Le Tout est souvent plus grand que la somme de ses parties.

                                    21 juin 2024 à 9:34:35

                                    PierrotLeFou a écrit:

                                    Je vais simplifier un peu l'expression:
                                    Est-ce que vous êtes d'accord avec ceci?
                                    2 * b * (b-1) = t * (t-1)
                                    2*b*(b-1) = 2 * b**2 - 2*b
                                    Le delta vaut 4 + 4*2*t*(t-1)
                                    Si on extrait le 4 pour donner 2 à l'extérieur de la racine:
                                    delta = 1 + 2*t*(t-1)


                                    Oui, oui, PierrotLeFou, je suis d'accord avec la valeur de delta.

                                    Ma version de code avec la solution de la résolution de l'équation du second degré est devenue la suivante :

                                    from math import sqrt
                                    
                                    
                                    nb_total = 20.22 * 10**9
                                    nb_bleues = 0.99
                                    
                                    while not nb_bleues.is_integer() or not (2 * nb_bleues * (nb_bleues - 1) == nb_total * (nb_total - 1)):
                                    
                                        nb_total += 1
                                    
                                        """
                                        Recherche de la solution positive de l'équation :
                                    
                                              (nb_bleues / nb_total) * ((nb_bleues -1 )/ (nb_total - 1)) = 0.5
                                    
                                              soit
                                    
                                              nb_bleues ** 2 - nb_bleues + 0.5 * (nb_total - nb_total **2) = 0
                                        """
                                    
                                        delta = 1 + 2 * nb_total * (nb_total - 1)
                                    
                                        if delta >= 0:
                                            nb_bleues = (1 + sqrt(delta)) / 2
                                    
                                    print(f"La réponse est {int(nb_bleues)} (Total = {int(nb_total)}).")

                                    Cependant, comme je l'ai précisé dans le edit de mon message précédent, la solution trouvée n'est pas validée.

                                    -
                                    Edité par PB68 21 juin 2024 à 9:37:09

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    PB68

                                      21 juin 2024 à 9:37:35

                                      Hello Fred,

                                      Je comprends vite mais il faut m'expliquer longtemps .....  :-)  :-)

                                      avec le code suivant, j'ai ce résultat:

                                      #(x/21)*(x-1/21-1) = 0.5 --> x^2 -x -(0.5*21**2 - 0.5*21) = 0
                                      x, total = 0.99, 10
                                      while(x-int(x) != 0):
                                          total += 1
                                          a, b, c = 1, -1, -(0.5*total**2 - 0.5*total)
                                          delta = b**2 - 4*a*c
                                          if(delta >= 0): x = (-b+sqrt(delta))/(2*a)
                                      
                                      x, total = int(x), int(total)
                                      print('{} boules bleues + {} boules rouges = {} au total'.format(x, total-x, total))
                                      
                                      p = (x/total)*((x-1)/(total-1))
                                      print('Vérification: proba = ', p)

                                      Et avec ce code:

                                      #(x/21)*(x-1/21-1) = 0.5 --> x^2 -x -(0.5*21**2 - 0.5*21) = 0
                                      x, total = 0.99, 10**10
                                      while(x-int(x) != 0):
                                          total += 1
                                          a, b, c = 1, -1, -(0.5*total**2 - 0.5*total)
                                          delta = b**2 - 4*a*c
                                          if(delta >= 0): x = (-b+sqrt(delta))/(2*a)
                                      
                                      x, total = int(x), int(total)
                                      print('{} boules bleues + {} boules rouges = {} au total'.format(x, total-x, total))
                                      
                                      p = (x/total)*((x-1)/(total-1))
                                      print('Vérification: proba = ', p)





                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        21 juin 2024 à 19:13:20

                                        0.499999999999999999 n'est pas égal 0.5 (oui c'est très proche, mais pas exactement la valeur)

                                        >>> (total*(total-1))
                                        100000362990329404350
                                        >>> x*(x-1)*2
                                        100000362990329393340

                                        on voit l'écart de 10 dont je parlais.

                                        et autre chose bizarre (les 2 expressions sont bien identiques, non? o_O ou j'ai râté un truc?)

                                        >>> x**2-x-(0.5*total**2) + (0.5*total)
                                        -2701.0
                                        >>> x**2-x-(0.5*total**2 - 0.5*total)
                                        0.0



                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          22 juin 2024 à 12:38:17

                                          Un problème de précision avec les grand nombres ?

                                          Avec x=15 et total = 21, ça marche

                                          Avec x=7071080646 et total= 10000018150 et en remplaçant les variables par leur valeur, on a la même chose que toi:

                                          print(50000181502235777316 - 7071080646 - 5.000018150016471e+19 + 5000009075.0)
                                          print(50000181502235777316 - 7071080646 - (5.000018150016471e+19 - 5000009075.0))


                                          -2701.0 et 0.0 

                                          EDIT

                                          Non, en fait, avec les nombres que tu as donnés le 20/06 à 10h32

                                          ca marche:

                                          x, total = 14297851353, 20220215296
                                          print(x**2-x-(0.5*total**2) + (0.5*total))
                                          print(x**2-x-(0.5*total**2 - 0.5*total))

                                          C'est quand même bizarre que

                                          A - B + C

                                          diffère de

                                          A-(B-C)



                                          -
                                          Edité par Phil_1857 22 juin 2024 à 16:46:45

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            22 juin 2024 à 15:35:04

                                            >>> x, t = 14297851353, 20220215296                                                                                     
                                            >>> 2*x*(x-1) == t*(t-1)                                                                                                
                                            False                                                                                                                   
                                            >>>

                                            edit:
                                            Remarque sur l'égalité  2 * b * (b-1) = t * (t-1)
                                            On a déjà un 2 à gauche et un des nombres b ou b-1 qui est divisible par 2.
                                            Un des nombres à droite est impair et l'autre sera forcément un multiple de 4.
                                            On aura ou bien 4x, 4x-1 ou bien 4x+1, 4x
                                            -
                                            On cherche une solution pour t > 10**10, mais on peut se demander s'il existe plusieurs solutions inférieures à 10**10
                                            J'ai écrit un petit programme (pas vraiment optimisé) pour les chercher.
                                            Python semble assez lent pour gérer les grands nombres. Les deux dernières lignes ont pris un temps vraiment abonimable( non calculé).
                                            Si quelqu'un a une idée de génie pour trouver le terme suivant ...
                                            Remarquons que toutes les valeurs de b  sont impaires et que celles de  t  alternent entre les deux formes citées ci-haut.
                                            En fait: 4, 20, 21, 60, 61, 97 (non cyclique)
                                            -
                                            b = 2
                                            t = 4
                                            while t < 10**10:
                                                d = 2*b*(b-1) - t*(t-1)
                                                if d == 0:
                                                    print(b, t, sep=", ")
                                                    t += 1
                                                elif d < 0:
                                                    b += 1
                                                else:
                                                    t += 1
                                            -
                                            3, 4
                                            15, 21
                                            85, 120
                                            493, 697
                                            2871, 4060
                                            16731, 23661
                                            97513, 137904
                                            568345, 803761
                                            3312555, 4684660
                                            19306983, 27304197
                                            112529341, 159140520
                                            655869061, 927538921
                                            3822685023, 5406093004

                                            -
                                            Edité par PierrotLeFou 23 juin 2024 à 2:36:48

                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Le Tout est souvent plus grand que la somme de ses parties.

                                              23 juin 2024 à 15:49:48


                                              Je n'ai pas été assez génial pour trouver la relation entre les valeurs de B (bleu). Je l'ai donc fait avec force brûte, mais en C car Python est trop lent.
                                              J'ai écrit ma propre version de l'arithmétique quadruple précision (4 x 32 bits).
                                              Voici ma réponse, qui est acceptée par le site:
                                              22280241075, 31509019101
                                              Voici la solution qui est très simple (quand on le sait ...):
                                              b(0) = 1
                                              b(1) = 3
                                              ...
                                              b(n) = b(n-1) * 6 - b(n-2) - 2
                                              Chercher b(15)
                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Le Tout est souvent plus grand que la somme de ses parties.

                                                24 juin 2024 à 17:31:38

                                                PierrotLeFou a écrit:


                                                Je n'ai pas été assez génial pour trouver la relation entre les valeurs de B (bleu). Je l'ai donc fait avec force brûte, mais en C car Python est trop lent.
                                                J'ai écrit ma propre version de l'arithmétique quadruple précision (4 x 32 bits).
                                                Voici ma réponse, qui est acceptée par le site:
                                                22280241075, 31509019101
                                                Voici la solution qui est très simple (quand on le sait ...):
                                                b(0) = 1
                                                b(1) = 3
                                                ...
                                                b(n) = b(n-1) * 6 - b(n-2) - 2
                                                Chercher b(15)

                                                Félicitations, PierrotLeFou.

                                                Oui, effectivement, avec la solution sous les yeux, la réponse se trouve toute seule.

                                                Maintenant, mon challenge est de tenter de retrouver cette suite !!!

                                                Un gros rafraichissement des notions de proba en perspective !!!

                                                -
                                                Edité par PB68 24 juin 2024 à 17:31:44

                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                PB68

                                                  28 juin 2024 à 17:44:54

                                                  Bonjour.

                                                  Ca y est, j'ai trouvé ma solution au problème :

                                                  Après avoir disposé les valeurs sous forme de tableau, c'est venu assez rapidement (explication dans le code) :

                                                  """
                                                  Résultat de mon observation :
                                                  
                                                  Le nombre de boules rouges du tirage suivant est égal à :
                                                      Nombre de boules total du tirage précédent + ( Nombre de boules bleues du tirage précédent - 1)
                                                  
                                                  Le nombre de boules bleues du tirage suivant est égal à :
                                                      Nombre de boules bleues du tirage précédent + 2 x nombre de boules rouges du tirage en cours
                                                  """
                                                  
                                                  # BRT [Bleu, Rouge, Total]
                                                  BRT = [[15, 6, 21], [85, 35, 120]]
                                                  
                                                  
                                                  while not BRT[-1][2] > 10**10:
                                                      R = BRT[-1][2] + (BRT[-1][0] - 1)
                                                      B = BRT[-1][0] + 2 * R
                                                      BRT.append([B, R, B + R])
                                                  
                                                  
                                                  print(f"La réponse est {BRT[-1][0]} (Total = {BRT[-1][2]}).")

                                                  -
                                                  Edité par PB68 28 juin 2024 à 17:46:37

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  PB68

                                                    28 juin 2024 à 18:19:50

                                                    et donc tu obtiens quelles valeurs ?
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      29 juin 2024 à 7:04:22

                                                      Bonjour.

                                                      Et, j’obtiens :

                                                      La réponse est 22280241075 (Total = 31509019101).

                                                      Réponse qui a été acceptée par le site.

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter

                                                      PB68

                                                      Défi TURING

                                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                      • Editeur
                                                      • Markdown