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 15-05-2020 10:08:20

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Comment "aller vers" en Python

Salut yoshi,

je continue mon exploration sur ce langage que je commence à apprécier car je lui trouve une grande agilité, mais bute pour le moment sur une petit sujet, peu important mais tout de même.
J'ai compris que le code n'avait pas de fonction "goto vers un label", qui permet de se brancher directement sur des calculs adaptés dans certaines circonstances, puis de revenir au pgm principal.
Je me dis que peut-être, il faut utiliser les sub-routines (c'est comme ça que j'avais appris il y a 40 ans !), mais je te soumets un petit problème amusant pour que tu me donnes une piste s'il y en a.
***
On est dans ce qu'on appelle un truel : un duel au pistolet à trois, genre "Le bon, la brute et le truand".
Ils se tirent l'un sur l'autre, chacun à son tour, jusqu'au dernier survivant, selon le protocole suivant.
Le tireur A fait mouche une fois sur 5 ; il tire en premier sur le plus habile des autres ;
le tireur B fait mouche une fois sur 2 ; il tire en second, lui aussi sur le plus habile des autres ;
Le tireur C rate sa cible une fois sur 5, il tire en dernier sur le plus habile des autres.
(on peut ensuite compliquer à l'envi en tirant au sort celui sur lequel chacun tire, de manière équiprobable ou non).

La question est de calculer la durée de survie de chacun.
En termes d'algo, on voit bien le truc.
On commence par A qui tire sur C. Puis, c'est au tour de B qui va tirer sur C s'il est toujours en vie, sinon, il tire sur A. Puis, si C est toujours debout, il tire sur B s'il est encore vivant, sinon sur A.
Et on recommence et on s'arrête quand il n'y en a plus qu'un.

On répète par exemple 100 fois la procédure et on regarde combien de fois A, B et C finissent debout. Le truc est de voir par exemple, si la survie est en lien avec leur habileté au tir.

Je me souviens avoir utilisé sur SAS la fonction "goto", (très présente sur fortran) c'est assez ludique à faire. Mais là, sous Python, je ne sais si tu as déjà rencontré ce petit problème.

Accessoirement, je cherche sous Python l'équivalent de la fonction Alea() disponible sous VBA, je pense que les gars ont dû faire un truc béton.


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#2 15-05-2020 10:26:08

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Re,

OK, la fonction aléa est randint from random :-)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#3 15-05-2020 10:27:46

LEG
Membre
Inscription : 19-09-2012
Messages : 690

Re : Comment "aller vers" en Python

Tu es sûr que ce n'est pas le Bon, la Brute et le Covid.....

Hors ligne

#4 15-05-2020 15:37:29

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Comment "aller vers" en Python

Re,

Non, c'est :
from random import randint

puis x=randint(borne_inf,borne_sup) bornes (entières)  incluses

Si :
from random import random

puis :
x=random() 0<=x<1
Pour en savoir bien plus : https://docs.python.org/3/library/random.html

Je suis sur ma revue, alors j'ai pas trop le temps de réfléchir...
Tes sub-routines doivent être si j'en crois mes souvenirs de Turbo-Basic doivent être les fonctions de Python
Une fonction se met en début de programme (après les import) et se définit ainsi :

def TrucBidule (paramètresbis):
     Instructions
     Instructions
     return resultat(s)

Et il faut l'appeler et lui passer les paramètres de travail...
Pour récupérer le ou les résultats après l'appel :
MesResultats=TrucBidule (paramètres)

Tu dois bien savoir que les variables et les paramètres utilisés dans la fonction sont inconnues du programmes principal, quand bien même elles porteraient le même nom...
Les paramètres passés dans l'appel et les paramètres récupérés par la fonction ne sont donc pas forcés d'utiliser le même nom, de même mes résultats renvoyés par return et ceux récupérés par :
MesResultats=TrucBidule (paramètres)...
Par contre il est impératif que le passage des paramètres et la récupération des résultats se fassent dans le même ordre...

Un exemple de fonction.
Cahier des charges :

réalisez une fonction plus Frequent qui recherche dans la chaîne de caractères passée en paramètre quelle est la lettre minuscule non accentuée qui présente le plus grand nombre d'occurrences, et retourne ce caractère. Si le plus grand nombre d'occurrences est commun à plusieurs lettres, c'est la première dans l'ordre alphabétique qui sera renvoyée par la fonction. Par ailleurs, si la chaîne reçue en paramètre est vide, la fonction doit renvoyer une chaine vide.

Pour réaliser cet exercice, vous pouvez déclarer une variable alphabet de type chaîne de caractères qui contient toutes les lettres minuscules de l'alphabet et pour chacune d'elles compter le nombre d'occurrences dans la chaîne passée en paramètre...

def Plus_Frequent(chaine):    
    if chaine=="":
        return 0,""
    alphabet=[chr(i) for i in range(97,123)]
    occurrences=[chaine.count(lettre)for lettre in alphabet]
    maxi=max(occurrences)
    return maxi,alphabet[occurrences.index(maxi)]

chaine="J'ai simplement dit que je préfère utiliser une variable de plus et retourner lettreplusfrequente, lettrecherchee, lettre_attendue, lettrereponse, peu importe pourvu que le nom soit clair, plutôt que alphabet[ i]"

maximum, lettre=Plus_Frequent(chaine) # appel et recup
if lettre=="":
    print ("La chaîne entrée était vide.")
else:
    print ("La lettre minuscule non accentuée",lettre,"était présente", maximum, "fois dans la chaine.")

Et j'obtiens  :

La lettre minuscule non accentuée e était présente 36 fois dans la chaine.

L'avantage de la fonction c'est qu'elle peut être appelée, avec récupération par icelle de noms génériques de paramètres, de plusieurs endroits différents : dans ton cas, par plusieurs tireurs. C'est de la "factorisation"...

Ça répond à ta question ?

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#5 15-05-2020 17:26:42

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut et merci, je vais regarder, prends ton temps, il n'y a pas d'urgence.
Oui, les fonctions qui appellent des fonctions, ce sont les subroutine d'antan !

Pour le petit problème que j'ai posé, je pense avoir trouvé la bonne manière de s'y prendre.

Je démarre un boucle while (au moins deux sur trois sont encore vivants)
  puis je commence par A qui tire sur C
       si C est touché, une indicatrice personnalisée  change de valeur ;
  puis je prends B qui tire sur C (ou A)
       si C (ou A est touché), une indicatrice personnalisée change de valeur
  puis si C est vivant, il tire sur B (ou A), ….

et ça tourne jusqu'au dernier survivant.

Pour le calcul, je ferai tourner 1.000 fois, voir plus si ça va très vite, ce que je pense.

PS : le Mersenne twister pour random, c'est top de chez top de chez top en termes de générateur pseudo-aléatoire !


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#6 16-05-2020 11:34:57

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Hello,

voilà mon idée.
On constate que C meurt très souvent, car ils s'y mettent à deux pour lui tirer dessus, au début. A a presque autant de chance que lui d'y rester aussi, c'est B qui tire le mieux son épingle du jeu. Je pense qu'on peut le vérifier par le calcul.


from random import random
from time import time

prob=[0.2,0.5,0.8]
tab=[0,0,0]
n=1000

for cpt in range(n):
    x=y=z=i=flaga=flagb=flagc=0
    seed=time() #en réalité, c'est inutile car c'est le principe de random()
    while i < 2:
        if flaga==0 and flagc==0: #A tire sur C
            x=random()
            if x < prob[0]:
                flagc=1
                i+=1
                tab[2]+=1
        elif flaga==0 and flagc==1: #A tire sur B
            x=random()
            if x > 1-prob[0]:
                flagb=1
                i+=1
                tab[1]+=1
        if flagb==0 and flagc==0: # B tire sur C
            y=random()
            if y < prob[1]:
                flagc=1
                i+=1
                tab[2]+=1
        elif flagb==0 and flaga==0: # B tire sur A
            y=random()
            if y > 1-prob[1]:
                flaga=1
                i+=1
                tab[0]+=1
        if flagc==0 and flagb==0: # C tire sur B
            z=random()
            if z < prob[2]:
                flagb=1
                i+=1
                tab[1]+=1
        elif flagc==0 and flaga==0: # C tire sur A
            z=random()
            if z > 1-prob[2]:
                flaga=1
                i+=1
                tab[0]+=1

print(cpt,tab)
       
 

Je vais un peu compliquer le truc en tirant au sort l'ordre des tireurs, ça devrait être piquant à faire.

Dernière modification par freddy (16-05-2020 12:37:12)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#7 18-05-2020 00:15:46

Mohspace
Invité

Re : Comment "aller vers" en Python

Salut,

Je te propose un autre code python pour ton problème. Le code est dispo sur :
https://colab.research.google.com/drive … sp=sharing

Il est construit de manière à faciliter sa généralisation. Tu trouveras dans le lien une généralisation à n tireurs ainsi qu'une autre variante avec choix aléatoire du tireur cible (dans les deux premiers cas, on cible le meilleur encore en vie).

Happy coding :)

#8 18-05-2020 06:35:39

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut,

ah oui, très intéressant, je ne maîtrise pas encore les bases du code, notamment la gestion astucieuse des listes,et donc j'ai fait un truc bourrin, ce WE, amusant pas vraiment satisfaisant. Toi, t'as fait le truc qui généralise bien, bravo ! Je vais regarder avec attention.


from random import *
from time import time

play=[[1,0.25,0],[2,0.5,0],[3,0.75,0]] #les joueurs vivants
U=[2,0,1] # l'ordre de tir d'origine
sum=[0,0,0]
tab=[0,0,0] #la table des résultats cumulés
n=6000 #le nombre d'essai

for cpt in range(n):
    x=y=z=i=0
    for q in range(3):
        play[q][2]=0
   
    seed=time() #en réalité, c'est inutile car c'est le principe de random()
    sum[U[0]]+=1 #pour vérifier que le brassage est équitable
   
    while i < 2:
        if play[U[0]][2]==0 and play[U[2]][2]==0: # 1 tire sur 3
            x=random()
            if x < play[U[0]][1]:
                play[U[2]][2]=1
                i+=1
                tab[U[2]]+=1
        elif play[U[0]][2]==0 and play[U[1]][2]==0: # 1 tire sur 2
            x=random()
            if x > 1-play[U[0]][1]:
                play[U[1]][2]=1
                i+=1
                tab[U[1]]+=1
               
        if play[U[1]][2]==0 and play[U[2]][2]==0: # 2 tire sur 3
            y=random()
            if y < play[U[1]][1]:
                play[U[2]][2]=1
                i+=1
                tab[U[2]]+=1
        elif play[U[1]][2]==0 and play[U[0]][2]==0: # 2 tire sur 1
            y=random()
            if y > 1-play[U[1]][1]:
                play[U[0]][2]=1
                i+=1
                tab[U[0]]+=1
        if play[U[2]][2]==0 and play[U[1]][2]==0: # 3 tire sur 2
            z=random()
            if z < play[U[2]][1]:
                play[U[1]][2]=1
                i+=1
                tab[U[1]]+=1
        elif play[U[2]][2]==0 and play[U[0]][2]==0: # 3 tire sur 1
            z=random()
            if z > 1-play[U[2]][1]:
                play[U[0]][2]=1
                i+=1
                tab[U[0]]+=1
        #print(cpt,U,play,tab)
        shuffle(U)

print(sum,tab)
 


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#9 18-05-2020 06:41:55

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Je recopie le code, pour tout le monde !


#base à 3 joueurs
from random import random

Proba = {'A': 0.2, 'B': 0.5, 'C': 0.8} #shooter list from weaker to stronger
DeathCount = {'A': 0, 'B': 0, 'C': 0}
nbiterations = 1000

for k in range(nbiterations):
  Alive = ['A', 'B', 'C']
  while(len(Alive) > 1):
    i = 0
    while(i < len(Alive)):
      shooter = Alive[i]
      copylist = Alive.copy()
      copylist.remove(shooter)
      target = copylist.pop() # cible = meilleur tireur dans copylist
      if(random() <= Proba[shooter]):
        DeathCount[target] += 1
        Alive.remove(target)
      i += 1

print(DeathCount)

#n joueurs qui tirent sur le meilleur survivant

from random import random
import numpy as np

nbopponents = 20

Proba = {} #shooter list from weaker to stronger
DeathCount = {}
opponentlist = []

probavalues = np.random.rand(nbopponents)
probavalues.sort()

for k in range(nbopponents):
  Proba[k] = round(probavalues[k],2)
  DeathCount[k] = 0
  opponentlist.append(k)

nbiterations = 1000

for k in range(nbiterations):
  Alive = opponentlist.copy()
  while(len(Alive) > 1):
    i = 0
    while(i < len(Alive)):
      shooter = Alive[i]
      copylist = Alive.copy()
      copylist.remove(shooter)
      target = copylist.pop() # cible = meilleur tireur dans copylist
      if(random() <= Proba[shooter]):
        DeathCount[target] += 1
        Alive.remove(target)
      i += 1

print(DeathCount)

#n joueurs et cible aléatoire

from random import random, choice # choice pour choisir aléatoirement dans une liste
import numpy as np

nbopponents = 20

Proba = {} #shooter list from weaker to stronger
DeathCount = {}
opponentlist = []

probavalues = np.random.rand(nbopponents)
probavalues.sort()

for k in range(nbopponents):
  Proba[k] = round(probavalues[k],2)
  DeathCount[k] = 0
  opponentlist.append(k)

nbiterations = 1000

for k in range(nbiterations):
  Alive = opponentlist.copy()
  while(len(Alive) > 1):
    i = 0
    while(i < len(Alive)):
      shooter = Alive[i]
      copylist = Alive.copy()
      copylist.remove(shooter)
      target = choice(copylist) #choix de cible aléatoire
      if(random() <= Proba[shooter]):
        DeathCount[target] += 1
        Alive.remove(target)
      i += 1

print(DeathCount)
 

Astucieux l’usage du pop de la liste !!!

PS : c'est une belle leçon sur l'usage des propriétés des listes sur Python, c'est pas mal. Quand je vois ce que j'ai fait, je me dis que je suis profondément marqué par les deux langages dont je me suis servi durant ma vie professionnelle, ça se perçoit bien :-)

Dernière modification par freddy (18-05-2020 11:14:40)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#10 18-05-2020 11:38:09

Mohspace
Invité

Re : Comment "aller vers" en Python

@freddy: J'espère que ça t'aidera pour monter en puissance avec Python car c'est un langage qui permet de faire plein de choses très vite (temps passé à coder, pas forcément le temps d'exécution). Je t'encourage à te documenter sur les structures de données : listes (aussi piles et files), sets, maps/dictionnaires ... et surtout comment les utiliser de manière pratique.
Pour répondre à ta question sur les goto, leur utilité est réelle dans des contextes très particuliers et dans des langages proches de la machines (Assembleur voire C, Fortran, ...): leur but étant d'optimiser le nombre de micro opérations exécutées. De nos jours, pour le grande majorité des programmeurs, ces soucis ne se posent plus : les machines sont très performantes + les compilateurs/interpréteurs sont pas mal optimisés pour faire le job à notre place :)
Merci en tout cas pour cet exercice très intéressant !

#11 18-05-2020 14:00:53

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Mohspace a écrit :

@freddy: J'espère que ça t'aidera pour monter en puissance avec Python car c'est un langage qui permet de faire plein de choses très vite (temps passé à coder, pas forcément le temps d'exécution). Je t'encourage à te documenter sur les structures de données : listes (aussi piles et files), sets, maps/dictionnaires ... et surtout comment les utiliser de manière pratique.
Pour répondre à ta question sur les goto, leur utilité est réelle dans des contextes très particuliers et dans des langages proches de la machines (Assembleur voire C, Fortran, ...): leur but étant d'optimiser le nombre de micro opérations exécutées. De nos jours, pour le grande majorité des programmeurs, ces soucis ne se posent plus : les machines sont très performantes + les compilateurs/interpréteurs sont pas mal optimisés pour faire le job à notre place :)
Merci en tout cas pour cet exercice très intéressant !

Salut et merci beaucoup !

Si tu vas sur la partition "énigmes …", il y a quelques sujets du même acabit où on peut s'amuser à pythonner, sans compter les problèmes de proba que certains nous posent, tu y croiseras l'ami yoshi qui s'amuse comme un fou :-)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#12 18-05-2020 16:38:20

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Comment "aller vers" en Python

Re,

freddy a écrit :

Quand je vois ce que j'ai fait, je me dis que je suis profondément marqué par les deux langages dont je me suis servi durant ma vie professionnelle, ça se perçoit bien :-)

Ne te désole pas, tu devrais savoir que c'est en sciant que Léonard devint scie...
Tu as déjà produit, en un temps record, un code fonctionnel : c'est déjà bien.
Maintenant tu vas pouvoir (et devoir), pour chaque code produit, te demander comment comment  tu peux raccourcir ton code et quels objets, quelles fonctions Python pourrait bien disposer pour ça...
Et Python dispose de tant de bibliothèques intégrées, et il y en a encore tant qu'on peut surajouter pour le calcul scientifque (numpy + scipy + matpoltlib), jongler avec les images, les pdf, les html, le xml, commander les Raspberry qu'on découvre des nouveaux trucs peut-être pas chaque jour, mais pas loin...
Tiens, je pensais tout savoir(ou presque) sur les listes ou sur print au choix :
j'en étais resté à :

>>> L=[1,2,3,4]
>>> print(L)
[1, 2, 3, 4]
>>>

qui affiche la liste...
Et il y a 2 jours, je suis tombé sur :

>>> print(*L)
1 2 3 4
>>>

Dans l'idle de Python, si tu veux tout savoir sur une fonction, tu tapes help(nomfonction)...
Exemple :

>>> help(print)
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
   
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

>>>

Deux points sur lesquels je voudrais attirer ton attention :

Proba = {'A': 0.2, 'B': 0.5, 'C': 0.8} #shooter list from weaker to stronger

Là, il a listé les tireurs, mais il n'a pas utilisé l'objet Python list, mais l'objet dict : un dictionnaire, ensemble non ordonné d'objets de type Clé : valeur :

>>> help(dict)
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
   
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.

>>> help(dict)
Help on class dict in module builtins:

class dict(object)
 |  dict() -> new empty dictionary
 |  dict(mapping) -> new dictionary initialized from a mapping object's
 |      (key, value) pairs
 |  dict(iterable) -> new dictionary initialized as if via:
 |      d = {}
 |      for k, v in iterable:
 |          d[k] = v
 |  dict(**kwargs) -> new dictionary initialized w ith the name=value pairs
 |      in the keyword argument list.  For example:  dict(one=1, two=2)
 |  
 |  Methods defined here:
 |  
 |  __contains__(self, key, /)
 |      True if D has a key k, else False.
 |  
 |  __delitem__(self, key, /)
 |      Delete self[key].
 |  
 |  __eq__(self, value, /)
 |      Return self==value.
 |  
 |  __ge__(self, value, /)
 |      Return self>=value.
 |  
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |  
 |  __getitem__(...)
 |      x.__getitem__(y) <==> x[y]
 |  
 |  __gt__(self, value, /)
 |      Return self>value.
 |  
 |  __init__(self, /, *args, **kwargs)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |  
 |  __iter__(self, /)
 |      Implement iter(self).
 |  
 |  __le__(self, value, /)
 |      Return self<=value.
 |  
 |  __len__(self, /)
 |      Return len(self).
 |  
 |  __lt__(self, value, /)
 |      Return self<value.
 |  
 |  __ne__(self, value, /)
 |      Return self!=value.
 |  
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  
 |  __repr__(self, /)
 |      Return repr(self).
 |  
 |  __setitem__(self, key, value, /)
 |      Set self[key] to value.
 |  
 |  __sizeof__(...)
 |      D.__sizeof__() -> size of D in memory, in bytes
 |  
 |  clear(...)
 |      D.clear() -> None.  Remove all items from D.
 |  
 |  copy(...)
 |      D.copy() -> a shallow copy of D
 |  
 |  fromkeys(iterable, value=None, /) from builtins.type
 |      Returns a new dict w ith keys from iterable and values equal to value.
 |  
 |  get(...)
 |      D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.
 |  
 |  items(...)
 |      D.items() -> a set-like object providing a view on D'
s items
 |  
 |  keys(...)
 |      D.keys() -> a set-like object providing a view on D's keys
 |  
 |  pop(...)
 |      D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
 |      If key is not found, d is returned if given, otherwise KeyError is raised
 |  
 |  popitem(...)
 |      D.popitem() -> (k, v), remove and return some (key, value) pair as a
 |      2-tuple; but raise KeyError if D is empty.
 |  
 |  setdefault(...)
 |      D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D
 |  
 |  update(...)
 |      D.update([E, ]**F) -> None.  Update D from dict/iterable E and F.
 |      If E is present and has a .keys() method, then does:  for k in E: D[k] = E[k]
 |      If E is present and lacks a .keys() method, then does:  for k, v in E: D[k] = v
 |      In either case, this is followed by: for k in F:  D[k] = F[k]
 |  
 |  values(...)
 |      D.values() -> an object providing a view on D'
s values
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  __hash__ = None
 

Peut-être ne t'es-tu pas encore demandé pourquoi il était écrit
copylist =Alive.copy()
et pas simplement :
copylist =Alive ?
Bin, c'est qu'il n'est pas tombé dan le "piège" qui surprend tous ceux qui ne l'avaient pas encore rencontré
Exemple :

L=[1,2,3,4]
print(L)
[1,2,3,4]
M=L
print(M)
[1,2,3,4]
M[2]=7
print(M)
[1,2,7,4]

Jusque-là, rien que de très normal...
Oui, sauf que :

print(L)
[1,2,7,4]

Pourtant, là, tu es sûr de pas avoir touché à  la liste L !!!
Certes, mais M n'est pas une copue de L, c'est un alias de L, L et M sont le même objet !
D'où le copy(). Cf https://docs.python.org/fr/3/library/copy.html

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#13 18-05-2020 20:11:22

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Hello,

Je pense qu’il faut que je fasse quelques exos d’application pour bien capter les trucs spécifiques, sinon, les vieux réflexes vont rester. Je vais chercher ça !

PS : et merci à yoshi pour l’interprétation des outils du code du camarade, ça facilite bien la lecture. J’aime bien ce code et je comprends pourquoi il est enseigné au lycée, il est souple et assez intuitif, mais comme pour une langue vivante, il faut avoir du vocabulaire et bien connaître sa grammaire :-)

Dernière modification par freddy (19-05-2020 07:16:18)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#14 21-05-2020 09:48:33

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut,

Pour répondre à yoshi, en effet, les fonctions sont une forme moderne des subroutine et des Goto. Merci ! Je travaille sur le code du jeu de la roulette, pour m’entraîner !


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#15 23-05-2020 23:11:13

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Hello,

et voilà le boulot, je suis preneur d'idées et méthodes pour raccourcir le code, en particulier pour saisir toutes les situations de pari à la roulette française.

PS : je pense que j'ai assez bien amélioré, l'outil est vraiment souple !


# Code d'une simulation du jeu de la roulette au casino
# Pour info, à ce jour, je ne suis jamais entré dans un casino, sauf pour y faire des courses :-)

from random import randrange, randint

# Déclaration des variables de départ et fabrication des listes de paris possibles
capital = 5000 # On a 1000 € au début du jeu
plafond = 15000 # montant de la capital acquise qui me fait quitter la table
temps = 100 # je quitte la table au bout de "temps" parties pour mon équilibre mental
richesse = capital # mesure de la richesse max détenue au cours de la partie
borne_inf = 1
borne_sup = 151

liste=[i for i in range(37)] # 36 numéros pleins qui paient 35 fois la mise
listebis=["Rouge","Noir","Manque","Passe","Pair","Impair"] # les chances simples qui paient une fois la mise
liste.extend(listebis)

# liste des gains par multipe et les chances associées, logiquement
        # on commence par les douzaine, regroupement de 12 numéros, soit par colonne, soit dans un groupe, ils paient 2 fois la mise
colonne_1 = [i for i in range(1,35,3)] # rang 43
colonne_2 = [i for i in range(2,36,3)] # rang 44
colonne_3 = [i for i in range(3,37,3)] # les 3 jeux sur les 3 douzaines en colonne rang 43 à 45
douzaine_1 = [i for i in range(1,13)] # rang 46
douzaine_2 = [i for i in range(13,25)] # rang 47
douzaine_3 = [i for i in range(25,37)] # rang 48

liste.append(colonne_1)
liste.append(colonne_2)
liste.append(colonne_3)
liste.append(douzaine_1)
liste.append(douzaine_2)
liste.append(douzaine_3)

        # on organise les transverses de rang 49 à 60 qui paient 11 fois la mise
transverse=[[i,i+1,i+2] for i in range(1,35,3)]
liste.extend(transverse)

        # on ajoute les sizains qui paient 5 fois la mise, 11 éléments, de rang 61 à 71
sizain=[[i for i in range(1,7)],[i for i in range(4,10)],[i for i in range(7,13)],[i for i in range(10,16)],[i for i in range(13,19)],[i for i in range(16,22)],
        [i for i in range(19,25)],[i for i in range(22,28)],[i for i in range(25,31)],[i for i in range(28,34)],[i for i in range(31,37)]]
liste.extend(sizain)

        # au tour des carrés du rang 72 à 93 qui paient 8 fois la mise
carre=[[i,i+1,i+3,i+4] for i in range(1,32,3)]
carre_1=[[i,i+1,i+3,i+4] for i in range(2,33,3)]
carre.extend(carre_1)
liste.extend(carre)

        # et enfin les paris à cheval sur deux nombres adjacents 57 éléments, ils paient 17 fois la mise
cheval = [[i,i+3] for i in range(1,34)]
cheval_1 = [[i,i+1] for i in range(1,35,3)]
cheval_2 = [[i+1,i+2] for i in range(1,35,3)]
cheval.extend(cheval_1)
cheval.extend(cheval_2)
liste.extend(cheval)

        # je ne traite pas pour l'instant des mises à cheval sur les groupes de douze numéro qui paient une demi fois la mise :-)
print(len(carre))
print(len(sizain))
print(len(cheval))
print(len(liste))
print(liste)

noir=[2,4,6,8,10,11,13,15,17,20,22,24,26,28,29,31,33,35]
rouge=[1,3,5,7,9,12,14,16,18,19,21,23,25,27,30,32,34,36]

continuer_partie = True # Booléen qui est vrai tant qu'on continue à jouer
cpt=0 # va décompter le nombre de paris effectués
Win=[0,0] # montant des gains et nombre de paris gagnés
TabWin = [0 for i in range(36)] # nombre de gain par multiple

print("Vous vous installez à la table de roulette avec pour ", capital, "€ en plaque de jeu")

while continuer_partie: # Tant qu'on doit continuer la partie
    # on demande à l'utilisateur de saisir le nombre sur lequel il va miser
    # on convient que 37 = rouge, 38 = noir, 39 = manque, 40 = passe, 41 = pair et 42 = impair
    cpt += 1
    richesse = max(richesse, capital)
    # On sélectionne le montant du pari
    mise = 0
    if capital/10 > 1:
        mise =randint(1,min(30,capital/10))*10 # mise aléatoire de 10, 20, ... 50 euros
    else:
        mise=capital # il joue tout son tapis
    #print("montant du pari =",mise, "€")
    # Numéro parié
    nombre_mise = randint(borne_inf,borne_sup)
    if nombre_mise < 37:
        print("  vous avez misé",mise,"€ sur le numéro",liste[nombre_mise], " qui paie 35 fois la mise !!! ... Rien ne va plus")
    elif nombre_mise in [i for i in range(37,43)]:
        print("     vous jouez une chance simple",liste[nombre_mise], " qui paie une fois la mise ! ... Rien ne va plus")
    else:
        print("   vous avez joué ",mise,"€ sur",liste[nombre_mise], " qui paie",int((36-len(liste[nombre_mise]))/len(liste[nombre_mise])),"fois la mise !... Rien ne va plus")
       

    # Le nombre misé et le montant de la mise ont été sélectionnés par l'utilisateur, on fait tourner la roulette, rien ne va plus !
    # Tirage
    numero_gagnant = randrange(37)
    if numero_gagnant > 0:
        if numero_gagnant in noir:
            couleur="Noir"
        else:
            couleur="Rouge"
        if numero_gagnant % 2 ==0:
            parite="Pair"
        else:
            parite="Impair"
        if numero_gagnant <= 18:
            long="Manque"
        else:
            long="Passe"
        print("  La roulette tourne... ... et s'arrête sur le numéro", numero_gagnant,couleur,parite,"et",long)
       
        # Résultat et calcul des gains éventuels

        if nombre_mise <= 36:
            if numero_gagnant == nombre_mise:
                print(" Félicitations ! Votre gain est égal à ", mise * 35, "€ !")
                capital += mise * 35
                Win[0]+= mise * 35
                Win[1]+=1
                TabWin[35] += 1
            else:
                print("    Bad luck, you lose !")
                capital -= mise
                TabWin [0] += 1
               
        elif nombre_mise in [i for i in range(37,43)]:
            if nombre_mise in [liste.index(couleur), liste.index(parite), liste.index(long)] :
                print("  Vous avez misé sur la bonne chance simple. Vous obtenez", mise, "€")
                capital += mise
                Win[0]+=mise
                Win[1]+=1
                TabWin[1] += 1
            else:
                print(" Même là, sur une chance simple, quand ça ne veut pas, ça ne veut pas !")
                capital -= mise
                TabWin [0] += 1
               
        elif nombre_mise > 42 and numero_gagnant in liste[nombre_mise]:
            mu=len(liste[nombre_mise])
            mu=int((36-mu)/mu)
            print("     Goof job guy, you win",mise*mu,"€")
            capital+=mise*mu
            Win[0]+=mise*mu
            Win[1]+=1
            TabWin[mu] += 1
                       
        else:
            print("  combinaison : Désolé, ce ne sera pas pour cette fois, vous perdez votre mise !")
            capital -= mise
            TabWin[0] += 1

    else:
        if nombre_mise > 36:
            print(" Désolé, le zéro rafle les mises")
            capital -= mise
            TabWin[0] += 1
        else:
            while numero_gagnant <=0:
                print("il faut relancer la bille car le 0 est sorti")
                numero_gagnant = randrange(37)
                print("La roulette tourne...  rien ne va plus ... et voilà le numéro gagnant :", numero_gagnant)
                if numero_gagnant == nombre_mise:
                    print("Bingo,le numéro sorti est le vôtre, la table rembourse votre mise de",mise,"€")
                    TabWin[0] += 1
                else:
                    print("Désolé, c'est perdu")
                    capital -= mise
                    TabWin[0] += 1
       
    # On interrompt la partie si le joueur est ruiné
    if capital <= 0:
        print("  Vous êtes ruiné cher ami ! C'est la fin de la partie, salut et bon retour !")
        continuer_partie = False
    elif capital >= plafond:
        richesse=max(richesse,capital)
        print("        Pour le personnel, merci!")
        continuer_partie = False
    elif cpt >= temps:
        richesse=max(richesse,capital)
        print("  Bonsoir messieurs, j'en ai assez, merci, je rentre avec",capital," €, j'ai gagné dans la soirée", Win[0]," c'est assez pour moi !")
        continuer_partie = False
    else:
        # On affiche la capital du joueur
        print("Vous disposez de ", capital, "€ et avez joué",cpt,"fois")
        if cpt % 100 == 0:
            quitter = input("Souhaitez-vous quitter la table (o/n) ? ")
            if quitter == "o" or quitter == "O":
                print("Vous quittez le casino après avoir gagné ",Win[1],"fois et",Win[0],"€")
                continuer_partie = False
    print("          ***")
       
print("Merci de la visite, vous avez joué",cpt,"fois, au revoir et à bientôt")
print("Vous quittez le casino après avoir gagné ",Win[1],"fois et",Win[0],"€ et détenu jusqu'à",richesse,"€")
print(TabWin)

 

Dernière modification par freddy (24-05-2020 19:44:19)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#16 24-05-2020 08:53:46

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Comment "aller vers" en Python

Re,

Joli, bel effort... Il fallait oser !

J'ai essayé de comprendre le jeu de roulette : j'ai fouillé la toile et je n'ai rien trouvé de clair.
A part que la rolette tourne ave la bille et qu'elle finit par s'arrêter sur un n° compris entre 0 et 36, que les cases sont
verte pour le 0
noires pour les impairs
rouges pour les pairs.
Point barre....
Mais il y a tellement de paris possibles qu'il y a de quoi se noyer...

Et dire que j'ai lu  que c'était le jeu de Casino le plus simple !!!
https://www.canaafrica.org/wp-content/u … ulette.jpg
Le jeu d'échecs, c'est une rigolade à côté...
Donc pour l'instant, tout ce que je peux dire  c'est que ton code est probablement améliorable mais que j'en serai parfaitement incapable tant que je n'aurai pas maîtrisé la subtilité du jeu. Et ce n'est pas pour demain, hélas.
En plus, pour une décade encore, j'ai d'autres priorités.

Désolé.

@+
.


Arx Tarpeia Capitoli proxima...

Hors ligne

#17 24-05-2020 09:47:42

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut !

Tu me flattes ! En réalité, c’est assez simple et le code l’est tout autant, il faut en revanche construire la liste des paris possibles, c’est le plus long. J’avais oublié le sizain, je viens de l’intégrer.

Pour les paris, il faut avoir devant soi une table de roulette pour comprendre les combinaisons qui sont très visuelles : un numéro seul ou deux numéros adjacents ou 3 numéros sur la même ligne transverse ou 4 numéros adjacents ou ..
Le principe est que plus tu joues de numéros, plus tu as de chance de gagner et bien sûr, moins tu gagnes si le numéro rentre. Je vais mettre le lien sur tous les paris possibles.

En faisant des simulations, j’ai compris pourquoi les gens jouaient : on perd sur la distance, l’espérance mathématique est négative, mais on peut un peu gagner de temps en temps, et donc, on a envie de rester à la table de jeu. Mais il faut avoir un peu d’argent aussi car accepter de perdre 1.000 € en une seule soirée n’est pas donné à tout le monde.

Et c'est encore un peu plus pernicieux car avec 1.000 €, on sort vite de la table, et donc, il faut venir avec plus pour espérer ne pas trop perdre dans la soirée, avec le risque de tout perdre tout de même ... On voit bien à quelle classe sociale c'était finalement réservé :-)

PS : pour les paris, j'avais trouvé ça, assez simple à comprendre.

Dernière modification par freddy (24-05-2020 10:20:24)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#18 25-05-2020 07:52:24

LEG
Membre
Inscription : 19-09-2012
Messages : 690

Re : Comment "aller vers" en Python

Bonjour
@Freddy : et si tu parts du principe de jouer un seul numéro, tu as 5000€ à perdre , tu attends 20 tours de roulette avant de jouer ton n° plein , qui n'est pas encore sortie, par exemple le 11.
Ensuite tu commences à miser 1€ , et  à chaque tour tu rajoutes un € : 1,2,3, 4.....> soit : (n*(n+1)) / 2 = 5000€ .
Est-ce que tu vas sortir gagnant, ou tu auras perdu tes 5000€ .... Autrement dit, plus tu perds plus tu risque de gagner plus ....?

Dernière modification par LEG (25-05-2020 08:01:43)

Hors ligne

#19 25-05-2020 09:22:48

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut,

Tu entres dans l’analyse des martingales possibles pour gagner à la roulette. Celle là est le paradoxe de Saint Petersbourg qui suppose, comme toutes les autres, de disposer d’une richesse infinie. Les casinos ont fini par plafonner les mises et donc, plus de sujet. Le mien est de coder une situation pour apprendre le code, le reste ne m’intéresse pas vraiment, désolé.

Là, je vais voir à coder un autre petit sujet, toujours pour m’entraîner. Si tu as des idées, je suis preneur !


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#20 25-05-2020 11:59:19

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Comment "aller vers" en Python

Salut

Proposition :

C=0.12345678910111213141516171819202122232425 ... (Nombre de David Champer)
1) Quelle est la 49e décimale ? la 234e  ? la 500e ? la 1000e ?
2)  Déterminer la somme des 49 premières décimales, des 234 premières, 500 premières,  1000 premières...
3) Pouvez-vous trouver votre date d'anniversaire (03071988) dans les décimales de C? Si oui combien de fois ? Expliquer votre réponse.

Tu mets ta date si tu veux, c'est celle de l'une de mes filles...

Ou alors, on avait travaillé ensemble sur le code CLE :

Salut voila j'ai un dm de math a faire:ce dernier comporte des exercices sur le système binaire et le code CLE.
Malgré quelques exemples,je n 'y arrive pas.Voici le contenu:
Ecrire en base 2 les nombres 9,21,100 et 157
Ecrire en base 10 le nombre qui s'écrit en code CLE (7;5;3;1)
Ecrire en code cle les nombres en base 10 suivants;359,250 et 128
A quoi reconnait on un nombre ecrit en code cle impair ,pair et une puissance de 2
ensuite écrire en code cle la somme 15 cle + 15 cle (ceci est la moitié de mon dm,les réponses fournises me peremettront de m'aidé et de pouvoir peut être y arrivé seul)
S'il vous plait si quelqu'un y arrive qu'il m'aide car je suis totalement perdu.Je voudrais si possible des réponses clair.
Merci d'avance

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#21 26-05-2020 09:23:43

Mohspace
Invité

Re : Comment "aller vers" en Python

Salut

Je vous propose un classique : Soit un ensemble de points sur un plan (2D). Trouver le nombre maximum de points alignés (se trouvant sur la même droite).

Exemple :
Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Illustration:
^
|
|  o
|      o         o
|         o
|  o         o
+------------------->
0  1  2  3  4  5  6

Output: 4

#22 26-05-2020 09:51:56

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Bonjour yoshi,

je ne vais pas te faire injure, j'ai vu que tu avais posté à ce sujet ! Mais je n'ai que vu, pas lu, donc je vais essayer de faire un truc qui répond à ta première question.

Pour la question de la date anniversaire, si au début, elle interroge, très vite, on comprend qu'il s'agit ni plus ni moins que d'un nombre qu'on verra apparaître à un moment donné dans la fabrication du nombre de Champer - en réalité, il s'agit de la constante de Champernowne, économiste et mathématicien anglais - (d'ailleurs, on aurait aussi pu écrire 19910728 = mon petit dernier) et la réponse est immédiate : ben oui, il est certain qu'on le rencontrera, et mieux que ça, on le rencontrera un nombre infini dénombrable de fois puisque on aura par exemple 15 031 989 (mon petit second) une fois, puis 115 031 989 une seconde fois puis 215 031 989 une troisième fois … usw ! Il est très amusant, ce nombre de Champernowne, je ne connaissais pas.
Pour finir, je sais qu'on rencontrera aussi ce nombre 23081981150319892807199125032017 et pas qu'une seule fois, je te laisse devine ce qu'il représente :-)

Après, je vais aussi regarder la CLE, mais je crois que tu as aussi écrit là-dessus, je vais éviter de te regarder ;-)

PS : j'ai passé un petit moment à remonter cette constante, je connaissais l'économiste-statisticien mais pas le mathématicien. Je cherchais une formule pour la construire, j'ai compris que ça ne servirait à rien pour chercher sa nième décimale, sujet classique en programmation si j'ai bien compris. Maintenant, je peux réfléchir à une méthode :-), c'est un joli sujet !

Dernière modification par freddy (31-05-2020 20:42:53)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#23 01-06-2020 22:50:40

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Hello,

voici une réponse à la première question de yoshi.
L'idée de ce code repose sur le calcul du nombre de décimale entre deux intervalles du genre 99 et 999, puis 999 et 9999,  ...
Entre chacune de ces bornes, le nombre de décimale est égal à $9\times n\times 10^{n-1}$, où $n$ est le nombre de décimale de la borne supérieure : 1 (unité), 2 (dizaine), 3 (centaine), …

Ainsi, on a $9$ décimales de 1 à 9, ou $9+2\times 9\times 10 =189$ de 1 à 99, ou $9+2\times 9\times 10 + 3\times 9\times 10^2 =2.889$  de 1 à 999, ou encore $9+2\times 9\times 10 + 3\times 9\times 10^2+ 4\times 9\times 10^3 =38.889$ de 1 à 9.999 et ainsi de suite. Donc on cherche à savoir dans quel intervalle se positionne le nombre de décimale en question, puis on déduit le nombre concerné et le chiffre dans ce nombre grâce à une petite division euclidienne.

Le code que je propose n'est rien d'autre que la programmation de la méthode que j’utilise pour résoudre le problème à la main.
J'espère qu'il n'y a pas d'erreur et je regarde la seconde question :-)


# procedure pour trouver une décimale précise de la constante C de Champernowne
from random import randint
n=int(input("entrez un nombre entier quelconque : ", ))
if n <= 0:
    n=randint(10,2500000)
digit=9
rang=9
cpt=1
numer=n
if n > 9 :
    while n > digit :
        cpt+=1
        digit +=9*cpt*10**(cpt-1)
        rang += 9*10**(cpt-1)
       
    rang -=9*10**(cpt-1)
    digit -= 9*cpt*10**(cpt-1)
    n -= digit
    p,r = divmod(n,cpt)
    if r == 0:
        number=rang+p
    else:
        number=rang+p+1
    decompo = [int(c) for c in str(number)]
    print(number,n,p,r)
    print("la décimale de rang",numer,"est le chiffre ",decompo[r-1]," du nombre",number)

else:
    print("vous ne savez pas compter ?!!!")
 

la décimale de rang 49 est le chiffre  9 du nombre 29
la décimale de rang 234 est le chiffre  4 du nombre 114
la décimale de rang 500 est le chiffre  0 du nombre 203
la décimale de rang 1000 est le chiffre  3  du nombre 370

Dernière modification par freddy (02-06-2020 08:25:50)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

#24 02-06-2020 13:08:25

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Comment "aller vers" en Python

Bonjour,

C'est intéressant de constater qu'on ne pense pas de la même façon...
Et de voir qu'on est faillible !
J'ai voulu tester tes réponses avec un programme écrit, il y a quelques mois et j'ai vu qu'on était en désaccord sur mes 4 réponses
Donc, j'ai construit une constante avec 5000 premiers chiffres en partant de 1, donti j'ai en extrait les chiffres en position demandée : tu avais raison sur toute la ligne !
Invraisemblable... Je teste pourtant avant mise en ligne et les tests de l'époque étaient concluants : bin, je ne sais toujours pas comment les résultats de ces nouveaux tests peuvent être faux !
Bref, j'ai décidé de refaire mon algorithme en traduisant la méthode manuelle que j'expliquais aux 6e...

N=[49,234,500,1000]
lg=len(str(max(N)))
for pos in N:
    i,nbc=0,0
    while nbc<=pos:
        nbc_ant=nbc
        nbc+=nbc+=9*(i+1)*10**i
        i+=1
    ecart=pos-nbc_ant
    q,r=divmod(ecart,i)
    q+=(r>0)
    nop=str(10**(i-1)+q-1)
    print("+-+ Le "+str(pos).rjust(lg," ")+"e chiffre décimal est",str(nop)[(r-1)%i],"+-+")  

Sortie :

+-+ Le   49e chiffre décimal est 9 +-+
+-+ Le  234e chiffre décimal est 4 +-+
+-+ Le  500e chiffre décimal est 0 +-+
+-+ Le 1000e chiffre décimal est 3 +-+

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#25 02-06-2020 15:23:43

freddy
Membre chevronné
Lieu : Paris
Inscription : 27-03-2009
Messages : 7 457

Re : Comment "aller vers" en Python

Salut,

Et moi, j’ai encore des trucs à apprendre quand je lis ton code ! Mais bon, j’aime bien ce langage de programmation, il est simple, souple et subtil à la fois ! Le problème est que je ne le connais pas vraiment, je découvre, et donc je suis plus concentré sur ce que je veux faire que sur comment faire mieux, plus court et plus efficace, mais ça viendra !

Dernière modification par freddy (02-06-2020 22:39:13)


De la considération des obstacles vient l’échec, des moyens, la réussite.

Hors ligne

Pied de page des forums