π
<-
Chat plein-écran
[^]

Concours de rentrée 2019 - défi de Python

Re: Concours de rentrée 2019 - défi de Python

Message non lude critor » 17 Nov 2019, 17:36

Ne désespérez pas, les résultats arrivent. :)

L'annonce est déjà prête pour TI-Planet. Manque juste à finaliser celle pour Planète Casio.
Image
Avatar de l’utilisateur
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Prochain niv.: 41.4%
 
Messages: 41455
Images: 14353
Inscription: 25 Oct 2008, 00:00
Localisation: Montpellier
Genre: Homme
Calculatrice(s):
MyCalcs profile
YouTube: critor3000
Twitter/X: critor2000
GitHub: critor

Re: Concours de rentrée 2019 - défi de Python

Message non lude Tituya » 17 Nov 2019, 17:42

Donc résultats ce soir ?
from hype import *

:p
Avatar de l’utilisateur
TituyaPremium
Niveau 8: ER (Espèce Rare: nerd)
Niveau 8: ER (Espèce Rare: nerd)
Prochain niv.: 97.3%
 
Messages: 13
Inscription: 15 Nov 2019, 00:02
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: DUT Info 1e Année

Re: Concours de rentrée 2019 - défi de Python

Message non lude Zocipal » 17 Nov 2019, 18:11

On a hâte !
Image
Avatar de l’utilisateur
ZocipalProgrammeur
Niveau 9: IC (Compteur Infatigable)
Niveau 9: IC (Compteur Infatigable)
Prochain niv.: 60.7%
 
Messages: 113
Inscription: 12 Sep 2019, 20:15
Localisation: Hauts-de-France
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: 1ère Maths Physique NSI

Re: Concours de rentrée 2019 - défi de Python

Message non lude critor » 17 Nov 2019, 20:06

Voilà, c'est fait, désolé pour l'attente : :)
viewtopic.php?f=49&t=23140&p=248090#p248088
Image
Avatar de l’utilisateur
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Prochain niv.: 41.4%
 
Messages: 41455
Images: 14353
Inscription: 25 Oct 2008, 00:00
Localisation: Montpellier
Genre: Homme
Calculatrice(s):
MyCalcs profile
YouTube: critor3000
Twitter/X: critor2000
GitHub: critor

Re: Concours de rentrée 2019 - défi de Python

Message non lude Afyu » 18 Nov 2019, 23:18

Voici comment j'ai procédé pour la résolution du défi Python dont j'ai découvert l'existence vers le 16 ou 17 octobre :

Après avoir effectué quelques test manuellement, j'ai écrit un programme en Python pour optimiser ma recherche.
J'ai récupéré la ressource NumWorks proposée pour le concours, que j'ai complétée.

L'idée est de tester des mains de 10 Pokémon et de comparer chaque nouveau score obtenu avec le meilleur score obtenu jusqu'à présent.

J'ai donc créé une liste qui va contenir le meilleur score (ou plutôt les meilleurs scores successifs obtenus au cours de la recherche).
J'aurais pu créer une variable globale pour stocker mon meilleur score, mais ne maitrisant pas la syntaxe pour ça, j'ai préféré créer une liste scoreliste qui s'allonge avec chaque nouveau meilleur score. Il suffit alors de prendre scoreliste[-1] pour récupérer le dernier élément, donc le meilleur score.
Et j'ai fait de même pour les codes avec codeliste. Par la suite, j'ai créé une variable score_max qui stocke la valeur scoreliste[-1].

Je tenais à avoir la liste des Pokémon et des puissances associées de chacun de mes meilleurs scores. C'est pour cette raison que j'affiche le meilleur score scoreliste[-1], le code associé codeliste[-1] ainsi que la liste des Pokémon pokemon et la liste des puissances associées attaque.

La première ligne est écrite avec un >= et non pas un > pour stocker un nouveau score s'il est meilleur que le dernier meilleur score obtenu, ou s'il est égal à ce dernier. C'est peut-être peu pertinent, mais ça permet de changer de temps en temps la liste des Pokémon ou des puissances sur laquelle le programme effectue ses tests, même si le meilleur score n'évolue plus.
Code: Tout sélectionner
if score>=score_max:
  atta.append(attaque[:])
  poke.append(pokemon[:])
  if score>score_max:
    print(scoreliste[-1],iii)
    print("#",score,codeliste[-1])
    print("# poke",poke[-1])
    print("# atta",atta[-1])
    print("")
  score_max=score


J'ai initialisé ma liste des Pokémon pokemon et ma liste des puissances attaque avec des 1, je crois.
Code: Tout sélectionner
pokemon=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] (ou pokemon=[1]*10)
attaque=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1] (ou attaque=[1]*10)

Je remplis la main avec la boucle :
Code: Tout sélectionner
for kkk in range(10):
  pk(pokemon[kkk],attaque[kkk])

Et je la vide avec la boucle :
Code: Tout sélectionner
for jjj in range(10):
  pk(pokemon[jjj],0)

J'ai commencé mes recherches en remplaçant une puissance d'attaque par un nombre tiré aléatoirement. Le rang de l'attaque est également choisi aléatoirement entre 0 et 9, ce qui désigne un des 10 Pokémon de la main.
Code: Tout sélectionner
rang=randint(0,9)
attaque[rang]=randint(1,200)


Dans un second programme, je cherche en modifiant non pas l'attaque des Pokémon, mais leur numéro parmi les 94 disponibles avec des nombres tirés aléatoirement, encore une fois :
Code: Tout sélectionner
rang=randint(0,9)
pokemon[rang]=randint(1,94)


Je récupère ma meilleure main de Pokémon, avec les puissances associées, et je fais travailler mes deux programmes sur chaque meilleure main trouvée, en la changeant lorsqu'elle est améliorée.

Après quelques essais (ici 10), je reprends ma recherche avec comme liste de départ la dernière meilleure main obtenue. Et j'effectue des changements sur cette main pour espérer améliorer mon score. Je ne repars pas d'une main totalement aléatoire à chaque fois que j'améliore mon meilleur score.
Code: Tout sélectionner
if nb_chgt==10:
  attaque=atta[-1] (ou pokemon=poke[-1] dans l'autre programme)


Après quelques min...jours de calculs, j'ai obtenu un score proche de 49,3154 avec O#0K_g^huS""1""h"""" mais qui est enregistré dans le tableau des participations sous un score un peu inférieur : 49,31486.
Mon meilleur score ne s'améliorant plus, j'ai changé mon approche. J'ai essayé de modifier les puissances d'attaque, mais de 1 en 1. Je choisis un Pokémon aléatoirement, dans ma meilleure main trouvée jusqu'alors et je modifie la puissance de ce Pokémon de 1. (donc j'ajoute 1 ou je retranche 1).
Code: Tout sélectionner
rang=randint(0,9)
attaque[rang]+=2*randint(0,1)-1


En tirant un entier aléatoirement valant 0 ou 1, puis en prenant son double (donc 0 ou 2) et enfin en lui retranchant 1, on obtient un entier qui vaut -1 ou 1.
Les deux lignes de code précédentes peuvent être compactées en une seule :
Code: Tout sélectionner
attaque[randint(0,9)]+=2*randint(0,1)-1

J'ai abandonné ma première syntaxe en une ligne :
Code: Tout sélectionner
attaque[randint(0,9)]=attaque[randint(0,9)]+2*randint(0,1)-1
au profit d'une écriture avec un += parce que les deux nombres tirés aléatoirement avec randint(0,9) sont très souvent différents, et ça ne m'intéresse pas.

Avec cette nouvelle approche, j'ai de nouveau pu améliorer mon meilleur score pour atteindre 49,31730 et même 49,31859 (le 19/10) et 49,31975 le 19/10 au soir !
Code: Tout sélectionner
49.31730339247606
'O#0K_g^huS""3""f""""'
poke [51, 85, 72, 62, 71, 63, 43, 16, 3, 47]
atta [4, 4, 61, 2, 2, 235, 3, 2, 3, 3]

49.3185945083636
'O#0K_g^huS""3""g""""'
poke [51, 85, 72, 62, 71, 63, 43, 16, 3, 47]
atta [2, 3, 61, 2, 2, 239, 2, 4, 2, 2]

Cette nouvelle approche m'a montré à chaque nouveau meilleur score que les puissances d'attaque de tous mes Pokémon se rapprochaient toujours plus de 2, sauf pour 2 Pokémon.
J'ai fini par essayer, à la main, des puissances d'attaque toutes égales à 2, sauf pour les deux Pokémon exception.
Et j'ai modifié mon programme pour que l'ajustement des puissances ne se fasse que pour les deux Pokémon exception.

Les deux Pokémon en question étant placés en position 2 et 5, j'ai donc modifié mon choix du rang pour :
Code: Tout sélectionner
rang=3*randint(0,1)+2
qui donne un nombre entier aléatoire qui vaut 2 ou 5.

Oui ? De quoi ? J'aurais pu tout simplement mettre les deux Pokémon en question en position 0 et 1 et tirer un nombre entier entre 0 et 1 avec randint(0,1) ? Euh...bah...euh... c'est pas faux. Bien vu ! pfff xD
Mais pourquoi faire simple quand on peut faire compliqué ? :D

Avec les deux dernières puissances proches de 60 et de 230, j'ai obtenu les scores 49,3188 et 49,3197. Puis pour des puissances d'attaque à 35 et à 143 et à 1 pour les 8 autres Pokémon, j'ai obtenu le score ultime de 49,3207 (le 21/10) !!
Code: Tout sélectionner
49.31975298152274
'O#0K_g^huS""3""h""""'
poke [51, 85, 72, 62, 71, 63, 43, 16, 3, 47]
atta [2, 2, 58, 2, 2, 234, 2, 2, 2, 2]

49.32078546995182
'O#0K_g^huS""3""i""""'
poke [51, 85, 72, 62, 71, 63, 43, 16, 3, 47]
atta [1, 1, 35, 1, 1, 143, 1, 1, 1, 1]

Super enthousiaste (naïvement ? Peut-être bien, oui... :(), j'envoie mes scores à Critor en espérant que la différence d'évaluation ne soit pas trop grande... et là c'est le drame ! Mes codes valent en fait 49,3151. La looooooose !

Je suis donc allé éplucher le forum et j'ai compris que les codes étaient passés dans la moulinette setst() pour retrouver le score et que c'est ce score qui est validé et ajouté dans le tableau des participations.
J'ai donc modifié mon programme en conséquence, en calculant le score avec setst("code_obtenu") avant de le comparer à mon meilleur score.
Code: Tout sélectionner
score=setst(codeliste[-1])

J'ai finalement compris (alors que c'était expliqué sur le forum, depuis le début du défi ! Mais quand on ne sait pas lire, hein...) que si la somme des puissances dépasse 100, alors toutes les puissances sont réduites par la fonction setst(), avec le même coefficient multiplicateur, pour que leur somme ne dépasse plus 100, puis arrondies à l'unité. Si les puissances réduites sont trop petites, alors l'arrondi à l'unité donne 0, ce qui explique la disparition de certains Pokémon de la main lorsqu'on ajoute un Pokémon avec une trop grande puissance.
La liste pkl contient le numéro de chaque Pokémon de la main, ainsi que sa puissance associée et un troisième nombre. Ce dernier nombre est la valeur retenue, après réduction et arrondi à l'unité.
J'ai donc découvert que mon 35 devient 18 et que mon 143 devient 72.
Pour respecter la proportionalité, il aurait au moins fallu avoir 17,5 et 71,5 (et 0,5 pour les 8 autres puissances, du coup ?).

Après quelques essais, j'ai vu que la somme des puissances pouvait être comprise entre 93 et 97. Mais même avec cette petite tolérance, je n'ai pas réussi à retrouver de très bons scores.

Après des heures de calcul, uniquement sur les deux puissances différentes de 1, pas moyen d'obtenir de nouveau un score supérieur à 49,3185... très déçu, j'abandonne et me lance dans la résolution du 3ème défi.
Le dernier jour ouvert pour la participation, vers 22h45, je me décide à lancer un ultime calcul. Le calcul de la dernière chance. Juste avant, je vais éplucher le forum, une fois encore, à la recherche d'une bonne idée. Je découvre qu'il est possible de passer des caractères codés avec un \ suivi d'un nombre. viewtopic.php?f=49&t=23011&start=190#p247491

J'ai sauté sur l'occasion et j'ai testé à la main quelques caractères écrits avec cette nouvelle écriture, jusqu'à retrouver mes 3 très bons scores au-dessus de 49,318 !! Un de ces trois scores n'avait pas encore été soumis, d'après le tableau des participations, alors j'en profite, j'envoie 2 mails (à 23h40 et 23h52 ! Plus que 8 min, tic tac tic tac !!).

Ces codes ressemblent à ça, le 35 et le 143 étant remplacés par des caractères codés avec un \ suivi d'une chaîne de caractère :
Code: Tout sélectionner
setst('O#0K_g^huS""\x3D""\x99""""')
49.318885384185236

setst('O#0K_g^huS""\x42""\xB2""""')
49.31951877543954

Et finalement, un participant est sorti de nulle part en soumettant 18 codes, en réservant la plupart des codes encore dispo, juste quelques heures avant moi.
Tant pis, je suis finalement 9ème. Mais je suis content d'avoir essayé jusqu'au bout et d'avoir trouvé une main qui donne un score de 49,3207 si on ne le repasse pas dans la moulinette setst() et qui n'utilise pas de caractères bizarres commençant par un \.

Je remercie grandement toutes les personnes qui ont permis à ce concours d'exister et qui ont permis d'avoir autant de lots très intéressants !

Je donne ici mon script complet, même pas nettoyé pour montrer mes traces de recherches.

Code: Tout sélectionner
#score=[]
codeliste=[0]
scoreliste=[0]
#cas
from math import *
def mmod(a,b):
  return a%b
#0 Nspire MicroPython
#1 NumWorks Python
#2 G90/35+E2 Python
#3 G75/85/95 CasioPython
#4 83PCE Python/PyAdapt
#5 HP Prime CAS
#6 G90/35+E2 KhiCAS
def getplatform():
  k=-1
  try:
    if chr(256)==chr(0):
      k=[6,5][("HP" in version())>0]
  except:
    pass
  if k>=0:
    return k
  try:
    import sys
    try:
      if sys.platform=="nspire":
        k=0
      elif sys.platform.startswith("TI-Python"):
        k=4
    except:
      k=3
  except:
    try:
      import kandinsky
      k=1
    except:
      k=2
  return k
def getlinechars(o=False):
  c,k=2**31-1,getplatform()
  if k>=0:
    c=[53,o and 99 or 29,o and 509 or 21,31,32,c,c][k]
  return c
lnm=["Bulbizarre","Herbizarre","Florizarre","Salameche","Reptincel","Dracaufeu","Carapuce","Carabaffe","Tortank","Chenipan","Chrysacier","Papilusion","Aspicot","Coconfort","Dardargnan","Roucool","Roucoups","Roucarnage","Rattata","Rattatac","Piafabec"]
lnm.extend(["Rapasdepic","Abo","Arbok","Pikachu","Raichu","Sabelette","Sablaireau","Nidoran F","Nidorina","Nidoqueen","Nidoran M","Nidorino","Nidoking","Melofee","Melodelfe","Goupix","Feunard","Rondoudou","Grodoudou","Nosferapti","Nosferalto"])
lnm.extend(["Mystherbe","Ortide","Rafflesia","Paras","Parasect","Mimitoss","Aeromite","Taupiqueur","Triopikeur","Miaouss","Persian","Psykokwak","Akwakwak","Ferosinge","Colossinge","Caninos","Arcanin","Ptitard","Tetarte","Tartard","Abra","Kadabra"])
lnm.extend(["Alakazam","Machoc","Machopeur","Mackogneur","Chetiflor","Boustiflor","Empiflor","Tentacool","Tentacruel","Racaillou","Gravalanch","Grolem","Ponyta","Galopa","Ramoloss","Flagadoss","Magneti","Magneton","Canarticho","Doduo","Dodrio","Otaria"])
lnm.extend(["Lamantine","Tadmorv","Grotadmorv","Kokiyas","Crustabri","Fantominus","Spectrum","Ectoplasma"])
na,pkl=21,[]
mrandmax,mrand,mfmax,nn,mp=2**31-1,0,93,getlinechars(True)-na,na//2
def mround(f):
  d=mmod(abs(f),1)
  return (mfloor(abs(f))+(d>=.5))*(1-2*(f<0))
def mfloor(f):
  return round(f)-(round(f)>f)
def mceil(f):
  return round(f)+(round(f)<f)
def mseed(s):
  global mrand
  mrand=mmod(s,mrandmax)
def mrandom():
  mseed(mrand*16807)
  return float(mrand/mrandmax)
def muniform(mini,maxi):
  return mrandom()*(maxi-mini)+mini
def mrandint(mini,maxi):
  return mround(muniform(mceil(mini),mfloor(maxi)))
def f2mf(f):
  return mround(float(f*mfmax))
def mf2f(n):
  return float(n/mfmax)
def mbit(a,b):
  return mmod((a//(2**b)),2)
def getattack(p,pts):
  global pkt
  mseed(42)
  for k in range(p+1):
    mrandom()
  a,pka=mrandint(1,mrandmax),""
  for j in range(na):
    if mbit(a,j)!=0:
      pka+="X"
      pkt[j]+=pts
    else:
      pka+=" -"[getplatform()>=5]
  return pka
def i2c(k):
  return chr(k+33)
def c2i(c):
  return ord(c)-33
def clean():
  global pkl
  t,s=0,0
  for l in pkl:
    t+=l[1]
  for l in pkl:
    l[2]=f2mf(l[1]/(t or 1))
    s+=l[2]
    if(l[2]<=0):
      pkl.remove(l)
      return clean()
  return s
def pk(n,p=1,d=2):
  global pkt, pkl
  n-=1
  if n>=0 and n<len(lnm):
    new=True
    for k in range(len(pkl)):
      if pkl[k][0]==n:
        new,pkl[k][1]=False,max(p,0)
    if new and len(pkl)<mp:
      pkl.append([n,max(p,0),0])
  ptt,pkt,t,st=clean(),[0 for k in range(na)],0,""
  for l in pkl:
    s=getattack(l[0],l[2]/ptt)
    if d:
      sn=" "+lnm[l[0]]
      if len(sn)>nn:
        sn=sn[:nn]
      #print(s+sn)
    st=i2c(l[0])+st+i2c(l[2])
  for k in pkt:
    if(k):
      t+=log(e+k*len(pkl))
  if(d):
    if(d>=2):
      #print("Bon score ? Si oui\nenvoie code suivant\na info@tiplanet.org :")
      scoreliste.append(float(t))
      codeliste.append(""+st)
      #score.append(setst(st))
    #print(""+st)
  return float(t)
def setst(st):
  s,pkl[:],n=0,[],len(st)//2
  for k in range(n):
    s=pk(c2i(st[n-1-k])+1,c2i(st[n+k+len(st)%2]),k+1>=n)
  return s
print("pk(n,p) pour rajouter\nle Pokemon n a ta main\navec p points d'attaque.")
#end




score_max=0
poke=[]
atta=[]
pokemon=[57, 72, 5, 43, 3, 69, 89, 62, 63, 16]
#attaque=[1, 1, 1, 1, 1, 1, 1, 1, 59, 236]
#pokemon=[51, 85, 72, 62, 71, 63, 43, 16, 3, 47]
#dd=9
attaque=[1, 1, 17, 1, 1, 68, 1, 1, 1, 1]
#pokemon=[1]*10
#attaque=[dd]*10
nb_chgt=0

from random import randint

for iii in range(50):
  #pokemon=[randint(1,94) for y in range(10)]
  #attaque=[randint(1,200) for y in range(10)]
  if iii>0: # et si iii vaut 0, on évite cette boucle et on ajoute un premier score non nul dans scoreliste
    #pokemon[randint(0,9)]+=2*randint(0,1)-1#randint(1,94)
    #rang=randint(0,9)
    rang=3*randint(0,1)+2
    #pokemon[randint(0,9)]=randint(1,94)
    #attaque[rang]-=1
    #attaque[rang]=max(attaque[rang]+2*randint(0,1)-1,1)
    #rang=randint(0,9)
    #rang=8-rang #3*randint(0,1)+2
    #pokemon[rang]=randint(1,94)
    #attaque[rang]=max(1,93-(sum(attaque[:])-attaque[rang]))
    #attaque[rang]=randint(1,50)
    attaque[rang]+=2*randint(0,1)-1
    #attaque[3*randint(0,1)+2]+=1*(2*randint(0,1)-1)
  for kkk in range(10):
    pk(pokemon[kkk],attaque[kkk])
  score=setst(codeliste[-1]) # ici le vrai score
  if score>=score_max:
    atta.append(attaque[:])
    poke.append(pokemon[:])
    #code=codeliste[-1]
    if score>score_max:
      print(scoreliste[-1],iii) # ici le score avant évaluation dans setst()
      print("#",score,codeliste[-1])
      #print("#",setst(code))
      print("# poke",poke[-1])
      print("# atta",atta[-1])
      print("")
    score_max=score
  for jjj in range(10):
      pk(pokemon[jjj],0)
  nb_chgt+=1
  if nb_chgt==20:
    #pokemon=poke[-1]
    attaque=atta[-1]
Dernière édition par Afyu le 25 Nov 2019, 20:35, édité 1 fois.
Avatar de l’utilisateur
AfyuVIP++
Niveau 15: CC (Chevalier des Calculatrices)
Niveau 15: CC (Chevalier des Calculatrices)
Prochain niv.: 89.2%
 
Messages: 339
Images: 18
Inscription: 30 Oct 2019, 19:17
Genre: Homme
Calculatrice(s):
MyCalcs profile
Classe: plutôt, oui :)

Re: Concours de rentrée 2019 - défi de Python

Message non lude critor » 18 Nov 2019, 23:52

Ah, merci à toi. :)
Image
Avatar de l’utilisateur
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Prochain niv.: 41.4%
 
Messages: 41455
Images: 14353
Inscription: 25 Oct 2008, 00:00
Localisation: Montpellier
Genre: Homme
Calculatrice(s):
MyCalcs profile
YouTube: critor3000
Twitter/X: critor2000
GitHub: critor

Précédente

Retourner vers News Divers

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 19 invités

-
Rechercher
-
Social TI-Planet
-
Sujets à la une
Comparaisons des meilleurs prix pour acheter sa calculatrice !
Aidez la communauté à documenter les révisions matérielles en listant vos calculatrices graphiques !
Phi NumWorks jailbreak
123
-
Faire un don / Premium
Pour plus de concours, de lots, de tests, nous aider à payer le serveur et les domaines...
Faire un don
Découvrez les avantages d'un compte donateur !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partenaires et pub
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
716 utilisateurs:
>701 invités
>10 membres
>5 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Autres sites intéressants
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)