Partage
  • Partager sur Facebook
  • Partager sur Twitter

Choisir son manteau

France ioi

    21 septembre 2020 à 21:04:17

    Bonsoir à tous 

    enfaite j'ai un probleme avec cet exo ,je l'ai pas compris , j'ai  pas compris ce qu'il demande 

    qlq peut m'expliquer et Merci d'avance 

    Choisir un manteau pour les vacances est toujours difficile, surtout lorsque l'on ne sait pas encore où l'on part. En effet chaque manteau est adapté à une certaine plage de température et vous aimeriez bien choisir un manteau qui s'adaptera à vos besoins.

    Vous voilà dans un vaste magasin de manteaux, un peu perdu dans l'énorme choix proposé. Pour chacun des manteaux du magasin, vous connaissez l'intervalle de température qui lui correspond.

    Avec votre logique impassible, vous décidez d'inventer un critère qui vous aidera à choisir votre manteau : Le niveau d'un manteau sera défini comme le nombre d'autres manteaux du magasin dont l'intervalle de température est contenu dans l'intervalle de celui-ci.

    Vous décidez de sortir votre ordinateur et d'écrire un programme qui déterminera le niveau maximal que l'on peut trouver.

    Limites de temps et de mémoire (Python)

    • Temps : 2 s sur une machine à 1 GHz.
    • Mémoire : 8 000 ko.

    Contraintes

    • 1 <= nbManteaux <= 20 000.
    • 0 <= temperatureinftemperaturesup <= 500 000 000, l'intervalle de température d'un manteau.

    Entrée

    Sur la première ligne de l'entrée, votre programme lira un unique entier : nbManteaux, le nombre de manteaux du magasin.

    Il lira ensuite nbManteaux lignes contenant chacune deux entiers indiquant l'intervalle de température d'un manteau.

    Sortie

    Votre programme affichera un unique entier : le niveau maximal d'un manteau.

    Exemple

    entrée :

    8
    1 3
    2 5
    5 8
    3 6
    2 5
    3 8
    3 6
    3 8

    sortie :

    4

    Commentaires

    Dans l'exemple présenté, les niveaux des manteaux sont, dans l'ordre : 0, 1, 0, 1, 1, 4, 1, 4.

    Le résultat à afficher est donc 4.

    Si vous ne passez pas en temps les derniers tests, c'est que votre algorithme est trop lent. A vous de l'améliorer, par vous-même.

    • Partager sur Facebook
    • Partager sur Twitter
      21 septembre 2020 à 21:58:14

      Montre ton code si tu veux de l'aide
      • Partager sur Facebook
      • Partager sur Twitter
        22 septembre 2020 à 7:07:07

        Je comprend que ce problème ne soit pas évident pour celui que je crois être un débutant.
        La contrainte sur la grandeur des intervalles (0 à 500000000( a peu d'impact sur la vitesse d'exécution.
        Je ne crois pas, qu'avec un algorithme naïf, on puisse traiter 20000 intervalles en 2 secondes.
        Pour qu'un intervalle (d1, f1) puisse inclure un intervalle (d2, f2), il faut que d1 <= d2 et f2 <= f1
        On peut réduire le nombre de comparaisons en triant la liste des intervalles.
        On trie par ordre croissant pour les débuts, et par ordre décroissant pour les fins, pour un même début.
        De cette façon, on n'a pas besoin de comparer les débuts car ils sont en ordre croissant.
        On divise donc par deux le nombre de comparaisons.
        On divise ensuite environ par deux le nombre de comparaisons si on commence à l'intervalle suivant de l'intervalle courant.
        Reste à savoir quel est le coût en temps du tri lui-même.
        • Partager sur Facebook
        • Partager sur Twitter

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

          22 septembre 2020 à 7:44:30

          Pour l'avoir fait, je sais qu'avec sorted ça passe.
          • Partager sur Facebook
          • Partager sur Twitter
            22 septembre 2020 à 8:18:40

            Un petit essai avant le dodo ...
            -
            from time import perf_counter
            from random import randrange
            # Valeurs de départ.
            n = 10 #5500
            L=[]
            lim = 500 # 500000000
            # Je génère aléatoirement mes intervalles.
            for i in range(n):
                d=randrange(lim+1)
                f=d+randrange(lim+1-d)
                L.append((d, f))
            t1 = perf_counter()
            # Fonction de comparaison, ordre croissant pour les débuts, ordre décroissant pour les fins.
            plage = lambda t: (t[0], -t[1])
            L.sort(key=plage)
            #print(*L)
            # Compter les intervalles qui en incluent un autre.
            C=[0 for i in range(n)]
            for i in range(n):
                for j in range(i+1,n):
                    if L[i][1]>=L[j][1]:
                       C[i]+=1
            #for i in range(n):
            #    print(L[i], C[i])
            print(max(C))
            t2=perf_counter()
            print(str(t2-t1)[:5], 'secondes')
            • Partager sur Facebook
            • Partager sur Twitter

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

              22 septembre 2020 à 9:15:58

              @pierrot j'ai testé ton code sur france ioi, il ne passe pas à cause des performances. (il ne passe que 5 tests sur 17)

              Ta solution est en O(N²) à cause la double boucle for.

              Perso j'ai une solution en O(N.log(N)) (c'est à dire la complexité de sorted)

              -
              Edité par thelinekioubeur 22 septembre 2020 à 9:16:56

              • Partager sur Facebook
              • Partager sur Twitter
                22 septembre 2020 à 17:53:27

                Réveil brutal ...
                Je savais que mon code était de l'ordre O(n²).
                Si on peut faire O(n log n), mon temps serait 13/5500 pour 5500 et 15/20000 pour 20000, ce qui me ferait passer en bas de la seconde.
                Peux-tu donner ta solution? Quelque chose manque à ma culture. :)
                Je continue à chercher.

                -
                Edité par PierrotLeFou 22 septembre 2020 à 18:45:22

                • Partager sur Facebook
                • Partager sur Twitter

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

                  22 septembre 2020 à 21:46:00

                  j'ai tenté un code, et quand je suis allé sur france ioi pour le valider, j'ai vu qu'en fait, je l'avais déjà résolu il y a longtemps avec un code 10 fois plus efficace ...

                  conclusion, j'étais bien meilleur avant en algo.

                  le voici:

                  z = [tuple(map(int,input().split()))for i in range(int(input()))]
                  z.sort(key=lambda x:x[1]-x[0],reverse=1)
                  qgr = 0
                  while qgr<len(z)/2:
                     mag = len(z)
                     a,*b = z
                     z = [i for i in b if not (i[0]>=a[0] and i[1]<=a[1])]
                     if mag-len(z)>qgr: qgr=mag-len(z)
                  print(qgr-1)
                  



                  • Partager sur Facebook
                  • Partager sur Twitter

                  Python c'est bon, mangez-en. 

                    22 septembre 2020 à 21:54:38

                    Voici ma solution. Par contre j'ai écrit ça il y a un an et aujourd'hui je ne la comprend plus :lol:
                    Mais elle fonctionne, en moins d'une seconde effectivement.

                    N = int(input())
                    manteaux = [tuple(map(int, input().split())) for i in range(N)]
                    manteaux = dict(enumerate(sorted(manteaux, key=lambda x: (x[0], -x[1]))))
                    m2 = sorted(manteaux, key=lambda x: (-manteaux[x][1], manteaux[x][0]))
                    p2 = {m: i for i, m in enumerate(m2)}
                    print(max(N - i - p2[i] - 1 for i in range(N)))



                    • Partager sur Facebook
                    • Partager sur Twitter
                      22 septembre 2020 à 22:42:42

                      thelinekioubeur a écrit:

                      aujourd'hui je ne la comprend plus


                      C'est bien dommage, j'aurais aimé une explication.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Python c'est bon, mangez-en. 

                        23 septembre 2020 à 1:39:21

                        ... six heures plus tard de l'autre côté de l'Atlantique ...
                        @thelinekioubeur et @josmiley:
                        J'ai pris note de vos codes respectifs.
                        Pour faire un test de performance, il faut beaucoup plus de données que ce qu'on entre normalement à la console.
                        Je vais essayer de modifier vos codes pour inclure certaines listes "pathologiques" d'intervvalles.
                        + intervalles choisis au hasard comme j'ai fait.
                        + liste de "poupées russes". par exemple, (1, 100), (2, 99), (3, 98), ...
                        + intervalles se chevauchant mais non inclus. Par exemple: (1, 100), (2, 101), (3, 102), ...
                        + intervalles disjoints. Par exemple: (1, 100), (101, 200), (201, 300), ...
                        Dans les 3 derniers cas, on peut prédire le nombre maximum cherché.
                        @josmiley:
                        Ton code fonctionne dans les 3 derniers cas (évidemment ...)
                        Pour comprendre le code de thelinekioubeur, tu pourrais suivre les conseils donnés à tous: fais des print()  :)
                        C'est ce que je voulais faire ...
                        J'avais pensé au dictionnaire quand thelinekioubeur m'a dit que mon code était trop lent. Mais je ne savais pas comment m'y prendre.
                        • Partager sur Facebook
                        • Partager sur Twitter

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

                          23 septembre 2020 à 6:18:16

                          je pense que c'est un coup de chance que mon code passe sur france ioi, car aujourd'hui, la condition du while me semble farfelue.
                          • Partager sur Facebook
                          • Partager sur Twitter

                          Python c'est bon, mangez-en. 

                            23 septembre 2020 à 6:52:54

                            josmiley a écrit:

                            je pense que c'est un coup de chance que mon code passe sur france ioi, car aujourd'hui, la condition du while me semble farfelue.

                            Comme je l'ai dit, les 3 derniers type d'intervalles sont corrects.

                            Je n'ai pas encore essayé avec le premier type.

                            As-tu des suggestions quant au genre d'intervalles qui seraient intéressants à tester?

                            De plus, il est inutile de changer l'ordre puisque vous faites tous deux des tris.

                            • Partager sur Facebook
                            • Partager sur Twitter

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

                              23 septembre 2020 à 6:58:07

                              10 manteaux en 2 groupes : 4 manteaux dont 1 a le plus grand intervalle + 6 autres.

                              Normalement mon code devrait pas passer. Je pense qu'il faut enlever le /2 du while. Je peux pas tester là, je suis au boulot.

                              • Partager sur Facebook
                              • Partager sur Twitter

                              Python c'est bon, mangez-en. 

                                23 septembre 2020 à 7:16:35

                                josmiley a écrit:

                                10 manteaux en 2 groupes : 4 manteaux dont 1 a le plus grand intervalle + 6 autres.

                                Normalement mon code devrait pas passer. Je pense qu'il faut enlever le /2 du while. Je peux pas tester là, je suis au boulot.

                                J'ai testé ton code avec des intervalles aléatoires. Ça ne plante pas et ça semble correct.

                                Pour la fiabilité, il faudrait que je mette plus d'un algo dans mon code et que je teste avec la même liste.

                                Si je fais des séries à répétitions et que tout est pareil, c'est un bon indice que les algo devraient être corrects.

                                • Partager sur Facebook
                                • Partager sur Twitter

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

                                  23 septembre 2020 à 7:33:19

                                  @pierrot  en fait les inputs sont là pour fonctionner avec france ioi. Puisqu'on parle d'un exercice de france ioi : http://www.france-ioi.org/algo/task.php?idChapter=671&idTask=2330
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    23 septembre 2020 à 13:57:10

                                    PierrotLeFou a écrit:

                                    josmiley a écrit:

                                    10 manteaux en 2 groupes : 4 manteaux dont 1 a le plus grand intervalle + 6 autres.

                                    Normalement mon code devrait pas passer. Je pense qu'il faut enlever le /2 du while. Je peux pas tester là, je suis au boulot.

                                    J'ai testé ton code avec des intervalles aléatoires. Ça ne plante pas et ça semble correct.

                                    Pour la fiabilité, il faudrait que je mette plus d'un algo dans mon code et que je teste avec la même liste.

                                    Si je fais des séries à répétitions et que tout est pareil, c'est un bon indice que les algo devraient être corrects.

                                    j'ai testé, et il faut effectivement modifier la condition du while dans mon code, c'était bien un coup de chance si j'ai passé les test france ioi, ils n'avaient pas tout prévu ^^:

                                    while qgr<len(z):




                                    -
                                    Edité par josmiley 23 septembre 2020 à 13:57:59

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Python c'est bon, mangez-en. 

                                      24 septembre 2020 à 4:04:58

                                      @josmiley:
                                      J'ai testé ton code avec et sans le '/2' et il y a des erreurs dans les deux cas.
                                      Je teste la même liste d'intervalles avec les trois codes: celui de thelinekioubeur, le tien et le mien.
                                      Je sais, le miens est très lent, mais combiné avec celui de thelinekioubeur, ça me donne une référence.
                                      Je vais essayer de trouver un exemple ou tu es différent de nous deux.
                                      Je viens de trouver ceci:
                                      js=4, tk=5, pf=5                                                                                                        
                                      (12, 21), (11, 17), (34, 47), (9, 42), (26, 32), (31, 36), (43, 45), (20, 48), (50, 50), (45, 48)
                                      Ça prend environ une dizaine d'essais avant de trouver un cas erroné.
                                      En espérant que j'ai bien recopié ton code.
                                      Celui-ci est avec le '/2':
                                      js=6, tk=7, pf=7                                                                                                        
                                      [(34, 40), (4, 32), (41, 43), (34, 40), (20, 48), (7, 12), (35, 43), (37, 37), (41, 43), (30, 30)]                       

                                      -
                                      Edité par PierrotLeFou 24 septembre 2020 à 4:21:18

                                      • Partager sur Facebook
                                      • Partager sur Twitter

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

                                        24 septembre 2020 à 6:13:23

                                        PierrotLeFou a écrit:

                                        @josmiley:
                                        Je viens de trouver ceci:
                                        (12, 21), (11, 17), (34, 47), (9, 42), (26, 32), (31, 36), (43, 45), (20, 48), (50, 50), (45, 48)


                                        mon code trouve 4, je l'ai fait à la main, je trouve 4 aussi ...

                                        je trouve 3 groupes:

                                        1: (9, 42), (12, 21), (11, 17), (26, 32), (31, 36) niveau 4

                                        2: (20, 48), (34, 47), (45, 48), (43, 45) niveau 3

                                        3: (50, 50) niveau 0

                                        • Partager sur Facebook
                                        • Partager sur Twitter

                                        Python c'est bon, mangez-en. 

                                          24 septembre 2020 à 8:01:23

                                          Peux-tu me redonner ton code exact? Je ne sais pas lequel je teste (sans /2 avec /2 avec //2)
                                          Sinon, je donnerai mon code non coloré au risque de me faire tuer ...
                                          Avec les tests courants, ton code est environ 4 fois plus rapide que celui de thelinekioubeur.
                                          • Partager sur Facebook
                                          • Partager sur Twitter

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

                                            24 septembre 2020 à 13:52:25

                                            PierrotLeFou a écrit:

                                            Peux-tu me redonner ton code exact? Je ne sais pas lequel je teste (sans /2 avec /2 avec //2)
                                            Sinon, je donnerai mon code non coloré au risque de me faire tuer ...
                                            Avec les tests courants, ton code est environ 4 fois plus rapide que celui de thelinekioubeur.

                                            z = [tuple(map(int,input().split()))for i in range(int(input()))]
                                            m = 0
                                            z.sort(key=lambda x:x[1]-x[0],reverse=1)
                                            qgr = 0
                                            while qgr<len(z):
                                                mag = len(z)
                                                a,*b = z
                                                z = [i for i in b if not (i[0]>=a[0] and i[1]<=a[1])]
                                                if mag-len(z)>qgr: qgr=mag-len(z)
                                            
                                            print(qgr-1)


                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Python c'est bon, mangez-en. 

                                              24 septembre 2020 à 18:47:49

                                              Voici ce que j'ai testé. Ça devrait être identique à ton code aux commentaires près.
                                              # js=1, tk=2, pf=2                                                                                                        
                                              # [(4, 25), *(20, 40), +(23, 28), (22, 50), +(21, 26)]                                                                        
                                              z=[(4, 25), (20, 40), (23, 28), (22, 50), (21, 26)]                                                                        
                                              #z = [tuple(map(int,input().split()))for i in range(int(input()))]
                                              #m = 0    # avec ou sans, ça ne fait pas de différence ...
                                              z.sort(key=lambda x:x[1]-x[0],reverse=1)
                                              qgr = 0
                                              while qgr<len(z):
                                                  mag = len(z)
                                                  a,*b = z
                                                  z = [i for i in b if not (i[0]>=a[0] and i[1]<=a[1])]
                                                  if mag-len(z)>qgr: qgr=mag-len(z)
                                              print(qgr-1)
                                              # 1    # résultat
                                              Ce serait dommage de ne pas trouver ce qui ne va pas. Ton code est le plus performant.
                                              -
                                              Voici le résultat de mon dernier test.
                                              Départ de 1000 essais, avec 20000 intervalles, limite de 500000000                                                      
                                              Nombre d'erreurs: 105                                                                                                   
                                              Fin du test                                                                                                             
                                              Valeur moyenne pour 1000 essais.                                                                                        
                                              js=0.006, tk=0.027                                                                                                       

                                              -
                                              Edité par PierrotLeFou 24 septembre 2020 à 19:03:21

                                              • Partager sur Facebook
                                              • Partager sur Twitter

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

                                                24 septembre 2020 à 19:02:52

                                                c'est bon, je l'ai fait à la main, ça fait bien 1.

                                                combien j'aurais dû trouver ?

                                                ça fait 3 groupes:

                                                1: (22, 50), (23, 28)

                                                2: (4, 25)

                                                3: (20, 40), (21, 26)

                                                le plus grand groupe contient 2 manteaux, donc le niveau est 1.

                                                -
                                                Edité par josmiley 24 septembre 2020 à 19:16:17

                                                • Partager sur Facebook
                                                • Partager sur Twitter

                                                Python c'est bon, mangez-en. 

                                                  24 septembre 2020 à 19:23:53

                                                  L'énoncé porte à confusion:
                                                  «... Le niveau d'un manteau sera défini comme le nombre d'autres manteaux du magasin dont l'intervalle de température est contenu dans l'intervalle de celui-ci.»
                                                  Qui est le 'celui-ci'?
                                                  Ceux qui sont inclus dans le plus grand? Ou ceux qui sont emboîtés comme dans les poupées russes.
                                                  Ton code fonctionne parfaitement si c'est la deuxième possibilité.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

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

                                                    24 septembre 2020 à 19:28:28

                                                    celui qui contient le plus d'intervalles inférieurs ou égaux.

                                                    -
                                                    Edité par josmiley 24 septembre 2020 à 19:30:35

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter

                                                    Python c'est bon, mangez-en. 

                                                      25 septembre 2020 à 1:52:03

                                                      Je comprend que 'inférieur' veut dire à l'intérieur ou imbriqué.
                                                      Je cherche encore un ordre de tri tordu avec lequel je pourrait parcourir la liste triée facilement d'un coup.
                                                      Ou utiliser une variante du MergeSort ...
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter

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

                                                        26 septembre 2020 à 4:10:03

                                                        @josmiley:
                                                        Après avoir essayé quelques trucs sadiques qui n'ont pas fonctionné ...
                                                        (la recherche dichotomique c'est bien, mais les insertions massives ça coûte cher)
                                                        Je me suis tourné vers ton code. Si je considère les lignes suivantes:
                                                            a,*b = z
                                                            z = [i for i in b if not (i[0]>=a[0] and i[1]<=a[1])]
                                                        La première ligne prend tout de même un certain temps. Si je remplace par ceci, ça fonctionne encore.
                                                            a = z[0]
                                                            z = [i for i in z if not (i[0]>=a[0] and i[1]<=a[1])]
                                                        Le premier élément de la liste de départ n'est pas inclus dans la liste résultante de toute façon.
                                                        Je pense que la seconde ligne prend plus de temps à s'exécuter. Je sauve environ 1/7 ième du temps d'exécution.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter

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

                                                          26 septembre 2020 à 7:03:52

                                                          PierrotLeFou a écrit:

                                                          Le premier élément de la liste de départ n'est pas inclus dans la liste résultante de toute façon.


                                                          Tu as absolument raison. La comparaison est surement plus rapide que l'affectation. Du coup je pense qu'on peut même se passer du reverse et faire a=z.pop() à la place de a=z[0].

                                                          et sans l'indexage de 'a' c'est encore plus rapide:

                                                          z = [tuple(map(int,input().split()))for i in range(int(input()))]
                                                          m = 0
                                                          z.sort(key=lambda x:x[1]-x[0])
                                                          qgr = 0
                                                          while qgr<len(z):
                                                              mag = len(z)
                                                              aw,ah = z.pop()
                                                              z = [i for i in z if not (i[0]>=aw and i[1]<=ah)]
                                                              if mag-len(z)>qgr: qgr=mag-len(z)
                                                          
                                                          print(qgr-1)



                                                          -
                                                          Edité par josmiley 26 septembre 2020 à 7:24:48

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          Python c'est bon, mangez-en. 

                                                          Choisir son manteau

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                          • Editeur
                                                          • Markdown