Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 01-05-2013 19:29:54

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

[Python]A propos de Jeu d'eau de Yassine (cf énigmes)

Bonsoir,

Sujet : http://www.bibmath.net/forums/viewtopic.php?id=6040

Voilà une version "factorisée"


#!/usr/bin/python
# -*- coding: Latin-1 -*-

def transfer(T,cr):
    a,b=T[0],T[1]
    q,r=max(a,b)//min(a,b),(max(a,b)%min(a,b))*cr
    if r==0:
        if q%2==0:
            T[1-cr],T[2]=T[1-cr]*2,T[2]-T[1-cr]
            print T
        else:
            T[1-cr],T[cr]=T[1-cr]*2,T[cr]-T[1-cr]
            print T
    elif cr:
        T[0],T[1]=T[0]*2,T[1]-T[0]
        print T
    return T

N=sorted([7,11,29])
print N
while not (N[0]==N[1] or N[0]==N[2] or N[1]==N[2]):
    if N[1]>N[0]:
        N=transfer(N,1)        
    elif N[0]>N[1] :
        if N[0]>N[2]:
            N[2],N[0]=N[2]*2,N[0]-N[2]
            print N
        else:
            N=transfer(N,0)
           

nb=10*(N[0]==N[1])+20*(N[0]==N[2])+21*(N[1]==N[2])
if nb==51:nb=10
print
print"** Fin **"
N[nb%10],N[nb//10]=0,N[nb//10]*2
print N
 

Sortie :

[7, 11, 29]
[14, 4, 29]
[10, 8, 29]
[2, 16, 29]
[4, 16, 27]
[8, 16, 23]
[16, 16, 15]

** Fin **
[0, 32, 15]

Pour optimiser dans le cas soulevé par arfr, il me faudrait rajouter une dizaine de lignes de code...
C'est fait, mais elles ne figurent pas ci-dessus : j'ai estimé que ça ne valait pas le coup !

@+

Dernière modification par yoshi (02-05-2013 12:18:39)

Hors ligne

#2 05-05-2013 18:55:25

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : [Python]A propos de Jeu d'eau de Yassine (cf énigmes)

Bonsoir,

Hélas, totomm a montré que cet algorithme n'est pas infaillible : il boucle parfois sans fin...
Donc après explications, j'ai recodé "propre" en incluant deux cas particuliers :
* [3,11,14] ou 14 - 11 = 3 et 14 - 3 = 11
[c,b,a] avec c < b <a  et a - c = b
Je ne fais qu'un test : si a-b = c alors a - c = b

* Cas du triple.
   [3,11,33] ou [5,11,15]
   [c,b,a] avec c < b <a  et a = 3c ou a = 3b
   Le sous-cas b = 3a est résolu par l'algorithme...


def vidage(L):
    print L
    while not (L[0]==0 or L[1]==0):
        M=L
        L=sorted(L)
        if M!=L:
            print L
        fg=(L[2]==L[0]*3)+10*(L[2]==L[1]*3)
        if L[2]-L[1]==L[0]:
            L[0],L[2]=L[0]*2,L[2]-L[0]
            print L
            L[2],L[1]=L[2]*2,0
            print L
        elif fg > 0:
            L[fg//10],L[2]=L[fg//10]*2,L[2]-L[fg//10]
            print L
            L[2],L[fg//10]=L[2]*2,0
            print L
        else:
            q=L[1]//L[0]
            lg=len(bin(q))-2
            for i in range(lg):
                L[0],L[2-((q>>i)&1)]=L[0]*2,L[2-((q>>i)&1)]-L[0]  
                print L

Sorties
>>> vidage([3, 11, 14])
[3, 11, 14]
[6, 11, 11]
[6, 0, 22]
>>> vidage([3, 17, 51])
[3, 17, 51]
[3, 34, 34]
[3, 0, 68]

>>> vidage([3, 7, 35])
[3, 7, 35]
[6, 7, 32]
[12, 1, 32]
[1, 12, 32]
[2, 12, 31]
[4, 12, 29]
[8, 8, 29]
[16, 0, 29]

Explications (pour qui ne saurait pas)
>>> bin(5)
'0b101'
>>> type(bin(5))
<type 'str'>
Confirmation : python convertit un nombre en binaire et restitue une chaîne...
>>> bin(9)
'0b1001'
>>> bin(9)[2:]
'1001'
q=L[1]//L[0]
Alors, j'obtiens le nombre de bits significatifs de q avec longueur de chaîne -2 : lg=len(bin(q))-2
Puis je boucle sur cette longueur...
(q>>i) & 1 :
j'obtiens le ieme bit par décalage vers la droite de i (>>) avec un & 1 logique...
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
* Si le résultat de ce calcul vaut 1 (valeur du ieme bit), alors L[2-((q>>i) & 1)] donne L[1] et c'est R2 que je vide
* Si le résultat de ce calcul vaut 0 (valeur du ieme bit), alors L[2-((q>>i) & 1)] donne L[2] et c'est R3 que je vide

@+

Hors ligne

#3 06-05-2013 20:41:46

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : [Python]A propos de Jeu d'eau de Yassine (cf énigmes)

Bonsoir,

J'ai gagné 2 lignes...


def vidage(L):
    print L
    while not (L[0]==0 or L[1]==0):
        if L!=sorted(L):
            L.sort()
            print L
        fg=(L[2]==L[0]*3)+10*(L[2]==L[1]*3)
        if L[2]-L[1]==L[0]:
            for i in range(2):
                L[2*i],L[2-i]=L[2*i]*2,L[2-i]-L[i]
                print L
        elif fg > 0:
            L[fg//10],L[2]=L[fg//10]*2,L[2]-L[fg//10]
            print L
            L[2],L[fg//10]=L[2]*2,0
            print L
        else:
            q=L[1]//L[0]
            lg=len(bin(q))-2
            for i in range(lg):
                L[0],L[2-((q>>i)&1)]=L[0]*2,L[2-((q>>i)&1)]-L[0]  
                print L

Je ne désespère pas d'en gagner encore au moins une...

@+

Hors ligne

#4 07-05-2013 19:48:14

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : [Python]A propos de Jeu d'eau de Yassine (cf énigmes)

bonsoir,

J'ai gagné ma ligne...
Tout ça pour ça ?
Ce n'est pas tant le fait de gagner une ligne que de ne plus écrire 2 fois de suite print L : l'intérêt est là


def vidage(L):
    print L
    while not (L[0]==0 or L[1]==0):
        if L!=sorted(L):
            L.sort()
            print L
        fg=(L[2]==L[0]*3)+10*(L[2]==L[1]*3)
        if L[2]-L[1]==L[0]:
            for i in range(2):
                L[2*i],L[2-i]=L[2*i]*2,L[2-i]-L[i]
                print L
        elif fg > 0:
            for i in range(2):
                L[(fg//10)*(1-i)+2*i],L[(fg//10)*i+2*(1-i)]=L[(fg//10)*(1-i)+2*i]*2,(L[2]-L[fg//10])*(1-i)
                print L
        else:
            q=L[1]//L[0]
            lg=len(bin(q))-2
            for i in range(lg):
                L[0],L[2-((q>>i)&1)]=L[0]*2,L[2-((q>>i)&1)]-L[0]  
                print L
 

C'est plus rationnel comme ça.

@+

Hors ligne

#5 08-05-2013 08:30:45

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 17 385

Re : [Python]A propos de Jeu d'eau de Yassine (cf énigmes)

Bonjour,

La nuit portant conseil, j'ai modifié la ligne  7, pour obtenir respectivement 2 et 1 au lieu de 1 et 10...
Ce qui m'a permis de simplifier considérablement les calculs de la ligne 14.


def vidage(L):
    print L
    while not (L[0]==0 or L[1]==0):
        if L!=sorted(L):
            L.sort()
            print L
        f=2*(L[2]==L[0]*3)+(L[2]==L[1]*3)
        if L[2]-L[1]==L[0]:
            for i in range(2):
                L[2*i],L[2-i]=L[2*i]*2,L[2-i]-L[i]
                print L
        elif f > 0:
            for i in range(2):
                L[f%2+f*i],L[2-f*i]=L[f%2+f*i]*2,L[2]-L[f%2+f*i]
                print L
        else:
            q=L[1]//L[0]
            lg=len(bin(q))-2
            for i in range(lg):
                L[0],L[2-((q>>i)&1)]=L[0]*2,L[2-((q>>i)&1)]-L[0]  
                print L
 

Et là, je ne pense pas qu'il n'y aura pas d'autres "mises à jour"...

@+

Hors ligne

Réponse rapide

Veuillez composer votre message et l'envoyer
Nom (obligatoire)

E-mail (obligatoire)

Message (obligatoire)

Programme anti-spam : Afin de lutter contre le spam, nous vous demandons de bien vouloir répondre à la question suivante. Après inscription sur le site, vous n'aurez plus à répondre à ces questions.

Quel est le résultat de l'opération suivante (donner le résultat en chiffres)?
quaranteneuf plus vingt huit
Système anti-bot

Faites glisser le curseur de gauche à droite pour activer le bouton de confirmation.

Attention : Vous devez activer Javascript dans votre navigateur pour utiliser le système anti-bot.

Pied de page des forums