π
<-
Chat plein-écran
[^]

Résultat concours rentrée 2019 - défi langage calculatrice

Online

Résultat concours rentrée 2019 - défi langage calculatrice

Unread postby critor » 08 Dec 2019, 15:11

Voici
enfin
aujourd'hui la fin des résultats de notre concours de rentrée 2019, plus précisément pour le défi en langage calculatrice.

Le défi te faisait ici travailler sur un automate cellulaire, dont un des plus connus est le
jeu de la vie
. Afin toutefois qu'il ne suffise pas d'exploiter l'un des nombreux travaux universitaires à ce sujet et donc de ne favoriser personne, les règles en étaient très éloignées :
  • deux populations au lieu d'une seule
  • chaque cellule n'était pas binaire
    (morte ou vivante)
    mais pouvait prendre 6 états différents
    (de bien morte à bien vivante)
    et ce pour chacune des populations
  • les deux populations utilisaient des règles de naissance/survie/mort différentes basées sur les états voisins, et également différentes de celles du
    jeu de la vie

Nous avons reçu un total de
109
participations de la part de
23
participants différents :
  • 3
    participants ont utilisé une
    Casio Graph 90+E
    ou son logiciel d'émulation
  • 3
    participants ont utilisé une
    TI-Nspire CX
    ou son logiciel d'émulation
  • 4
    participants ont utilisé entre autres une
    TI-83 Premium CE Edition Python
    ou son logiciel d'émulation
  • 2
    participants ont utilisé une
    HP Prime
    ou son logiciel d'émulation



22ème
:

thecamouflage
, lycéen en
Terminale S
à l'aide de sa
Casio Graph 90+E
, réalise dès le départ pas moins de
15
interventions
divines :
  • 4
    fois en faveur des
    Muens
  • puis
    11
    fois en faveur des
    Atlantes
Ce qui lui permet d'obtenir
15460
points en l'an
42
.
Précisons que dans sa simulation les
Atlantes
emportent la victoire sur les
Muens
en l'an
64
ce qui donne un score maximal de
21970
points.


21ème
:

ggauny@live.fr
muni de sa fidèle
HP Prime
, intervient pour sa part
17
fois
:
  • 4
    fois pour aider les
    Atlantes
  • puis
    13
    fois pour aider les
    Muens
Ce qui lui donne
16588
points en l'an
42
.
Précisons que dans sous cette configuration les
Atlantes
gagnent encore sur les
Muens
mais après pas moins de
173
ans, pour score final de
81410
points ! :D


20ème
:

C'est muni de sa
TI-83 Premium CE Edition Python
qu'
Azerpogba
, lycéen en Première Spécialité Mathématiques+PC+SVT présent à la fois sur
TI-Planet
et sur
Planète Casio
, use
8
fois
de son pouvoir divin sans favoritisme :
  • 4
    fois à l'avantage des
    Muens
  • 4
    fois à l'avantage des
    Atlantes
Ce qui l'amène à
16647
points en l'an
42
.
Dans cette réalité alternative ce sont les
Muens
qui éradiquent les
Atlantes
mais dès l'an
87
, pour un score terminal de
34787
points.


19ème
:

Adoptant quant à lui la
TI-Nspire CX
,
Ti64CLi++
, élève en classe préparatoire MPSI, fréquentant aussi bien
TI-Planet
que
Planète Casio
, fait appel
11
fois
à ses capacités divines :
  • 4
    fois pour semer une colonies
    Muenne
  • puis
    7
    fois pour semer une colonies
    Atlante
Ce qui lui permet d'obtenir
16647
points en l'an
42
.
Avec un tel semis, les
Atlantes
écrasent à leur tour les
Muens
ici encore assez vite, dès l'an
86
, pour un ultime score de
29051
points.


18ème
:

La
TI-83 Premium CE Edition Python
est maintenant de retour avec
LePetitMage
, lycéen en Terminale S, qui se mêle
11
fois
mais de façon alternative des affaires humaines :
  • 5
    fois à l'avantage des
    Muens
  • 6
    fois à l'avantage des
    Atlantes
Une stratégie qui lui octroie
16699
points en l'an
42
.
Ici encore la cohabitation n'est pas bien durable, les
Atlantes
régnant sans partage dès l'an
71
, pour un score alors figé à
28455
points.


17ème
:

Toujours sur
TI-83 Premium CE Edition Python
,
grandben49
n'apparaît aux simples mortels qu'avec parcimonie, seulement
6
fois
:
  • 3
    fois pour créer une colonie
    Muenne
  • puis
    3
    fois pour créer une colonie
    Atlante
Il atteint ainsi
17257
points en l'an
42
.
Une vision à plus long terme dans son cas, les
Muens
n'arrivant alors à exterminer les
Atlantes
qu'après
134
ans, pour un score définitif de
58203
points. :D


16ème
:

La valeur n'attend point le nombre des années et
Leno
, collégien en Quatrième traînant aussi bien sur
TI-Planet
que sur
Planète Casio
, ne se mêle lui aussi que
6
fois
des affaires inférieures :
  • prenant
    3
    fois parti pour les
    Muens
  • prenant
    3
    fois parti pour les
    Atlantes
Il récupère ainsi
17922
points en l'an
42
.
Une bonne durabilité là encore, les
Muens
ne dominant alors le monde qu'après
144
ans, pour un score s'arrêtant alors à
52750
points. :D


15ème
:

Astrostellar
, lycéen en Terminale S, exerce lui aussi
6
fois
ses talents de créateur :
  • 3
    fois au service de la cause
    Muenne
  • 3
    fois au service de la cause
    Atlante
Il encaisse ainsi
17989
points en l'an
42
.
Mais hélas l'équilibre n'est sans lui qu'éphémère, les
Muens
triomphant alors après seulement
88
ans pour
35375
points.


14ème
:

Encephalogramme
, lycéen plus interventioniste en Première, invoque ses pouvoirs divins pas plus de
10
fois
sur les
11
premières années :
  • 3
    fois au au nom des
    Atlantes
  • puis
    7
    fois au nom des
    Muens
Il décroche ainsi
18142
points en l'an
42
. :)
Une cohabitation de ces populations qui a le mérite de durer
247
ans, avant la victoire finale des
Atlantes
sur les
Muens
pour
117607
points ! :bj:


13ème
:

C'est au nom des anciens dieux Commodore Amiga qu'
Amiga68000
agit quant à lui
7
fois
sur les
8
premières années :
  • 3
    fois pour le bien des
    Atlantes
  • 4
    fois pour le bien des
    Muens
Il décroche ainsi
18425
points en l'an
42
. :)
Une durabilité toutefois en retrait, les
Atlantes
devant les maîtres du monde après
149
ans pour
65274
points. :D
Amiga68000 wrote:
Voici mon code, et vu mon classement vous comprendrez que ma méthode n'est pas la meilleure.
J'ai fait des tirages aléatoires en paramétrant
(en en tirant aléatoirement)
:
  • la taille zone de départ où mettre les habitants
    (variables carrex et carrey)
  • le nombre d’habitants
Voilà les 2 fonctions utilisées: atmu=run(100,False)
  1. 100 = nombre de tirages de 42 ans
  2. 0 = pas de limite
  3. True = sauvegarde de chaque tirage pour faire des statistiques
Routine qui à partir d'une composition fait varier chaque position de chaque habitant et prend la meilleure configuration : variercompo()

Et le code global ci-contre
(merci
Pavel
pour la transpo sur
PC
)
.
Code: Select all
from math import log10,sqrt

from random import randint
import csv




from math import log10,sqrt
from tkinter import *




def color(r, g, b):
  return '#%02x%02x%02x' % (r, g, b)

def fill_rect(x, y, w, h, color):
  y += 18
  canvas.create_rectangle(x, y, x + w, y + h, fill=color, outline='')

def draw_string(text, x, y, fg=color(0,0,0), bg=None):
  y += 18
  t = canvas.create_text(x, y, anchor=NW, text=text, fill=fg)
  if bg is not None:
    r = canvas.create_rectangle(canvas.bbox(t), fill=bg, outline='')
    canvas.tag_lower(r, t)

def clear():
  canvas.delete('all')
  canvas.create_rectangle(0, 18, 320, 240, fill=color(255, 255, 255), outline='')
  canvas.create_rectangle(0, 0, 320, 18, fill=color(255, 183, 52), outline='')

def init():
  global atmu,n,j,s,ma,mb,mc,w,fp,fm
  atmu,n,j,s,w,fp,fm=[],9,0,0,5,0,0
  ma,mb,mc=[[0]*n for k in range(n)],[[0]*n for k in range(n)],[[0]*n for k in range(n)]

def dr():
  global s,j,w
  sw=320
  d,h=min(sw//n,221//n),(color(0,0,0),color(255,255,255))
  b=sw-1-n*d
  clear()
  for i in range(0,n*d+1,d):
    fill_rect(b,i,n*d,1,h[0])
    fill_rect(b+i,0,1,n*d,h[0])
  for y in range(0,n):
    for x in range(0,n):
      t=255-(255*abs(ma[y][x])//w)
      fill_rect(b+x*d+1,y*d+1,d-1,d-1,ma[y][x]<0 and color(t,t,255) or ma[y][x]>0 and color(255,t,t) or h[1])
  draw_string(" ATLEMU ",1,1,color(255,255,0),color(127,127,127))
  draw_string("Muen\ndo(-1,c,l)",0,19,color(0,0,255),h[1])
  draw_string("Atlante\ndo(1,c,l)",0,53,color(255,0,0),h[1])
  draw_string("Passer\ndo(0)",0,87,color(255,0,255),h[1])
  draw_string("Recommencer\ninit()",0,121,color(0,0,0),h[1])
  draw_string("An: "+str(j)+"\nScore:\n"+str(s)[:10],0,n*d-49)

def do(*ar):
  global j,gp,gm,fp,fm,s
  j,k,v,(sc,sl)=j+1,ar[0],(len(ar)%2) or ar[len(ar)-1],(len(ar)>=3) and (ar[1],ar[2]) or (0,0)
  k,gp,gm=k and k//abs(k),fp,fm
  for y in range(n):mb[y]=mc[y].copy()
  for y in range(n):
    for x in range(n):
      o,ma[y][x]=ma[y][x],ma[y][x]+w*(ma[y][x]==0 and x==sc and y==sl)*((k>0)-(k<0))+(ma[y][x]<=0 and (x-sc or y-sl or k==0) and mb[y][x]//10==3)*((ma[y][x]==0)*w-ma[y][x]*(not(not(ma[y][x]))))-(ma[y][x]>=0 and (x-sc or y-sl or k==0) and mb[y][x]-10*(mb[y][x]//10)==3)*((ma[y][x]==0)*w+ma[y][x]*(not(not(ma[y][x]))))
      if o and ma[y][x]==o:
        ls=(-1,w>abs(ma[y][x]))
        ma[y][x]=ma[y][x]+(ma[y][x]>0)*ls[mb[y][x]//10==3 or mb[y][x]//10==4]-(ma[y][x]<0)*ls[mb[y][x]-10*(mb[y][x]//10)==3 or mb[y][x]-10*(mb[y][x]//10)==2]
      if ma[y][x]-o:
        fp,fm=fp+(ma[y][x]>0 and not(o))-(o>0 and not(ma[y][x])),fm+(ma[y][x]<0 and not(o))-(o<0 and not(ma[y][x]))
        if not(o) and ma[y][x] or o and not(ma[y][x]):
          for dl in range(-1,2):
            for dc in range(-1,2):
              if dl or dc:mc[y+dl+(dl<0 and y==0)*n-(dl>0 and y==n-1)*n][x+dc+(dc<0 and x==0)*n-(dc>0 and x==n-1)*n]+=(ma[y][x]<0)-(o<0 and 0==ma[y][x])+10*((ma[y][x]>0)-(o>0 and 0==ma[y][x]))
  if max(fp,gp)*max(fm,gm):s=s/(1+abs(k)*log10(sqrt(j)))+fp*fm*min(fp,gp)*min(fm,gm)/max(fp,gp)/max(fm,gm)
  atmu.append((sc*k+k,sl*k+k))
  if v:
    dr()
#    print("Bon score ? Envoie la liste\n'atmu' a info@tiplanet.org")
  return s

def st(l,v=True):
  init()
  for p in l:s=do((p[0]>0)-(p[0]<0),abs(p[0])-1,abs(p[1])-1,v)
  dr()
  return s





 
 
#  ************************************************************************************
#  **
#  ** SUB PERSO
#  **
#  ************************************************************************************

rep="D:/_Datas/_Datas PERSO/Python-atlemu"

def sauvecsv(v,nom=rep + "/sansnom.csv",m="w"):
  #sauvegarde une matrice p en csv
  #with open("L:/_Datas/11 - Arnaud/Python - DEFI/table.csv", "w") as f_write:
    with open(nom, m) as f_write:
        writer = csv.writer(f_write,delimiter=";")
        writer.writerow(v) #        writer.writerows(v) si plusieurs lignes
    return
   
def sauvetxt(v,nom=rep + "/sansnom.txt"):     
    fichier = open(nom,"w")
    fichier.write(str(v))
    fichier.close()
       
    return
 

 

def run(nbboucles,sauvechaquetirage=False):
  global atmumax
 
  smax=0
  boucle=0
  moyscore=0
 
  while boucle<nbboucles or nbboucles==0:
    boucle+=1
   
    init()
    if boucle%100==0:print("run "+str(boucle)+" Max="+str(smax))
 
    carrex= randint(2,4)
    carrey= randint(2,4)
   
    zonex=9-carrex
    zoney=9-carrey
   
    x1=randint(1,zonex)
    y1=randint(1,zoney)
    x2=randint(1,zonex)
    y2=randint(1,zoney)
   
    nbhabitants=12 #randint(3,5)
   

    for k in range(nbhabitants-1): #nombre d'habitants  par couleur
#      l=randint(0,carre)
#      m=randint(0,carre)
   
        do(1,x1+randint(0,carrex),y1+randint(0,carrey) )
        do(-1,x2+randint(0,carrex),y2+randint(0,carrey) )

#        nx1=x1+randint(0,carrex)
#        ny1=y1+randint(0,carrey)       
#        if ma[nx1-1][ny1-1]!=0:
#              s=do(0)
#        else:
#              do(1,nx1,ny1)
#               
#        nx2=x2+randint(0,carrex)
#        ny2=y2+randint(0,carrey)
#        if ma[nx2-1][ny2-1]!=0:
#              s=do(0)
#        else:
#              do(-1,nx2,ny2)

    s=do(0)
    s=do(0)
    do(1,x1+randint(0,carrex),y1+randint(0,carrey) )
    do(-1,x2+randint(0,carrex),y2+randint(0,carrey) )
       

    while j<42:
      s=do(0)
     
    moyscore+=s
       
    if s>smax:
      smax=s
      atmumax=list(atmu)
      print("---")
      print("#"+str(smax))
      print("#"+str(atmumax))
      print("---")
      print("Carre X="+str(carrex))
      print("Carre Y="+str(carrey))
      print("Nb habitants="+str(nbhabitants))
      print("---")
     
      if not(sauvechaquetirage):
             sauvertirage(smax,nbhabitants,0,carrex,carrey,atmumax) 
     

    if sauvechaquetirage:
      sauvertirage(s,nbhabitants,0,carrex,carrey,atmu) 
 
     
     
  print("#"+str(smax))
  print("#st("+str(atmumax)+",False)")
  print("#"+str(smax))
  moyscore=moyscore/nbboucles
  print("#"+str(moyscore))
 
  st(atmumax,False)
 
  return atmumax

 
def sauvertirage(score,nbhabitants,surface,carrex,carrey,compo):
    if surface==0:
        surface=carrex*carrey
    e=[]
    e.append(score)
    e.append(nbhabitants)
    e.append(surface)
    e.append(carrex)
    e.append(carrey)
    e.append(compo)
    sauvecsv(e,rep+"/stat-tirages.csv","a")
    return
 
   
def variercompo():
    compo=[(7, 2), (-4, -7), (8, 2), (-2, -7), (7, 4), (-3, -7), (0, 0), (-4, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

    smax=0
    atmumax=[]
    s=st(compo,False)
    smax=s
    atmumax=list(atmu)
   
    for k in range(len(compo)):
        print("k="+str(k))
       
        hab=compo[k]
        x=hab[0]
        y=hab[1]
        if x!=0:

            #on fait varier les positions
            plage=[-1,0,1]
            for deltax in plage:
                nx=x+deltax
                for deltay in plage:
                    ny=y+deltay
                   
                    #on a la nouvelle position nx,ny
                    ncompo=list(compo)
                    print(ncompo[k])
                    ncompo[k][0]=nx
                    ncompo[k][1]=ny

                    #on teste la compo
                    s=st(ncompo,False)
                   
                    #
                    if s>smax:
                        smax=s
                        atmumax=list(atmu)
                        print("---")
                        print("#"+str(smax))
                        print("#"+str(atmumax))
                        print("---")
                        print("Carre X="+str(carrex))
                        print("Carre Y="+str(carrey))
                        print("Nb habitants="+str(nbhabitants))
                        print("---")

    return
   
   
   
   
 
master = Tk()
master.resizable(0, 0)
canvas = Canvas(master, width=320, height=240)
canvas.pack()


sauvertirage("Score","nb habitants","surface","carre X","carre Y","Sequence")

init()
dr()
variercompo()
#atmu=run(100,False)
#sauvetxt(atmu,rep+"/CompoAtmu.txt")

#affichage
if __name__== "__main__":master.mainloop()


#st([(7, 2), (-4, -7), (8, 2), (-2, -7), (7, 4), (-3, -7), (0, 0), (-4, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],False)
#18425.217793183947

#st([(7, 2), (-4, -7), (8, 2), (-2, -7), (7, 4), (-3, -7), (0, 0), (-4, -9), (0, 0), (-3, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)],False)
#18390.75048739328

#18381.309236990124
#[(7, 2), (-4, -7), (8, 2), (-2, -7), (7, 4), (-3, -7), (8, 2), (-4, -9), (7, 4), (-3, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
#18381.309236990124

#18168.450679791244
#[(9, 7), (-4, -8), (9, 8), (-4, -7), (7, 8), (-2, -8), (9, 8), (-4, -8), (8, 6), (-4, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
#18168.450679791244

#18049.830151963542
#[(9, 3), (-5, -3), (7, 3), (-5, -2), (9, 2), (-5, -4), (7, 2), (-3, -4), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
#18049.830151963542

#18035.99025478949
#[(3, 3), (-8, -7), (2, 3), (-7, -6), (3, 4), (-9, -6), (4, 3), (-7, -7), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
#18035.99025478949

#18003.837819596458
#[(3, 3), (-4, -8), (3, 4), (-4, -7), (5, 3), (-2, -8), (2, 2), (-5, -9), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
#18003.837819596458

#17841.546235752416
#[(4, 4), (-8, -2), (4, 5), (-8, -3), (2, 5), (-6, -3), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

#17781.124608967286
#[(4, 7), (-8, -6), (3, 6), (-9, -7), (5, 6), (-7, -7), (4, 7), (-8, -6), (3, 5), (-9, -8), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

#17605.76772889996
#[(2, 9), (-7, -6), (3, 9), (-7, -7), (2, 8), (-5, -7), (4, 7), (-5, -7), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]

#17425
#[(4, 5), (-8, -3), (4, 4), (-8, -4), (4, 3), (-6, -4), (3, 3), (-6, -3), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
viewtopic.php?f=49&t=23051&start=150#p248013


12ème
:

Ne0tuX
hantant à la fois
TI-Planet
et
Planète Casio
, met la main à la pâte
9
fois
sur les
13
premières années :
  • 5
    fois pour aider les
    Atlantes
  • 4
    fois pour aider les
    Muens
Il est ainsi récompensé de
18467
points en l'an
42
. :D
Saluons la durée exceptionnelle de cohabitation de ces deux populations, les
Muens
devant attendre pas moins de
263
ans pour régner en maîtres absolus, pour pas moins de
130039
points ! :bj:
Ne0tuX wrote:Félicitations à tous les participants et aux instigateurs de l'épreuve ! J'ai trouvé ce défi particulièrement intéressant pour les raisons suivantes :
  • Contrairement au défi précédent, l'ordre des éléments a un sens ce qui complique les choses ;
  • La lois de l'automate cellulaire ne sont pas explicitement lisibles dans le code ce qui pousse à l'expérimentation
    on calc
    ;
  • L'automate n'est pas
    bijectif
    , mais
    surjectif
    (sésolé si ce ne sont pas les bons termes, qu'on me corrige s'il y a mieux)
    . Autrement dit, même si on trouve une configuration de la 42ème année qui donne un bon score, on ne peut pas remonter le temps pour déterminer une séquence d'implantation des colonies
    (pas à ma connaissance du moins)
    .
Pour ce qui est de ma méthode, j'ai pressenti que l'algorithme génétique n'était pas terrible à l'état brut
(voir la première raison ci-dessus)
. J'ai donc rapidement implémenté en
Python
un recuit simulé
(rien de sorcier sur la forme)
mais j'ai vite compris que TOUT reposait sur le paramétrage et surtout sur la définition du
mouvement élémentaire
, qu'il faut définir avec beaucoup de soin et de façon intelligente. Par manque de temps et d'investissement je n'avais ni l'un ni l'autre donc j'ai coupé court... J'aurais vraiment aimé explorer ce problème, mais n'ai finalement fait que quelques essais directement sur
TI-Nspire
(très belle animation d'arrière plan au passage)
en remarquant globalement les mêmes observations que celles postées précédemment sur ce topic.

J'ai hâte de lire toutes les méthodes employées et je n'exclus pas d'en expérimenter quelques-unes pour le plaisir !
viewtopic.php?f=49&t=23051&start=140#p247951


11ème
:

Thomas F.
se retrousse les manches pas plus de
10
fois
sur les
12
premières années :
  • 4
    fois pour aider les
    Atlantes
  • 6
    fois pour aider les
    Muens
Le voici ainsi pourvu de
18835
points en l'an
42
. :D
Par contre c'est bien moins solide, les
Atlantes
faisant disparaître les derniers
Muens
après seulement
86
ans pour
30546
points.
Thomas F. wrote:J'ai placé 3 civilisations de chaque couleur. Il m'a fallu un peu de temps pour comprendre le fait que la grille était semblable à un tore. Puis un peu plus pour constater que l'ordre avait aussi son importance. Du coup j'ai lancé une recherche de la meilleure configuration de départ pour mes 2 lignes de 3 civilisations. Enfin, j'ai lancé des boucles de recherche de meilleurs scores avec des civilisations aléatoires dans les 6 tours suivant. J'ai fait le choix totalement arbitraire de ne pas explorer plus loin dans le temps l'implantation de nouvelles civilisations. Voilà, c'est pas transcendant comme démarche, mais je n'ai pas trouvé mieux en trois jours.


10ème
:

edgar13
, lycéen en Première Spécialité Mathématiques+PC+SVT accompagné de sa fidèle
TI-83 Premium CE Edition Python
présent à la fois sur
TI-Planet
et sur
Planète Casio
modère le monde
11
fois
:
  • 6
    fois pour la gloire
    Atlantes
  • 5
    fois pour la gloire des
    Muens
L'an
42
le récompense alors de
19013
points ! :D
La durabilité est améliorée, avec les
Muens
qui ne signent l'arrêt de mort des
Atlantes
que l'an
148
avec
64383
points. :D
edgar13 wrote:Alors moi aussi j'ai commencé sur
TI-83 Premium CE
mais c’était très long! :(
Avec la
TI-83 Premium CE
j'ai compris que 6 colonies suffisaient pour devenir autonomes et qu'il valait mieux ne rien faire pour gagner plus de points. Finalement lundi soir à 20h m'a un peu aidé, il m'a fait remarquer que le programme existait aussi en
Python
. Et là avec un simple
brute force
j'ai fait 19013. :whistle:
A vrai dire je ne comprends pas pourquoi il existe aussi la version python alors que c'est le défi basic. :?
C'était une force brute mais je ne l'ai fait tourner que 2h. :)
Après j'ai dormi. :D
viewtopic.php?f=49&t=23051&start=140#p247946


9ème
:

RdB
armé de sa puissance
HP Prime
choisit d'éditer le monde
9
fois
sur les
10
premières années :
  • 5
    fois pour augmenter
    Atlantes
  • 4
    fois pour augmenter
    Muens
Il arrive ainsi à
19236
points en l'an
42
! :D
Mais les
Atlantes
font maintenant disparaître les
Muens
après
116
ans pour
46842
points.


8ème
:

M4x1m3
lycéen en Terminale S altère
10
fois
la réalité :
  • 3
    fois en faveur des
    Atlantes
  • 7
    fois en faveur des
    Muens
Il se classe ainsi à
19534
points en l'an
42
! :D
Meilleure durabilité puisque les
Atlantes
ne triomphent des
Muens
qu'après
193
ans pour
78423
points ! :D


7ème
:

C'est muni de sa
TI-Nspire CX
qu'
Extra44
agit
10
fois
:
  • 5
    fois en l'honneur des
    Muens
  • 5
    en l'honneur des
    Atlantes
Il obtient ainsi
19743
points en l'an
42
! :D
Meilleure durabilité puisque les
Atlantes
gagnent leur dernier combat dès l'an
96
avec
36335
points.
Extra44 wrote:Voila pour ma part mon explication de ma démarche.
NB
: L'explication sera malheureusement générale, car mon PC portable qui servait pour les essais a planté
(carte mère)
, et je n'ai plus accès à mes fichiers
tns
intermédiaires
(je n'ai pas encore pu réinstaller le logiciel
TI Nspire CAS Software
)
.

Bon ma méthode pour avoir le score max est composé de plusieurs points :
  • quelques essais manuels pour voir comment àa marche
  • décodage du code
    (compressé ;) )
    et voir à quoi correspondent les variables sur la version ti nspire, donc en Langage
    LUA
  • afficher des résultats pour arriver à décoder le code
    (affichage consultable dans la console de l'éditeur
    LUA
    du logiciel
    TI-Nspire Software
    )
  • Modifier le code pour n'avoir au final qu'un affichage du score dans la console
    (plus d'affichage intermédiaire)
  • Faire une version LUA sans affichage graphique et qui ne ressort que le résultat final en fonction d'une entrée sous forme de liste
  • On peut passer maintenant à faire des algo pour trouver un bon score...
  • J'ai essayé le score aléatoire ... mais ce n'est pas fameux ;)
  • J'ai remarqué qu'il faut au moins 3 colonies d'une population pour qu'elle puisse croître ...Donc un minimum de 2x3 = liste de 6 éléments minimum
  • J'ai remarqué que si l'ajout d'une colonie n'est pas optimal, il peut réduire fortement le score !
  • Ensuite, pour accélérer les recherches, j'ai converti le code
    LUA
    en
    C++
    et j'ai compilé des versions successives en
    C++
    , pour plus de rapidité. J'ai ajouté parfois ...
    • une partie d'algo de recherche aléatoire
      (entre 6 et 20..22..40 colonies)
    • une partie d'algo génétique, mais apparemment je n'ai pas trouvé/obtenu le bon démarrage.
    • une partie d'algo d'optimisation de bon résultats,
    • Tout cela me permettait d'arriver rapidement à chaque fois aux 17000/18000/18800 points.
    • Sur un bon résultat, je l'ai modifié à la main, et réussit à obtenir mon score final de 19743 pts
    • J'ai fait tourner ma machine pendant 2/3/4 jours avant qu'elle ne plante,
      (le mercredi de la dernière semaine du concours)
    • Puis en changeant de machine
      (je passais d'un
      i5
      à un
      i3
      ;-( )
      , j'ai essayé d'autres algos, d'autres paramètres d'algo génétique sans obtenir de meilleur résultats ;-(
Bravo encore aux organisateurs pour ce joli concours, et aux participants ! ;-)
viewtopic.php?f=49&t=23051&p=249019#p249019


6ème
:

Sentaro21
sévissant à la fois sur
TI-Planet
et sur
Planète Casio
fait réaliser
9
miracles
à sa
Casio Graph 90+E
:
  • 3
    en faveur des
    Atlantes
  • 6
    en faveur des
    Muens
Il atteint ainsi
19907
points en l'an
42
! :D
Et c'est du solide, les
Muens
ne remportant leur ultime bataille qu'en l'an
225
avec
108463
points ! :bj:
sentaro21 wrote:Thank you very much for the contest again this year. Animation is very good. ;)
The result is clear at a glance. There is no content that I can explain in particular. I quickly found out that the first few steps were important, but I couldn't stabilize the two countries. As a result, I got results only by trial and error with the calculator just like last year. :p
In this participate,
Casio
's traditional language
Basic
was too slow. However, it was very good that it was able to work with
C.Basic
. :D
viewtopic.php?f=49&t=23051&start=160#p248950


5ème
:

Zocipal
, lycéen en Première Spécialité Maths-PC-NSI, intervient équitablement
8
fois
:
  • 4
    fois pour aider les
    Atlantes
  • 4
    fois pour aider les
    Muens
Il franchit ainsi un cap symbolique avec pas moins de
20130
points en l'an
42
! :bj:
C'est un peu plus fragile, les deux populations n'arrivant à cohabiter que jusqu'à l'an
142
, où seuls les
Atlantes
subsisteront avec
62652
points. :D


4ème
:

Golden Man
, lycéen en Terminale S, intervient pour sa part pas moins de
12
fois
:
  • 5
    fois pour avantager
    Atlantes
  • 7
    fois pour avantager les
    Muens
Il passe ainsi à
20311
points en l'an
42
! :bj:
Un net mieux en terme de cohabitation, qui dure maintenant jusqu'à l'an
183
, où ne resteront que les
Muens
avec
78167
points ! :D
Golden Man wrote:Après le passionnant nous nous sommes attaqué au défi historique, proposé par les sites internet
TI-Planet
et
Planète Casio
et les équipes de bénévoles passionnés qui animent ces communautés.


LE CONTEXTE

Il existait autrefois au coeur du grand océan appelé Pacifique un empire, l’empire de Mu. Grâce à l’énergie du soleil qu’ils avaient réussi à maîtriser complètement les Lémuriens menaient une vie tranquille et prospère. A la même époque, une autre civilisation celle de l’Atlantide régnait au centre de l’autre océan, l’Atlantique. Les Atlantes eux aussi savaient contrôler la puissance du soleil et ils avaient construit un puissant empire.
Mais un jour, la guerre éclata entre la terre de Mu et l’Atlantide pour une raison si insignifiante que l’histoire elle-même l’a oubliée. La guerre dura longtemps, de nombreuses années, car les forces des deux puissances étaient égales. Jusqu’au jour où les hommes firent usage de l’arme solaire. C’est ainsi que ces deux grandes civilisations disparurent, englouties au fond des deux océans…

Tu n’as rien compris ? Normal, cela fait parti du challenge !
(lire l’intégralité du défi : Concours de rentrée 2019 - défi langage historique)


Il était possible de participer avec un script en
Casio-Basic
,
TI-Basic
, ou en
Python
. Nous avons bien évidement choisi le langage
Python
pour sa souplesse, et la capacité que nous avions à le faire tourner sur un
PC
sur divers
IDE Python
.

Dans la suite de l’article, le "nous" fait référence aux participants
cent20
et
Golden Man
, car nous avons réalisé les recherches en commun.


PREMIERS TESTS

Tout commence par des premiers tests à la main, et en tout premier lieu nous avons commencé par neutraliser le traitement graphique du script, les affichages textes, pour chercher à l’aveugle par ce que sinon cela n’est pas assez difficile...
Code: Select all
from math import log10,sqrt
def init():
    global atmu,n,j,s,ma,mb,mc,w,fp,fm
   
    atmu = []
    n = 9
    j = 0
    s = 0
    w = 5
    fp = 0
    fm = 0
    ma = [[0]*n for k in range(n)]
    mb = [[0]*n for k in range(n)]
    mc = [[0]*n for k in range(n)]

"""
A CREUSER

def dr():
    global s,j,w # sjw (je sais pas si c'est fait expres, mais c'est tres drole)
    sw=320
    d,h=min(sw//n,221//n),(color(0,0,0),color(255,255,255))
    b=sw-1-n*d
   
    for i in range(0,n*d+1,d):
        fill_rect(b,i,n*d,1,h[0])
        fill_rect(b+i,0,1,n*d,h[0])
       
    for y in range(0,n):
        for x in range(0,n):
            t=255-(255*abs(ma[y][x])//w)
            fill_rect(b+x*d+1,y*d+1,d-1,d-1,ma[y][x]<0 and (t,t,255) or ma[y][x]>0 and (255,t,t) or h[1])
           
    draw_string(" ATLEMU ",1,1,color(255,255,0),color(127,127,127))
    draw_string("Muen\ndo(1,c,l)",0,19,color(0,0,255),h[1])
    draw_string("Atlante\ndo(-1,c,l)",0,53,color(255,0,0),h[1])
    draw_string("Passer\ndo(0)",0,87,color(255,0,255),h[1])
    draw_string("An: "+str(j)+"\nScore:\n"+str(s)[:10],0,n*d-49)
   
"""

def do(*ar):
   
    global j,gp,gm,fp,fm,s
   
    j = j+1 # Indice de la liste des couples et nombre d'annees
    k = ar[0] # Notre premier argument (le camp choisi (ou passer))
    v = (len(ar)%2) or ar[len(ar)-1] # v = 1 ou 0 selon la longueur (3 ou 1)
    (sc,sl) = (len(ar)>=3) and (ar[1],ar[2]) or (0,0) # Les deux derniers
   
    # permet de recuperer les deux derniers elements de do(a,b,c)
    # a = equipe ; b = colonnes ; c = lignes
   
    k = k and k//abs(k) # Change pas k (fausse piste je pense)
   
    # Changement de nom
    gp = fp
    gm = fm
   
    for y in range(n):
        # mb possiblement une sauvegarde
        # mc devient une copie de mb
        mb[y]=mc[y].copy()
       
    for y in range(n):
        for x in range(n):
           
            o = ma[y][x]
           
            # Le gros tas
            ma[y][x] = ma[y][x]+w*(ma[y][x]==0 and x==sc and y==sl)*((k>0)-(k<0))+(ma[y][x]<=0 and (x-sc or y-sl or k==0) and mb[y][x]//10==3)*((ma[y][x]==0)*w-ma[y][x]*(not(not(ma[y][x]))))-(ma[y][x]>=0 and (x-sc or y-sl or k==0) and mb[y][x]-10*(mb[y][x]//10)==3)*((ma[y][x]==0)*w+ma[y][x]*(not(not(ma[y][x]))))
           
            if o and ma[y][x]==o:
               
                ls=(-1,w>abs(ma[y][x]))
                ma[y][x]=ma[y][x]+(ma[y][x]>0)*ls[mb[y][x]//10==3 or mb[y][x]//10==4]-(ma[y][x]<0)*ls[mb[y][x]-10*(mb[y][x]//10)==3 or mb[y][x]-10*(mb[y][x]//10)==2]
           
            if ma[y][x]-o:
               
                fp = fp+(ma[y][x]>0 and not(o))-(o>0 and not(ma[y][x]))
                fm = fm+(ma[y][x]<0 and not(o))-(o<0 and not(ma[y][x]))
               
                if not(o) and ma[y][x] or o and not(ma[y][x]):
                    for dl in range(-1,2):
                        for dc in range(-1,2):
                            if dl or dc:
                                mc[y+dl+(dl<0 and y==0)*n-(dl>0 and y==n-1)*n][x+dc+(dc<0 and x==0)*n-(dc>0 and x==n-1)*n]+=(ma[y][x]<0)-(o<0 and 0==ma[y][x])+10*((ma[y][x]>0)-(o>0 and 0==ma[y][x]))
    if max(fp,gp)*max(fm,gm):
        s=s/(1+abs(k)*log10(sqrt(j)))+fp*fm*min(fp,gp)*min(fm,gm)/max(fp,gp)/max(fm,gm)
   
    # The final code !
    # Il est ici
    # Chaque elements est de la forme (sc*k+k,sl*k+k)
   
    atmu.append((sc*k+k,sl*k+k))
   
    if v:
        # dr()
        print("Bon score ? Envoie la liste\n'atmu' a info@tiplanet.org")
    return s
def st(l,v=False):
    init()
    for p in l:
       
        # C'est ici qu'on triche !
        # On va pas utiliser une liste de couple, mais une liste de liste
        # comme ca, c'est modifiable comme on veut
       
        # J'ai mis v sur False pour pas avoir le message "Bon score..."
       
        s=do((p[0]>0)-(p[0]<0),abs(p[0])-1,abs(p[1])-1,v)
    # dr()
    return s
init()

actions = [[0,0] for k in range(42)]
rien = [0,0]
scores = []
refscores = []
def chasse():
    for k in range(100): # On va tester au max
        for i in range(42):
            scores = []
            for t in [-1,1]:
                for col in range(1,10):
                    for lig in range(1,10):
                        actions[i] = [t*(col+1),t*(lig+1)]
                        scores.append(st(actions))
                        refscores.append([t,col,lig])
            actions[i] = rien
            scores.append(st(actions))
            refscores.append(rien)
            if refscores[scores.index(max(scores))] != rien:
                actions[i] = [refscores[scores.index(max(scores))][0]*(refscores[scores.index(max(scores))][1]+1),refscores[scores.index(max(scores))][0]*(refscores[scores.index(max(scores))][2]+1)]
            else:
                actions[i] = rien
            print("Annee",i,":",max(scores))


Tout commence avec des tirages aléatoires très aléatoires sans aucune réflexion, et ayant réussi à fabriquer une liste de 5 couples avec un score acceptable
(on le pense alors !)
, on essaye de l’améliorer, et de tirer d’autres listes de 5 couples acceptables.
Code: Select all
import random
def aleat5():
    m = 42
    l = [(-2,-2), (2,3), (-2,-4), (2,5), (-4,-3)] # la liste de départ
    while len(l)<m:
        l.append((0,0))
    scoremax = st(l)
    print("score liste : ", scoremax)
    equipe = [1, -1]
    l = []
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(5):       
            random.shuffle(equipe)
            l.append((equipe[0]*random.randint(1,9),equipe[0]*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)   
       
        if scorerandom > scoremax:
            print("Meilleur score", scorerandom)
            print("Liste",l[0:5])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)

Cette méthode est un échec, les scores générés ne dépassent pas 100 ! Nous pensions que 100 était en score acceptable car on l’a comparé naïvement au score maxi de 43.x obtenu sur le défi précédent.


ET SI ON EN TIRAIT 10 COUPLES ?

Au lieu de tirer 5 couples, on décide d’en tirer 10.

Pour rappel à ce stade nous sommes toujours aveugles, nous n’avons aucun rendu graphique à analyser pour affiner notre stratégie.
Code: Select all
import random
def aleat10():
    m = 42
    scoremax = 100
    print("score aleat5 : ", scoremax)
    equipe = [1, -1]
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(10):       
            random.shuffle(equipe)
            l.append((equipe[0]*random.randint(1,9),equipe[0]*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)       
        if scorerandom > scoremax:
            print("Meilleur score", scorerandom)
            print("Liste",l[0:10])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)

Assez rapidement, on obtient des score aux alentours de 16000-17000.

Comme au pays des aveugles les borgnes sont rois, on décide alors de continuer les tirages aléatoires de n couples et dans le même temps de développer notre propre couche graphique histoire d’y voir quelques choses et de laisser passer un peu de lumière...
Meilleur score 16685.07457023799
Liste [(-8, -3), (-4, -6), (-9, -1), (-1, -1), (4, 7), (-5, -4), (5, 9), (6, 7), (-4, -3), (-2, -5)]
Meilleur score 17304.672747006774
Liste [(7, 6), (5, 7), (7, 5), (-4, -7), (-3, -5), (-5, -5), (-3, -9), (-6, -5), (-3, -5), (-9, -8)]



TIRAGES ALÉATOIRES DE N COUPLES

Bien évidemment, on lance les fonctions
aleatn(annee)
avec des valeurs pour la variable annee comprise entre 1 et 42 mais tout ceci est très long, un unique script tourne sur un unique
IDE Python
.
Code: Select all
def aleatn(annee):
    m = 42
    scoremax = 100
    print("score kiki : ", scoremax)
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(annee):
            l.append(((-1)**i*random.randint(1,9),(-1)**i*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)
        if scorerandom > 15000:
            print("bon score", scorerandom)
            print("Liste",l[0:annee])
        if scorerandom > scoremax:
            print("========== Meilleur score : ", scorerandom)
            print("================== Liste = ",l[0:annee])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)



LA PROBLÉMATIQUE DU
MULTI-THREAD

Nous n’arrivons pas à faire tourner nos scripts en
multi thread
sur
Python
en utilisant les outils adéquates, nous commençons donc par faire du
multi thread
manuel :
  • 2
    PCs
    = 2 scripts qui tournent 😄
  • 3
    IDE
    = 3 scripts qui tournent. 😅
  • 2
    PCs
    avec 3
    IDE
    = 6 scripts 🤣

Et puis sur
pycharm
nous arrivons enfin à faire tourner 10-12 scripts en parallèle.
(oui enfin, nous avions autant de fichiers que de [i]threads
, cela ressemblait vraiment à un classeur d’élève de 2nde)[/i]

Maîtrisant le
multi thread
cela fut le début de folles nuits des tirages aléatoires
Il faut bien occuper le
Ryzen 7 2700
et ses 16
threads
!


La première nuit, les fonctions
aleatn(annee)
furent lancées avec tous les entiers possible entre 4 et 14.
Je vais me coucher. J’ai lancé les 10 scripts en parallèle on verra demain matin si on a cassé le score de
Pavel
.


Et le lendemain matin les résultats furent dépouillées.


DES NOUVELLES DE LA COUCHE GRAPHIQUE

En parallèle, nous nous sommes occupés de recréer l’interface graphique en l’améliorant légèrement pour pouvoir voir comment le programme fonctionnait et, accessoirement, ce que l’on obtenait avec nos tirages.

Nous avons choisit
tKinter
pour ce travail et fixé un cahier des charges :
  • Un espace pour voir la grille.
  • Un petit commentaire pour expliquer le fonctionnement de la GUI.
  • Une reconnaissance de l’entrée des touches pour entrer les do() plus vite.
  • Un espace pour entrer des commandes spéciales (st() par ex). La détection des touches doit être désactivée pour saisir
  • Un historique :
    • Une grille
      (plus visuelle)
      .
    • Sous forme de texte.
Ainsi, il a fallu créer la fenêtre.
Code: Select all
interface = Tk()
interface.resizable(False,False)
interface.title('Concours AT//MU')

# Utilisable
utilisable = Frame(interface,borderwidth=0)
utilisable.pack(side=LEFT)
canevas = Canvas(utilisable,width=500,height=400,bg="white")
canevas.pack(side=TOP)
saisie = StringVar()
barreSaisie = Entry(utilisable,width=60,textvariable=saisie)
barreSaisie.pack(side=RIGHT)
barreSaisie.configure(state="readonly")
label = Label(utilisable,text="'W' pour (ne plus) ecrire")
label.pack(side=LEFT)
labelScore = canevas.create_text(10,240,text="An : 0 // Score = 0",anchor=NW)
canevas.create_text(10,270,text="Appuyez sur + ou - sur le clavier numerique pour choisir votre camp",anchor=NW)
canevas.create_text(10,290,text="Puis, toujours sur le clavier numerique, selectionnez votre colonne puis votre ligne avec les",anchor=NW)
canevas.create_text(10,305,text="touches 1 a 9.",anchor=NW)
canevas.create_text(10,325,text="Attention, la case (1;1) est la case en haut a gauche !",anchor=NW)
canevas.create_text(10,345,text="Pour passer une annee, appuyez sur le point du clavier numerique.",anchor=NW)
canevas.create_text(10,365,text="Pour recommencer une partie, appuyez sur 'R'.",anchor=NW)
canevas.create_text(10,385,text="Il est possible de rentrer des commandes speciales a tout moment en appuyant sur 'W'.",anchor=NW)

# Historique
historique = Frame(interface,borderwidth=0)
historique.pack(side=RIGHT)
canevasHist = Canvas(historique,width=400,height=230,bg="white")
canevasHist.pack(side=TOP)
listeHist = ScrolledText(historique,width=50,height=11)
listeHist.pack(side=BOTTOM)

Ceci étant fait, on crée une fonction récupérant les événements claviers.

Attention :
On prend bien soin de lier cette fonction à la fenêtre : interface.bind("<Key>",event)
Cette ligne envoie à la fonction
event()
la valeur quand une touche est pressée.
Code: Select all
isWriting = False
commande = ["","",""]
index = 1

def event(touche):
    global isWriting,index,commande
    touche = touche.keysym
    if touche == "w":
        if isWriting:
            barreSaisie.configure(state="readonly")
            saisie.set("do("+commande[0]+","+commande[1]+","+commande[2]+")")
        else:
            barreSaisie.configure(state="normal")
            saisie.set("")
        isWriting = isWriting == False # paradoxe du menteur
    if touche == "r":
        init()
        dr(2,0,0)
    if touche == "plus" and not isWriting:
        commande[0]="1"
    if touche == "minus" and not isWriting:
        commande[0]="-1"
    if touche == "BackSpace" and not isWriting:
        commande[index-1] = ""
        if index > 1:
            index -= 1
    if touche == "1" and not isWriting and index<3:
        commande[index] = "0"
        index += 1
    if touche == "2" and not isWriting and index<3:
        commande[index] = "1"
        index += 1
    if touche == "3" and not isWriting and index<3:
        commande[index] = "2"
        index += 1
    if touche == "4" and not isWriting and index<3:
        commande[index] = "3"
        index += 1
    if touche == "5" and not isWriting and index<3:
        commande[index] = "4"
        index += 1
    if touche == "6" and not isWriting and index<3:
        commande[index] = "5"
        index += 1
    if touche == "7" and not isWriting and index<3:
        commande[index] = "6"
        index += 1
    if touche == "8" and not isWriting and index<3:
        commande[index] = "7"
        index += 1
    if touche == "9" and not isWriting and index<3:
        commande[index] = "8"
        index += 1
    if touche == "Return":
        try:
            eval(saisie.get())
            saisie.set("")
            index=1
            commande=["","",""]
        except:
            print("aie")
    if touche == "period" and not isWriting:
        do(0)
    if not isWriting:
        saisie.set("do("+commande[0]+","+commande[1]+","+commande[2]+")")

Mais, un problème de taille était toujours présent, modifier la couche graphique pré-codée avec
kandinsky
.

Voici donc ce qu’on a pu faire.
Code: Select all
def dr(camp,xHist,yHist):
    global s,j,w,labelScore
    sw=320
    d=min(sw//n,221//n)
    b=sw-1-n*d
   
    for i in range(0,n*d+1,d):
        canevas.create_rectangle(b,10+i,b+n*d,i+11,fill=hexColor(0,0,0),outline="")
        canevas.create_rectangle(b+i,10,b+i+1,n*d+10,fill=hexColor(0,0,0),outline="")
        canevasHist.create_rectangle(b,10+i,b+n*d,i+11,fill=hexColor(0,0,0),outline="")
        canevasHist.create_rectangle(b+i,10,b+i+1,n*d+10,fill=hexColor(0,0,0),outline="")
       
    if camp != 0 and camp != 2:
        t=255-(255*abs(ma[yHist][xHist])//w)
        canevasHist.create_rectangle(b+xHist*d+1,yHist*d+11,b+xHist*d+d,yHist*d+10+d,fill=camp<0 and hexColor(t,t,255) or camp>0 and hexColor(255,t,t),outline="")
        listeHist.insert(END,str((xHist*camp+camp,yHist*camp+camp))+"\n")
    elif camp == 0:
        listeHist.insert(END,"(0, 0)\n")
    else:
        listeHist.delete(1.0,END)
       
    for y in range(0,n):
        for x in range(0,n):
            t=255-(255*abs(ma[y][x])//w)
            canevas.create_rectangle(b+x*d+1,y*d+11,b+x*d+d,y*d+10+d,fill=ma[y][x]<0 and hexColor(t,t,255) or ma[y][x]>0 and hexColor(255,t,t) or hexColor(255,255,255),outline="")
            if camp == 2:
                canevasHist.create_rectangle(b+x*d+1,y*d+11,b+x*d+d,y*d+10+d,fill=ma[y][x]<0 and hexColor(t,t,255) or ma[y][x]>0 and hexColor(255,t,t) or hexColor(255,255,255),outline="")
           
           
    canevas.itemconfig(labelScore,text="An: "+str(j)+" // Score: "+str(s)[:10])

On remarque que les couleurs sont générées au moyen d’un code
RGB
, or
tKinter
n’accepte que des chaines de caractères, donc
(cours de
NSI
;) )
, on convertit les valeurs en hexadécimal et on crée un code de la forme
"#rrggbb"
.
Code: Select all
def hexColor(r,g,b):
    r = "0" + hex(r)[2:]
    g = "0" + hex(g)[2:]
    b = "0" + hex(b)[2:]
    return "#"+r[len(r)-2:len(r)]+g[len(g)-2:len(g)]+b[len(b)-2:len(b)]

On obtient ainsi le résultat suivant.

Bon au cours du développement de cette couche graphique, on a constaté que
Pavel
avait codé la sienne de son coté et qu’il l’avait rendue publique pendant le concours. Heureusement bien peu ont compris l’importance de ces simulations graphiques.


ANALYSE DES RÉSULTATS

A partir de là, nous avons commencé à faire des tirages aléatoires sans
IA
.

Les 30 000 000 de tirages réalisés pendant la nuit furent analysés en détails, et des grilles de
sudoku
furent coloriées pour identifier les positions initiales de 6 couples ayant de gros scores.

Nous avons eu confirmation que cela ressemblait au jeu de la vie et avons compris quelques règles :
  • Il faut semer 3 cases différentes mais proches d’une même colonie pour avoir un développement exponentiel.
  • Quand les colonies Atlantes et Muennes se rencontrent, elles se détruisent. Une trop forte densité d’une colonie amène aussi à son auto destruction par le centre.
  • Il existe des états stables mais nous ne les avons pas trouvé optimaux en terme de score à la fin de l’an 42.
  • Le score monte plus vite si les deux colonies se développent, donc
    aleatn(5)
    ne produira jamais un gros score,
    aleatn(6)
    lui peut faire un gros score.
Pour affiner les résultats, nous avons décidé de sauvegarder les bonnes listes et non plus uniquement les meilleures listes.


NUITS DE FOLIE : 6 À 12 SCRIPTS QUI TOURNENT EN PARALLÈLE

Quelques nuits de folies plus tard ...
Code: Select all
listealeat = []
tirage = [0 for k in range(42)]

best_list =  []
best_scor = 0

good_list = []
good_scor = []
good_indice = 0

def sauvegarde(sauveliste,score,tirage,annee):
    global best_indice, best_scor, good_list, good_scor, good_indice, best_list
    if score > 15500: #Le chiffre de 15500 a régulièrement été augmenté
        # On sauvegarde les listes de couples donnant 15500 min
        good_list.append(sauveliste)
        good_scor.append(score)
        good_indice+=1
    if score > best_scor:
         # On sauvegarde la meilleur liste trouvée
        best_list = sauveliste[0:annee]
        best_scor = score
        print("\n======= Meilleur score ======== tirage n° ",tirage, "sur",annee, "années ======== ")
        print("Score : ",score)
        print("liste = ",best_list[0:annee])

def calcule_score(liste,tirage,annee):
    m=42
    sauveliste = liste
    # print(sauveliste)
    # input()
    while len(liste)<m:
        liste.append((0,0))
    score = st(liste)
    sauvegarde(sauveliste,score,tirage,annee)

def forcealeat(annee,nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee]+=1
        for i in range(annee):
                listealeat.append(((-1)**i*random.randint(1,9),(-1)**i*random.randint(1,9)))
                # le choix de faire un coup négatif un coup positif peut se discuter...
                random.shuffle(listealeat)
        calcule_score(listealeat,tirage[annee],annee) 
    print(30*"##")
    print("fini,",nbtirage, "tirages de",annee, "couples aléatoires")
    print("bonne liste : ",good_indice)
    print("MeilleurScore : ",best_scor)
    print("liste = ",best_list)

def forcealeatgeometrie6(annee,nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee]+=1
        col1 = random.randint(1,6)
        lig1 = random.randint(1,9)
        col2 = random.randint(1,9)
        lig2 = random.randint(1,6)
        listealeat.append((col1,lig1))
        listealeat.append((col1+1,lig1))
        listealeat.append((col1+2,lig1))
        listealeat.append((-1*col2,-1*lig2))
        listealeat.append((-1*col2,-1*(lig2+1)))
        listealeat.append((-1*col2,-1*(lig2+2)))
        random.shuffle(listealeat)
        calcule_score(listealeat,tirage[annee],annee) 
    print(30*"##")
    print("fini,",nbtirage, "tirages de",annee, "couples aléatoires")
    print("bonne liste : ",good_indice)
    print("MeilleurScore : ",best_scor)
    print("liste = ",best_list)



JEUX AVEC LE MOTEUR GRAPHIQUE

A l’aide du moteur graphique, on a pu analyser les figures donnant des
états stables
. C’est à dire qu’à partir d’une configuration donnée, on obtient une configuration qui n’évolue plus dans le temps.

Ainsi, on obtient les résultats suivants.

1er état stable, avant-après :

2ème état stable, avant-après :

Un 3ème, très joli :

Avec ces états, on observe un autre comportement du programme, les bords interagissent entre eux.


TIRAGES ALÉATOIRES AVEC IA

Nos résultats étaient satisfaisants et ils nous permettait d’obtenir un score supérieur à 18 000, mais beaucoup de tirage étaient gâchés car l’algorithme manquait de discernement.

Nous avons alors repris les coloriages et amélioré notre script de tirage. L’heure de l’
IA
avait sonné.
Oui on utilise facilement le mot
IA
alors que ... on a juste réfléchit et que les scripts sont eux toujours aussi stupides.


Ce script a réalisé à lui tout seul plus de 20 000 000 de tirage, déjà parce qu’il était beau, et ensuite parce que nous voulions obtenir une liste significative de tirage ayant un score supérieur à 18 000.

forcealeatIA(6,7000000)
nous au ainsi donné 154 tirages certifiés supérieurs à 18 000.
Code: Select all
def forcealeatIA(annee, nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee] += 1
        na = random.randint(1, 9)
        ma = random.randint(1, 9)
        nlist = [max(na - 1, 1), na, min(na + 1, 9)]
        mlist = [max(ma - 1, 1), ma, min(ma + 1, 9)]
        pa = random.randint(1, 9)
        qa = random.randint(1, 9)
        plist = [max(pa - 1, 1), pa, min(pa + 1, 9)]
        qlist = [max(qa - 1, 1), qa, min(qa + 1, 9)]
        for i in range(annee // 2):
            listealeat.append((random.choice(nlist), random.choice(mlist)))
            listealeat.append(((-1) * random.choice(plist), (-1) * random.choice(qlist)))
        random.shuffle(listealeat)
        goodliste(listealeat, tirage[annee], annee)
    print(30 * "##")
    print("fini,", nbtirage, "tirages de", annee, "couples aléatoires")
    print("bonne liste : ", good_indice)
    print("MeilleurScore : ", best_scor)
    print("liste = ", best_list)

Ces tirages ont alors été mélangés aléatoirement, histoire de s’assurer vérifier que un autre ordre ne nous donnerait pas un meilleur score.

La variable
goodliste
contenait à ce moment là une liste de listes, nos 154 listes que nous avons mélangés 100 000 fois procédant ainsi à 15 000 000 nouveaux tirages.
Code: Select all
def improve_liste():
    global goodliste
    listetraiteeok = 0
    for listeatraiter in goodliste:
        listetraiteeok += 1
        annee = len(listeatraiter)
        for i in range(100000):
            listemelange = listeatraiter[0:annee]
            random.shuffle(listemelange)
            calcule_score(listemelange, i, annee)
        if listetraiteeok % 10 == 0:
            print("liste mélangées :", listetraiteeok, "1000 fois")

In fine, nous avons obtenu trois 4 listes ayant un score supérieur à 19 000.
Code: Select all
[(-1, -4), (-2, -5), (8, 1), (-3, -5), (7, 1), (7, 3)]
[(2, 3), (2, 4), (-6, -7), (1, 2), (-6, -9), (-5, -7)]
[(5, 3), (7, 3), (7, 4), (-1, -7), (-3, -7), (-1, -6)]
[(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]

MeilleurScore : 19207.913058803344
liste = [(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]



DERNIÈRE APPROCHE GAGNANTE

La dernière approche
(gagnante)
fut de procéder par force brute sur des listes ayant un bon patrimoine génétique.

Nous avions à notre disposition des nombreuses listes courtes avec des scores supérieur à 18 000 voir 19 000. Et si nous cherchions à les rallonger ?

Certains résultats obtenus par
forcealeatIA(9,1000000)
étaient surprenant. Certaines listes de 9 couples avaient un bon score, mais si on ne prenait que la liste des 6 premiers couples le score était mauvais.

Un script sur mesure fut donc codé.

La variable
goodliste
contenait à ce moment là une unique liste, que l’on voulait compléter.
  • add_liste(goodliste, an, 1)
    quelques secondes, 163 tirages
  • add_liste(goodliste, an, 2)
    quelques minutes, 26 569 tirages
  • add_liste(goodliste, an, 3)
    quelques heures, plus de 4 000 000 de tirages
Nous n’avons pas testé
add_liste(goodliste, an, 4)
par manque de temps.

Par contre, sur 6,8,12 thread le script
add_liste(goodliste, an, 3)
a tourné non stop sur des listes sélectionnées avec amour au moyen des scripts
forcealeatIA(annee, nbtirage)
qui continuait à tourner, dès fois que ...
Code: Select all
def add_liste(listeatraiter, annee, rangsup=1):
    liste = listeatraiter.copy()
    # on essaie avec (0,0)
    liste.append((0, 0))
    listescore = liste.copy()
    calcule_score(listescore, 0, annee + 1)
    if rangsup - 1 > 0:
        add_liste(liste, annee + 1, rangsup - 1)
    liste.pop(len(liste) - 1)
    # on essaie avec (+,+)
    for i in range(1, 10, 1):
        for j in range(1, 10, 1):
            liste.append((i, j))
            listescore = liste.copy()
            calcule_score(listescore, 10 * i + j, annee + 1)
            if rangsup - 1 > 0:
                add_liste(liste, annee + 1, rangsup - 1)
            liste.pop(len(liste) - 1)
    # on essaie avec (-,-)
    for i in range(-9, 0, 1):
        for j in range(-9, 0, 1):
            liste.append((i, j))
            listescore = liste.copy()
            calcule_score(listescore, 10 * i + j, annee + 1)
            if rangsup - 1 > 0:
                add_liste(liste, annee + 1, rangsup - 1)
            liste.pop(len(liste) - 1)

an = len(goodliste)
add_liste(goodliste, an, 2)
print(good_list)



CHRONOLOGIE DES SCORES OBTENUS

  1. 15/10 17:00 : 15016

    Pour l’instant on pédale dans la semoule
    global s,j,w # sjw, je ne sais pas si c’est fait exprès mais...
  2. 15/10 19:34 : 17142

    On n’a toujours aucun graphique ni aucune idée de ce qui se passe mais si ça ressemble fortement à des multiplications matricielles.
  3. 16/10 14:16 : 18157

    Score de la nuit sur 10 000 000 de tirages pas vraiment optimisés.
  4. 23/10 10:30 : 18860

    Objectif 19000 avant la fin de la journée.
  5. 23/10 11:30 : 19117

    Prochain objectif : 19430
    (pour doubler un autre candidat)
    .
  6. 24/10 10:07 : 19675

    Finalement 19430 n’était qu’une formalité.
    Maintenant pour aller jusqu’à 21700 il va falloir trouver une autre méthode, celle-ci est un peu longue, mais comme il faut chauffer un peu la maison je ne suis responsable d’aucun meurtre supplémentaire de pingouin.
  7. 24/10 21:13 : 20180

    500 points de plus ! Et c’est pas fini !
  8. 28/10 22:12 : 20475

    Il me tarde de savoir comment a fait
    Pavel
    parce que j’ai tout donné et que j’ai 7 scripts qui moulinent sur mon PC...
  9. 28/10 22:12 : 20972

    Je ne perds pas espoir de finir 1er, mais stratégiquement je me dis que j’ai peut-être intérêt à envoyer mes scores le dernier jour pour que le 1er ne puisse pas réagir...
    C’est beau de rêver ... 20972 fut notre meilleur score.


CONCLUSIONS

Une estimation basse du nombre de tirages que nous avons réalisé donne 100 000 000 de tirages. Mais comme les scripts tournaient non stop en parallèle, nous pensons qu’on s’approche plus des 200 000 000 de tirages et simulations diverses pas du tout optimales.

Ne maîtrisant pas encore les
exports / imports
CSV
en
Python
nous avons été limités par la nécessité d’arrêter manuellement les scripts, de copier / coller les bons résultats et de relancer les scripts, mais pour le défi de l’année prochaine nous seront prêts.

Félicitation une nouvelle fois à
Pavel
qui a dominé les 3 épreuves mais semble ne pas partir avec les mêmes connaissances de base que le simple visiteur des sites
TI-Planet
et
Planète Casio
.

L’année prochaine, il est probable que l’on donnera le concours
Python
en devoir maison facultatif aux élèves de spé
NSI
de Terminale de notre lycée, histoire de voir s’ils ont fixé des connaissances et s’ils font preuve d’initiative et d’autonomie.

Se classer dans les 10 premiers : 18/20, coefficient 0,42.
Se classer devant le prof : 20/20, coefficient 0,666.
https://nsi.xyz/concours-de-rentree-201 ... -en-python


3ème
:

Afyu
n'interfère quant à lui que
10
fois
:
  • 3
    fois pour les
    Atlantes
  • 7
    fois pour les
    Muens
Ce qui fait la différence avec
20453
points en l'an
42
! :bj:
Une longévité de plus exceptionnelle, les
Atlantes
mettant pas moins
277
ans à achever les derniers
Muens
pour
136275
points ! :bj:
Afyu wrote:Voici comment j'ai procédé pour la résolution du défi en langage historique :

J'ai effectué mes premiers essais sur la ressource NumWorks proposée pour le concours, avec des do(1,c,l) et des do(-1,c,l) qui permettent de placer des civilisations rouges ou bleues en indiquant la position en ligne et en colonne (vivement l'implémentation du getkey() pour simplifier tout ça !).

Après quelques (nombreux) essais, j'ai découvert que le score augmentait bien plus vite lorsqu'on "oubliait" de placer une colonie et qu'on laissait passer une année. J'ai donc essayé de réduire fortement le nombre de colonies à placer et un nombre de colonies autour de 10 semblait être bien.

J'ai également découvert que le score n'augmente pas tant qu'il n'y a qu'une civilisation (donc qu'une seule couleur) de placée. De plus, il faut au minimum 3 colonies d'une même civilisation pour que cette dernière se développe. Donc il faut au minimum 6 colonies (3 pour chaque civilisation) pour que les deux civilisations se développent. Dernier point : pour qu'une civilisation se développe, il faut que les 3 colonies placées soient les voisines d'une même cellule vide pour y faire apparaître une colonie (une ressemblance avec le Jeu de la vie de John Conway ? :D).

Partant de ce constat et trouvant que taper des do(+-1,c,l) est assez fastidieux, j'ai commencé à automatiser le placement de mes colonies, en utilisant la programmation en Python. J'ai repris le programme de la ressource NumWorks et je l'ai un peu modifié, mais hors ressource NumWorks, pour gagner en confort (de modification, de vitesse et de capacité de mémoire de travail).

À la fin du programme, j'ai ajouté quelques lignes pour initialiser une liste de colonies à placer, puis pour modifier aléatoirement des éléments de cette liste et pour déterminer et afficher le score obtenu avec cette liste.

On initialise la liste de colonies à placer à (0,0) pour chacune des 42 années (donc 42 colonies). Ensuite, on répète 50 000 fois l'essai suivant : on choisit un nombre entier entre 0 et 9 pour modifier une des 10 premières colonies à placer, puis on modifie le couple de coordonnées de cette colonie à placer, en essayant de placer une colonie Muenne, puis une colonie Atlante.
Code: Select all
from random import randint
liste0=[(0,0)]*42
liste=liste0[:]
st(liste)
for k in range(50000):
    a=randint(0,9)
    liste[a]=(-randint(1,9),-randint(1,9))
    st(liste)
    liste[a]=(randint(1,9),randint(1,9))
    st(liste)


Ensuite, j'ai modifié mon programme pour n'afficher le score obtenu que s'il est meilleur que le meilleur score déjà obtenu. Il faut donc stocker le meilleur score obtenu et comparer chaque nouveau score avec ce meilleur score. On initialise donc une liste scores qui stocke les meilleurs scores obtenus et une liste gagnant qui stocke les listes correspondantes. On stocke la valeur -1 dans scores pour s'assurer que le premier test effectué (sur une liste de 42 couples à (0,0)) stocke bien un score à 0, associé à une liste de couples à (0,0) dans gagnant.
Code: Select all
scores=[-1]
gagnant=[]

Dans le programme, j'ai remplacé la ligne qui affiche "Bon score ? Envoie la liste 'atmu' à ..." par mon test de comparaison et un éventuel stockage du nouvau score obtenu. On vérifie si on a atteint la 42ème année et si le nouveau score obtenu est meilleur que l'actuel meilleur score. Si c'est le cas, on ajoute la nouvelle meilleure liste à gagnant et le nouveau meilleur score à scores et on affiche cette nouvelle meilleure liste, puis ce nouveau meilleur score, l'année (pour vérification) et enfin la longueur de la liste (pour vérification). Le # affiché en début de sortie me permet de faire un copier-coller de cette nouvelle meilleure liste pour remplacer ma liste0, tout en gardant une trace du score associé et sans avoir à commenter ce score pour ne pas avoir d'erreur à l'exécution.
Code: Select all
        if j==42 and s>scores[-1]:
            gagnant.append(liste[:])
            print(liste)
            scores.append(s)
            print("#",s,j,len(liste))


Le stockage de la meilleure liste n'est pas indispensable, un simple affichage suffit. Mais je la stocke pour la reprendre après un certain nombre d'essais infructueux. Je ne sais pas si c'est la meilleure stratégie, mais elle m'a semblée plutôt efficace.
J'initialise à 0 une variable nb_chgt qui stocke le nombre de changements effectués, au même moment que je crée ma liste0. Ensuite, j'ajoute à la fin de mon programme quelques lignes qui permettent d'augmenter le compteur du nombre de changements effectués, puis de récupérer la dernière meilleure liste stockée après un certain nombre de changements effectués.
Code: Select all
   nb_chgt+=1
    if nb_chgt=20:
    nb_chgt=0
    liste=gagnant[-1]


J'aurais sûrement pu éviter de stocker dans la liste gagnant TOUS les meilleurs scores obtenus et ne garder que le dernier. Pour ça, il faut déclarer la variable gagnant comme étant globale et non pas locale, je crois, mais je ne maîtrise pas cette subtilité et je n'ai pas cherché comment faire. :D

J'ai ensuite laissé tourner ce programme durant de nombreuses heures/jours/semaines, en espérant améliorer mon score jusqu'à l'infini et au-dela !
J'ai remarqué qu'une liste qui comporte des couples de (0,0) entre des colonies assure souvent un meilleur score en les supprimant et en rapprochant du début de la liste les dernières colonies placées. :)
Par exemple, la liste [(5, 5), (5, 4), (7, 4), (-2, -6), (-2, -5), (-2, -4), (-6, -1), (-2, -1), (-3, -3), (0, 0), (-8, -9)] donne un score de 20300 tandis que la liste [(5, 5), (5, 4), (7, 4), (-2, -6), (-2, -5), (-2, -4), (-6, -1), (-2, -1), (-3, -3), (-8, -9)] donne un score de 20453, simplement en avançant la dernière colonie à la place du (0,0).

Parmi les autres essais que j'ai effectués :
Je vais appeler seed une liste assez courte de civilisations à placer, suivies de couples tous à (0,0) jusqu'à atteindre 42 années.
J'ai essayé de trouver le meilleur seed de 6 de long, puis de 7 de long, jusqu'à 10 de long. J'ai donc modifié le randint(0,9) pour que le choix des colonies à modifier ne soit plus parmi les 10 premières, mais seulement parmi les 6 premières randint(0,5), etc.

Uniquement pour la recherche du meilleur seed de 6 de long, j'ai effectué une recherche exhaustive (enfin, je crois :D) en choisissant soit de placer 3 colonies Atlantes suivies de 3 colonies Muennes, soit d'alterner les colonies. C'est lors de ces essais que j'ai constaté qu'on obtenait souvent (toujours ?) un meilleur score en plaçant d'abord les colonies Atlantes. Pour éviter de multiplier les essais, j'ai raisonné en terme de symétrie et de distance. Par symétrie, on peut placer la première colonie (liste[0]) au milieu de la grille (donc en (5,5)) et placer la 2ème colonie (liste[1]) de la même civilisation dans 1/8 de disque et à une distance de maximum 2 de la colonie placée au centre (ce qui laisse donc seulement 5 cellules à tester : (5,4);(5,3);(6;4);(6;3);(7;3) tous les autres cas pouvant être obtenus par symétrie de ces 5). De même, la 3ème colonie (liste[2]) de la même civilisation est à placer à une distance de maximum 2 de chacune des deux premières colonies placées (pour assurer l'apparition d'une 4ème colonie, etc), ce qui limite beaucoup le nombre de positions possibles.
Pour les colonies de l'autre civilisation, je les ai placées en parcourant toute la grille et en respectant une distance de maximum 2 entre les colonies placées avec
Code: Select all
for k in range(c-2,c+2+1):
    cc=(k+9-1)%9+1
la position cc de la nouvelle colonie à placer varie entre c-2 et c+2 avec c la position de la précédente colonie placée de la même civilisation et la position cc de la nouvelle colonie à placer est modifiée si elle est inférieure à 1 ou supérieure à 9 pour être ramenée dans la grille, en considérant que cette dernière est un tore (donc 0 devient 9 et -1 devient 8 et 10 devient 1 et 11 devient 2). Ma précédente approche pour cette distance inférieure à 2 était d'utiliser for cc in range(max(1,c-2),min(c+2,9)+1): qui oublie quelques cas particuliers lorsqu'une colonie est proche d'un bord de la grille, donc à oublier.
Cette recherche exhaustive ressemble donc à :
Code: Select all
liste[0]=(5,5)
liste[1]=(5,4)

for a in range(5,7+1):
  for b in range(3,6+1):
     
    for c in range(1,9+1):
      for d in range(1,9+1):
        print(a,b,c,d)
        for k in range(c-2,c+2+1):
          cc=(k+9-1)%9+1
          for l in range(d-2,d+2+1):
            dd=(l+9-1)%9+1
            for kk in range(c-2,c+2+1):
              ccc=(kk+9-1)%9+1
              for ll in range(d-2,d+2+1):
                ddd=(ll+9-1)%9+1
                liste[2]=(-a,-b)
                liste[3]=(c,d)
                liste[4]=(cc,dd)
                liste[5]=(ccc,ddd)
                st(liste)
Et pour alterner les civilisations, il suffit de remplacer l'ordre 0,1,2,3,4,5 des indices x donnés dans liste[x] par 0,2,4,1,3,5.


J'ai obtenu un score de 19207 avec [(5, 5), (5, 4), (7, 4), (-2, -6), (-2, -5), (-2, -4)] qui est a compléter avec des (0,0) pour atteindre 42 années.

À partir de ce score, j'ai essayé de trouver le meilleur score en complétant avec une 7ème colonie, puis une 8ème, jusqu'à 11 ou 12. Essayer de placer plus de 12 colonies ne m'a jamais donné un meilleur score, alors j'ai fini par ne tester que jusqu'à 12.

J'ai également essayé, en partant d'une liste avec un bon score, de parcourir toutes les positions possibles pour deux couples qui se suivent (de rangs rang1 et rang2) de la liste.
Code: Select all
rang1=9
rang2=rang1+1
for a in range(0,10):
  print(a)
  for b in range(0,10):
    print(b)
    for aa in range(0,10):
      for bb in range(0,10):
        liste[rang1]=(a,b)
        liste[rang2]=(aa,bb)
        st(liste)
        liste[rang2]=(-aa,-bb)
        st(liste)
        liste[rang1]=(-a,-b)
        st(liste)
        liste[rang2]=(aa,bb)
        st(liste)


Autre essai effectué : en partant d'une liste donnant un score de 20266 (liste [(5, 5), (5, 4), (7, 4), (-2, -6), (-2, -5), (-2, -4), (5, 9), (-6,-1), (-6, -8), (-8, -6), (-3, -8), (0, 0), (-6, -5)] à compléter jusqu'à 42 années) j'ai essayé de décaler de 0 ou de 1, horizontalement ou verticalement, vers la gauche ou vers la droite, vers le haut ou vers le bas, chacune des colonies placées en espérant améliorer mon score... sans succès. :(
Code: Select all
for i1 in [-1,0,1]:
  for j1 in [-1,0,1]:
    for i2 in [-1,0,1]:
      for j2 in [-1,0,1]:
        for i3 in [-1,0,1]:
          for j3 in [-1,0,1]:
            for i4 in [-1,0,1]:
              for j4 in [-1,0,1]:
                print(i1,j1,i2,j2,i3,j3,i4,j4,100*((i1+1)/3+(j1+1)/9+(i2+1)/27+(j2+1)/81+(i3+1)/243+(j3+1)/729+(i4+1)/2187)+(j4+1)/6561)
                for i5 in [-1,0,1]:
                  for j5 in [-1,0,1]:
                    for i6 in [-1,0,1]:
                      for j6 in [1]:
                        for i7 in [-1,0,1]:
                          for j7 in [-1,0,1]:
                            liste=[(5, 5), (5, 4), (7, 4), (-2, -6), (-2, -5), (-2, -4), (5+i1, 9+j1),(-6+i2, -1+j2), (-6+i3, -8+j3), (-8+i4, -6+j4), (-3+i5, -8+j5), (0+i6, 0+i6), (-6+i7, -5+j7), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0,0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0)]
                            st(liste)
La ligne avec les fractions permet simplement d'afficher le pourcentage d'avancement de la recherche.


J'ai obtenu de nombreux scores entre 20000 et 20453, sans jamais faire mieux. En voyant le détail de la liste proposée par Pavel, j'ai compris (mais un peu tard) qu'une liste qui donne un excellent score ne provient pas forcément d'un seed qui donne un très bon score. Ma recherche des meilleurs seed n'était donc pas la meilleure stratégie, mais quand on ne connait ni le recuit simulé, ni les algorithmes génétiques... :p

Je tiens à remercier toutes les personnes qui ont permis l'organisation de ce concours avec un aussi grand nombre de lots de qualité ! Merci !! :D
viewtopic.php?f=49&t=23051&p=249030#p249029


2nd
:

cent20
n'intervient lui que
9
fois
:
  • 3
    fois pour doper les
    Atlantes
  • puis
    6
    fois pour doper les
    Muens
Il nous repousse ainsi le record à pas moins de
20972
points en l'an
42
! :bj:
Dommage toutefois que cela dure moins, les
Atlantes
ne mettant que
102
ans à conquérir le monde pour
44277
points.
cent20 wrote:Après le passionnant nous nous sommes attaqué au défi historique, proposé par les sites internet
TI-Planet
et
Planète Casio
et les équipes de bénévoles passionnés qui animent ces communautés.


LE CONTEXTE

Il existait autrefois au coeur du grand océan appelé Pacifique un empire, l’empire de Mu. Grâce à l’énergie du soleil qu’ils avaient réussi à maîtriser complètement les Lémuriens menaient une vie tranquille et prospère. A la même époque, une autre civilisation celle de l’Atlantide régnait au centre de l’autre océan, l’Atlantique. Les Atlantes eux aussi savaient contrôler la puissance du soleil et ils avaient construit un puissant empire.
Mais un jour, la guerre éclata entre la terre de Mu et l’Atlantide pour une raison si insignifiante que l’histoire elle-même l’a oubliée. La guerre dura longtemps, de nombreuses années, car les forces des deux puissances étaient égales. Jusqu’au jour où les hommes firent usage de l’arme solaire. C’est ainsi que ces deux grandes civilisations disparurent, englouties au fond des deux océans…

Tu n’as rien compris ? Normal, cela fait parti du challenge !
(lire l’intégralité du défi : Concours de rentrée 2019 - défi langage historique)


Il était possible de participer avec un script en
Casio-Basic
,
TI-Basic
, ou en
Python
. Nous avons bien évidement choisi le langage
Python
pour sa souplesse, et la capacité que nous avions à le faire tourner sur un
PC
sur divers
IDE Python
.

Dans la suite de l’article, le "nous" fait référence aux participants
cent20
et
Golden Man
, car nous avons réalisé les recherches en commun.


PREMIERS TESTS

Tout commence par des premiers tests à la main, et en tout premier lieu nous avons commencé par neutraliser le traitement graphique du script, les affichages textes, pour chercher à l’aveugle par ce que sinon cela n’est pas assez difficile...
Code: Select all
from math import log10,sqrt
def init():
    global atmu,n,j,s,ma,mb,mc,w,fp,fm
   
    atmu = []
    n = 9
    j = 0
    s = 0
    w = 5
    fp = 0
    fm = 0
    ma = [[0]*n for k in range(n)]
    mb = [[0]*n for k in range(n)]
    mc = [[0]*n for k in range(n)]

"""
A CREUSER

def dr():
    global s,j,w # sjw (je sais pas si c'est fait expres, mais c'est tres drole)
    sw=320
    d,h=min(sw//n,221//n),(color(0,0,0),color(255,255,255))
    b=sw-1-n*d
   
    for i in range(0,n*d+1,d):
        fill_rect(b,i,n*d,1,h[0])
        fill_rect(b+i,0,1,n*d,h[0])
       
    for y in range(0,n):
        for x in range(0,n):
            t=255-(255*abs(ma[y][x])//w)
            fill_rect(b+x*d+1,y*d+1,d-1,d-1,ma[y][x]<0 and (t,t,255) or ma[y][x]>0 and (255,t,t) or h[1])
           
    draw_string(" ATLEMU ",1,1,color(255,255,0),color(127,127,127))
    draw_string("Muen\ndo(1,c,l)",0,19,color(0,0,255),h[1])
    draw_string("Atlante\ndo(-1,c,l)",0,53,color(255,0,0),h[1])
    draw_string("Passer\ndo(0)",0,87,color(255,0,255),h[1])
    draw_string("An: "+str(j)+"\nScore:\n"+str(s)[:10],0,n*d-49)
   
"""

def do(*ar):
   
    global j,gp,gm,fp,fm,s
   
    j = j+1 # Indice de la liste des couples et nombre d'annees
    k = ar[0] # Notre premier argument (le camp choisi (ou passer))
    v = (len(ar)%2) or ar[len(ar)-1] # v = 1 ou 0 selon la longueur (3 ou 1)
    (sc,sl) = (len(ar)>=3) and (ar[1],ar[2]) or (0,0) # Les deux derniers
   
    # permet de recuperer les deux derniers elements de do(a,b,c)
    # a = equipe ; b = colonnes ; c = lignes
   
    k = k and k//abs(k) # Change pas k (fausse piste je pense)
   
    # Changement de nom
    gp = fp
    gm = fm
   
    for y in range(n):
        # mb possiblement une sauvegarde
        # mc devient une copie de mb
        mb[y]=mc[y].copy()
       
    for y in range(n):
        for x in range(n):
           
            o = ma[y][x]
           
            # Le gros tas
            ma[y][x] = ma[y][x]+w*(ma[y][x]==0 and x==sc and y==sl)*((k>0)-(k<0))+(ma[y][x]<=0 and (x-sc or y-sl or k==0) and mb[y][x]//10==3)*((ma[y][x]==0)*w-ma[y][x]*(not(not(ma[y][x]))))-(ma[y][x]>=0 and (x-sc or y-sl or k==0) and mb[y][x]-10*(mb[y][x]//10)==3)*((ma[y][x]==0)*w+ma[y][x]*(not(not(ma[y][x]))))
           
            if o and ma[y][x]==o:
               
                ls=(-1,w>abs(ma[y][x]))
                ma[y][x]=ma[y][x]+(ma[y][x]>0)*ls[mb[y][x]//10==3 or mb[y][x]//10==4]-(ma[y][x]<0)*ls[mb[y][x]-10*(mb[y][x]//10)==3 or mb[y][x]-10*(mb[y][x]//10)==2]
           
            if ma[y][x]-o:
               
                fp = fp+(ma[y][x]>0 and not(o))-(o>0 and not(ma[y][x]))
                fm = fm+(ma[y][x]<0 and not(o))-(o<0 and not(ma[y][x]))
               
                if not(o) and ma[y][x] or o and not(ma[y][x]):
                    for dl in range(-1,2):
                        for dc in range(-1,2):
                            if dl or dc:
                                mc[y+dl+(dl<0 and y==0)*n-(dl>0 and y==n-1)*n][x+dc+(dc<0 and x==0)*n-(dc>0 and x==n-1)*n]+=(ma[y][x]<0)-(o<0 and 0==ma[y][x])+10*((ma[y][x]>0)-(o>0 and 0==ma[y][x]))
    if max(fp,gp)*max(fm,gm):
        s=s/(1+abs(k)*log10(sqrt(j)))+fp*fm*min(fp,gp)*min(fm,gm)/max(fp,gp)/max(fm,gm)
   
    # The final code !
    # Il est ici
    # Chaque elements est de la forme (sc*k+k,sl*k+k)
   
    atmu.append((sc*k+k,sl*k+k))
   
    if v:
        # dr()
        print("Bon score ? Envoie la liste\n'atmu' a info@tiplanet.org")
    return s
def st(l,v=False):
    init()
    for p in l:
       
        # C'est ici qu'on triche !
        # On va pas utiliser une liste de couple, mais une liste de liste
        # comme ca, c'est modifiable comme on veut
       
        # J'ai mis v sur False pour pas avoir le message "Bon score..."
       
        s=do((p[0]>0)-(p[0]<0),abs(p[0])-1,abs(p[1])-1,v)
    # dr()
    return s
init()

actions = [[0,0] for k in range(42)]
rien = [0,0]
scores = []
refscores = []
def chasse():
    for k in range(100): # On va tester au max
        for i in range(42):
            scores = []
            for t in [-1,1]:
                for col in range(1,10):
                    for lig in range(1,10):
                        actions[i] = [t*(col+1),t*(lig+1)]
                        scores.append(st(actions))
                        refscores.append([t,col,lig])
            actions[i] = rien
            scores.append(st(actions))
            refscores.append(rien)
            if refscores[scores.index(max(scores))] != rien:
                actions[i] = [refscores[scores.index(max(scores))][0]*(refscores[scores.index(max(scores))][1]+1),refscores[scores.index(max(scores))][0]*(refscores[scores.index(max(scores))][2]+1)]
            else:
                actions[i] = rien
            print("Annee",i,":",max(scores))


Tout commence avec des tirages aléatoires très aléatoires sans aucune réflexion, et ayant réussi à fabriquer une liste de 5 couples avec un score acceptable
(on le pense alors !)
, on essaye de l’améliorer, et de tirer d’autres listes de 5 couples acceptables.
Code: Select all
import random
def aleat5():
    m = 42
    l = [(-2,-2), (2,3), (-2,-4), (2,5), (-4,-3)] # la liste de départ
    while len(l)<m:
        l.append((0,0))
    scoremax = st(l)
    print("score liste : ", scoremax)
    equipe = [1, -1]
    l = []
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(5):       
            random.shuffle(equipe)
            l.append((equipe[0]*random.randint(1,9),equipe[0]*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)   
       
        if scorerandom > scoremax:
            print("Meilleur score", scorerandom)
            print("Liste",l[0:5])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)

Cette méthode est un échec, les scores générés ne dépassent pas 100 ! Nous pensions que 100 était en score acceptable car on l’a comparé naïvement au score maxi de 43.x obtenu sur le défi précédent.


ET SI ON EN TIRAIT 10 COUPLES ?

Au lieu de tirer 5 couples, on décide d’en tirer 10.

Pour rappel à ce stade nous sommes toujours aveugles, nous n’avons aucun rendu graphique à analyser pour affiner notre stratégie.
Code: Select all
import random
def aleat10():
    m = 42
    scoremax = 100
    print("score aleat5 : ", scoremax)
    equipe = [1, -1]
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(10):       
            random.shuffle(equipe)
            l.append((equipe[0]*random.randint(1,9),equipe[0]*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)       
        if scorerandom > scoremax:
            print("Meilleur score", scorerandom)
            print("Liste",l[0:10])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)

Assez rapidement, on obtient des score aux alentours de 16000-17000.

Comme au pays des aveugles les borgnes sont rois, on décide alors de continuer les tirages aléatoires de n couples et dans le même temps de développer notre propre couche graphique histoire d’y voir quelques choses et de laisser passer un peu de lumière...
Meilleur score 16685.07457023799
Liste [(-8, -3), (-4, -6), (-9, -1), (-1, -1), (4, 7), (-5, -4), (5, 9), (6, 7), (-4, -3), (-2, -5)]
Meilleur score 17304.672747006774
Liste [(7, 6), (5, 7), (7, 5), (-4, -7), (-3, -5), (-5, -5), (-3, -9), (-6, -5), (-3, -5), (-9, -8)]



TIRAGES ALÉATOIRES DE N COUPLES

Bien évidemment, on lance les fonctions
aleatn(annee)
avec des valeurs pour la variable annee comprise entre 1 et 42 mais tout ceci est très long, un unique script tourne sur un unique
IDE Python
.
Code: Select all
def aleatn(annee):
    m = 42
    scoremax = 100
    print("score kiki : ", scoremax)
    tirage = 0   
    while scoremax <100000:
        tirage+=1
        l = []
        for i in range(annee):
            l.append(((-1)**i*random.randint(1,9),(-1)**i*random.randint(1,9)))
        while len(l)<m:
            l.append((0,0))
        scorerandom = st(l)
        if scorerandom > 15000:
            print("bon score", scorerandom)
            print("Liste",l[0:annee])
        if scorerandom > scoremax:
            print("========== Meilleur score : ", scorerandom)
            print("================== Liste = ",l[0:annee])
            scoremax = scorerandom
        if tirage%1000==0:
            print("Tirages aléatoire : ",tirage)



LA PROBLÉMATIQUE DU
MULTI-THREAD

Nous n’arrivons pas à faire tourner nos scripts en
multi thread
sur
Python
en utilisant les outils adéquates, nous commençons donc par faire du
multi thread
manuel :
  • 2
    PCs
    = 2 scripts qui tournent 😄
  • 3
    IDE
    = 3 scripts qui tournent. 😅
  • 2
    PCs
    avec 3
    IDE
    = 6 scripts 🤣

Et puis sur
pycharm
nous arrivons enfin à faire tourner 10-12 scripts en parallèle.
(oui enfin, nous avions autant de fichiers que de [i]threads
, cela ressemblait vraiment à un classeur d’élève de 2nde)[/i]

Maîtrisant le
multi thread
cela fut le début de folles nuits des tirages aléatoires
Il faut bien occuper le
Ryzen 7 2700
et ses 16
threads
!


La première nuit, les fonctions
aleatn(annee)
furent lancées avec tous les entiers possible entre 4 et 14.
Je vais me coucher. J’ai lancé les 10 scripts en parallèle on verra demain matin si on a cassé le score de
Pavel
.


Et le lendemain matin les résultats furent dépouillées.


DES NOUVELLES DE LA COUCHE GRAPHIQUE

En parallèle, nous nous sommes occupés de recréer l’interface graphique en l’améliorant légèrement pour pouvoir voir comment le programme fonctionnait et, accessoirement, ce que l’on obtenait avec nos tirages.

Nous avons choisit
tKinter
pour ce travail et fixé un cahier des charges :
  • Un espace pour voir la grille.
  • Un petit commentaire pour expliquer le fonctionnement de la GUI.
  • Une reconnaissance de l’entrée des touches pour entrer les do() plus vite.
  • Un espace pour entrer des commandes spéciales (st() par ex). La détection des touches doit être désactivée pour saisir
  • Un historique :
    • Une grille
      (plus visuelle)
      .
    • Sous forme de texte.
Ainsi, il a fallu créer la fenêtre.
Code: Select all
interface = Tk()
interface.resizable(False,False)
interface.title('Concours AT//MU')

# Utilisable
utilisable = Frame(interface,borderwidth=0)
utilisable.pack(side=LEFT)
canevas = Canvas(utilisable,width=500,height=400,bg="white")
canevas.pack(side=TOP)
saisie = StringVar()
barreSaisie = Entry(utilisable,width=60,textvariable=saisie)
barreSaisie.pack(side=RIGHT)
barreSaisie.configure(state="readonly")
label = Label(utilisable,text="'W' pour (ne plus) ecrire")
label.pack(side=LEFT)
labelScore = canevas.create_text(10,240,text="An : 0 // Score = 0",anchor=NW)
canevas.create_text(10,270,text="Appuyez sur + ou - sur le clavier numerique pour choisir votre camp",anchor=NW)
canevas.create_text(10,290,text="Puis, toujours sur le clavier numerique, selectionnez votre colonne puis votre ligne avec les",anchor=NW)
canevas.create_text(10,305,text="touches 1 a 9.",anchor=NW)
canevas.create_text(10,325,text="Attention, la case (1;1) est la case en haut a gauche !",anchor=NW)
canevas.create_text(10,345,text="Pour passer une annee, appuyez sur le point du clavier numerique.",anchor=NW)
canevas.create_text(10,365,text="Pour recommencer une partie, appuyez sur 'R'.",anchor=NW)
canevas.create_text(10,385,text="Il est possible de rentrer des commandes speciales a tout moment en appuyant sur 'W'.",anchor=NW)

# Historique
historique = Frame(interface,borderwidth=0)
historique.pack(side=RIGHT)
canevasHist = Canvas(historique,width=400,height=230,bg="white")
canevasHist.pack(side=TOP)
listeHist = ScrolledText(historique,width=50,height=11)
listeHist.pack(side=BOTTOM)

Ceci étant fait, on crée une fonction récupérant les événements claviers.

Attention :
On prend bien soin de lier cette fonction à la fenêtre : interface.bind("<Key>",event)
Cette ligne envoie à la fonction
event()
la valeur quand une touche est pressée.
Code: Select all
isWriting = False
commande = ["","",""]
index = 1

def event(touche):
    global isWriting,index,commande
    touche = touche.keysym
    if touche == "w":
        if isWriting:
            barreSaisie.configure(state="readonly")
            saisie.set("do("+commande[0]+","+commande[1]+","+commande[2]+")")
        else:
            barreSaisie.configure(state="normal")
            saisie.set("")
        isWriting = isWriting == False # paradoxe du menteur
    if touche == "r":
        init()
        dr(2,0,0)
    if touche == "plus" and not isWriting:
        commande[0]="1"
    if touche == "minus" and not isWriting:
        commande[0]="-1"
    if touche == "BackSpace" and not isWriting:
        commande[index-1] = ""
        if index > 1:
            index -= 1
    if touche == "1" and not isWriting and index<3:
        commande[index] = "0"
        index += 1
    if touche == "2" and not isWriting and index<3:
        commande[index] = "1"
        index += 1
    if touche == "3" and not isWriting and index<3:
        commande[index] = "2"
        index += 1
    if touche == "4" and not isWriting and index<3:
        commande[index] = "3"
        index += 1
    if touche == "5" and not isWriting and index<3:
        commande[index] = "4"
        index += 1
    if touche == "6" and not isWriting and index<3:
        commande[index] = "5"
        index += 1
    if touche == "7" and not isWriting and index<3:
        commande[index] = "6"
        index += 1
    if touche == "8" and not isWriting and index<3:
        commande[index] = "7"
        index += 1
    if touche == "9" and not isWriting and index<3:
        commande[index] = "8"
        index += 1
    if touche == "Return":
        try:
            eval(saisie.get())
            saisie.set("")
            index=1
            commande=["","",""]
        except:
            print("aie")
    if touche == "period" and not isWriting:
        do(0)
    if not isWriting:
        saisie.set("do("+commande[0]+","+commande[1]+","+commande[2]+")")

Mais, un problème de taille était toujours présent, modifier la couche graphique pré-codée avec
kandinsky
.

Voici donc ce qu’on a pu faire.
Code: Select all
def dr(camp,xHist,yHist):
    global s,j,w,labelScore
    sw=320
    d=min(sw//n,221//n)
    b=sw-1-n*d
   
    for i in range(0,n*d+1,d):
        canevas.create_rectangle(b,10+i,b+n*d,i+11,fill=hexColor(0,0,0),outline="")
        canevas.create_rectangle(b+i,10,b+i+1,n*d+10,fill=hexColor(0,0,0),outline="")
        canevasHist.create_rectangle(b,10+i,b+n*d,i+11,fill=hexColor(0,0,0),outline="")
        canevasHist.create_rectangle(b+i,10,b+i+1,n*d+10,fill=hexColor(0,0,0),outline="")
       
    if camp != 0 and camp != 2:
        t=255-(255*abs(ma[yHist][xHist])//w)
        canevasHist.create_rectangle(b+xHist*d+1,yHist*d+11,b+xHist*d+d,yHist*d+10+d,fill=camp<0 and hexColor(t,t,255) or camp>0 and hexColor(255,t,t),outline="")
        listeHist.insert(END,str((xHist*camp+camp,yHist*camp+camp))+"\n")
    elif camp == 0:
        listeHist.insert(END,"(0, 0)\n")
    else:
        listeHist.delete(1.0,END)
       
    for y in range(0,n):
        for x in range(0,n):
            t=255-(255*abs(ma[y][x])//w)
            canevas.create_rectangle(b+x*d+1,y*d+11,b+x*d+d,y*d+10+d,fill=ma[y][x]<0 and hexColor(t,t,255) or ma[y][x]>0 and hexColor(255,t,t) or hexColor(255,255,255),outline="")
            if camp == 2:
                canevasHist.create_rectangle(b+x*d+1,y*d+11,b+x*d+d,y*d+10+d,fill=ma[y][x]<0 and hexColor(t,t,255) or ma[y][x]>0 and hexColor(255,t,t) or hexColor(255,255,255),outline="")
           
           
    canevas.itemconfig(labelScore,text="An: "+str(j)+" // Score: "+str(s)[:10])

On remarque que les couleurs sont générées au moyen d’un code
RGB
, or
tKinter
n’accepte que des chaines de caractères, donc
(cours de
NSI
;) )
, on convertit les valeurs en hexadécimal et on crée un code de la forme
"#rrggbb"
.
Code: Select all
def hexColor(r,g,b):
    r = "0" + hex(r)[2:]
    g = "0" + hex(g)[2:]
    b = "0" + hex(b)[2:]
    return "#"+r[len(r)-2:len(r)]+g[len(g)-2:len(g)]+b[len(b)-2:len(b)]

On obtient ainsi le résultat suivant.

Bon au cours du développement de cette couche graphique, on a constaté que
Pavel
avait codé la sienne de son coté et qu’il l’avait rendue publique pendant le concours. Heureusement bien peu ont compris l’importance de ces simulations graphiques.


ANALYSE DES RÉSULTATS

A partir de là, nous avons commencé à faire des tirages aléatoires sans
IA
.

Les 30 000 000 de tirages réalisés pendant la nuit furent analysés en détails, et des grilles de
sudoku
furent coloriées pour identifier les positions initiales de 6 couples ayant de gros scores.

Nous avons eu confirmation que cela ressemblait au jeu de la vie et avons compris quelques règles :
  • Il faut semer 3 cases différentes mais proches d’une même colonie pour avoir un développement exponentiel.
  • Quand les colonies Atlantes et Muennes se rencontrent, elles se détruisent. Une trop forte densité d’une colonie amène aussi à son auto destruction par le centre.
  • Il existe des états stables mais nous ne les avons pas trouvé optimaux en terme de score à la fin de l’an 42.
  • Le score monte plus vite si les deux colonies se développent, donc
    aleatn(5)
    ne produira jamais un gros score,
    aleatn(6)
    lui peut faire un gros score.
Pour affiner les résultats, nous avons décidé de sauvegarder les bonnes listes et non plus uniquement les meilleures listes.


NUITS DE FOLIE : 6 À 12 SCRIPTS QUI TOURNENT EN PARALLÈLE

Quelques nuits de folies plus tard ...
Code: Select all
listealeat = []
tirage = [0 for k in range(42)]

best_list =  []
best_scor = 0

good_list = []
good_scor = []
good_indice = 0

def sauvegarde(sauveliste,score,tirage,annee):
    global best_indice, best_scor, good_list, good_scor, good_indice, best_list
    if score > 15500: #Le chiffre de 15500 a régulièrement été augmenté
        # On sauvegarde les listes de couples donnant 15500 min
        good_list.append(sauveliste)
        good_scor.append(score)
        good_indice+=1
    if score > best_scor:
         # On sauvegarde la meilleur liste trouvée
        best_list = sauveliste[0:annee]
        best_scor = score
        print("\n======= Meilleur score ======== tirage n° ",tirage, "sur",annee, "années ======== ")
        print("Score : ",score)
        print("liste = ",best_list[0:annee])

def calcule_score(liste,tirage,annee):
    m=42
    sauveliste = liste
    # print(sauveliste)
    # input()
    while len(liste)<m:
        liste.append((0,0))
    score = st(liste)
    sauvegarde(sauveliste,score,tirage,annee)

def forcealeat(annee,nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee]+=1
        for i in range(annee):
                listealeat.append(((-1)**i*random.randint(1,9),(-1)**i*random.randint(1,9)))
                # le choix de faire un coup négatif un coup positif peut se discuter...
                random.shuffle(listealeat)
        calcule_score(listealeat,tirage[annee],annee) 
    print(30*"##")
    print("fini,",nbtirage, "tirages de",annee, "couples aléatoires")
    print("bonne liste : ",good_indice)
    print("MeilleurScore : ",best_scor)
    print("liste = ",best_list)

def forcealeatgeometrie6(annee,nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee]+=1
        col1 = random.randint(1,6)
        lig1 = random.randint(1,9)
        col2 = random.randint(1,9)
        lig2 = random.randint(1,6)
        listealeat.append((col1,lig1))
        listealeat.append((col1+1,lig1))
        listealeat.append((col1+2,lig1))
        listealeat.append((-1*col2,-1*lig2))
        listealeat.append((-1*col2,-1*(lig2+1)))
        listealeat.append((-1*col2,-1*(lig2+2)))
        random.shuffle(listealeat)
        calcule_score(listealeat,tirage[annee],annee) 
    print(30*"##")
    print("fini,",nbtirage, "tirages de",annee, "couples aléatoires")
    print("bonne liste : ",good_indice)
    print("MeilleurScore : ",best_scor)
    print("liste = ",best_list)



JEUX AVEC LE MOTEUR GRAPHIQUE

A l’aide du moteur graphique, on a pu analyser les figures donnant des
états stables
. C’est à dire qu’à partir d’une configuration donnée, on obtient une configuration qui n’évolue plus dans le temps.

Ainsi, on obtient les résultats suivants.

1er état stable, avant-après :

2ème état stable, avant-après :

Un 3ème, très joli :

Avec ces états, on observe un autre comportement du programme, les bords interagissent entre eux.


TIRAGES ALÉATOIRES AVEC IA

Nos résultats étaient satisfaisants et ils nous permettait d’obtenir un score supérieur à 18 000, mais beaucoup de tirage étaient gâchés car l’algorithme manquait de discernement.

Nous avons alors repris les coloriages et amélioré notre script de tirage. L’heure de l’
IA
avait sonné.
Oui on utilise facilement le mot
IA
alors que ... on a juste réfléchit et que les scripts sont eux toujours aussi stupides.


Ce script a réalisé à lui tout seul plus de 20 000 000 de tirage, déjà parce qu’il était beau, et ensuite parce que nous voulions obtenir une liste significative de tirage ayant un score supérieur à 18 000.

forcealeatIA(6,7000000)
nous au ainsi donné 154 tirages certifiés supérieurs à 18 000.
Code: Select all
def forcealeatIA(annee, nbtirage):
    global best_scor, good_indice
    for j in range(nbtirage):
        listealeat = []
        tirage[annee] += 1
        na = random.randint(1, 9)
        ma = random.randint(1, 9)
        nlist = [max(na - 1, 1), na, min(na + 1, 9)]
        mlist = [max(ma - 1, 1), ma, min(ma + 1, 9)]
        pa = random.randint(1, 9)
        qa = random.randint(1, 9)
        plist = [max(pa - 1, 1), pa, min(pa + 1, 9)]
        qlist = [max(qa - 1, 1), qa, min(qa + 1, 9)]
        for i in range(annee // 2):
            listealeat.append((random.choice(nlist), random.choice(mlist)))
            listealeat.append(((-1) * random.choice(plist), (-1) * random.choice(qlist)))
        random.shuffle(listealeat)
        goodliste(listealeat, tirage[annee], annee)
    print(30 * "##")
    print("fini,", nbtirage, "tirages de", annee, "couples aléatoires")
    print("bonne liste : ", good_indice)
    print("MeilleurScore : ", best_scor)
    print("liste = ", best_list)

Ces tirages ont alors été mélangés aléatoirement, histoire de s’assurer vérifier que un autre ordre ne nous donnerait pas un meilleur score.

La variable
goodliste
contenait à ce moment là une liste de listes, nos 154 listes que nous avons mélangés 100 000 fois procédant ainsi à 15 000 000 nouveaux tirages.
Code: Select all
def improve_liste():
    global goodliste
    listetraiteeok = 0
    for listeatraiter in goodliste:
        listetraiteeok += 1
        annee = len(listeatraiter)
        for i in range(100000):
            listemelange = listeatraiter[0:annee]
            random.shuffle(listemelange)
            calcule_score(listemelange, i, annee)
        if listetraiteeok % 10 == 0:
            print("liste mélangées :", listetraiteeok, "1000 fois")

In fine, nous avons obtenu trois 4 listes ayant un score supérieur à 19 000.
Code: Select all
[(-1, -4), (-2, -5), (8, 1), (-3, -5), (7, 1), (7, 3)]
[(2, 3), (2, 4), (-6, -7), (1, 2), (-6, -9), (-5, -7)]
[(5, 3), (7, 3), (7, 4), (-1, -7), (-3, -7), (-1, -6)]
[(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]

MeilleurScore : 19207.913058803344
liste = [(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]



DERNIÈRE APPROCHE GAGNANTE

La dernière approche
(gagnante)
fut de procéder par force brute sur des listes ayant un bon patrimoine génétique.

Nous avions à notre disposition des nombreuses listes courtes avec des scores supérieur à 18 000 voir 19 000. Et si nous cherchions à les rallonger ?

Certains résultats obtenus par
forcealeatIA(9,1000000)
étaient surprenant. Certaines listes de 9 couples avaient un bon score, mais si on ne prenait que la liste des 6 premiers couples le score était mauvais.

Un script sur mesure fut donc codé.

La variable
goodliste
contenait à ce moment là une unique liste, que l’on voulait compléter.
  • add_liste(goodliste, an, 1)
    quelques secondes, 163 tirages
  • add_liste(goodliste, an, 2)
    quelques minutes, 26 569 tirages
  • add_liste(goodliste, an, 3)
    quelques heures, plus de 4 000 000 de tirages
Nous n’avons pas testé
add_liste(goodliste, an, 4)
par manque de temps.

Par contre, sur 6,8,12 thread le script
add_liste(goodliste, an, 3)
a tourné non stop sur des listes sélectionnées avec amour au moyen des scripts
forcealeatIA(annee, nbtirage)
qui continuait à tourner, dès fois que ...
Code: Select all
def add_liste(listeatraiter, annee, rangsup=1):
    liste = listeatraiter.copy()
    # on essaie avec (0,0)
    liste.append((0, 0))
    listescore = liste.copy()
    calcule_score(listescore, 0, annee + 1)
    if rangsup - 1 > 0:
        add_liste(liste, annee + 1, rangsup - 1)
    liste.pop(len(liste) - 1)
    # on essaie avec (+,+)
    for i in range(1, 10, 1):
        for j in range(1, 10, 1):
            liste.append((i, j))
            listescore = liste.copy()
            calcule_score(listescore, 10 * i + j, annee + 1)
            if rangsup - 1 > 0:
                add_liste(liste, annee + 1, rangsup - 1)
            liste.pop(len(liste) - 1)
    # on essaie avec (-,-)
    for i in range(-9, 0, 1):
        for j in range(-9, 0, 1):
            liste.append((i, j))
            listescore = liste.copy()
            calcule_score(listescore, 10 * i + j, annee + 1)
            if rangsup - 1 > 0:
                add_liste(liste, annee + 1, rangsup - 1)
            liste.pop(len(liste) - 1)

an = len(goodliste)
add_liste(goodliste, an, 2)
print(good_list)



CHRONOLOGIE DES SCORES OBTENUS

  1. 15/10 17:00 : 15016

    Pour l’instant on pédale dans la semoule
    global s,j,w # sjw, je ne sais pas si c’est fait exprès mais...
  2. 15/10 19:34 : 17142

    On n’a toujours aucun graphique ni aucune idée de ce qui se passe mais si ça ressemble fortement à des multiplications matricielles.
  3. 16/10 14:16 : 18157

    Score de la nuit sur 10 000 000 de tirages pas vraiment optimisés.
  4. 23/10 10:30 : 18860

    Objectif 19000 avant la fin de la journée.
  5. 23/10 11:30 : 19117

    Prochain objectif : 19430
    (pour doubler un autre candidat)
    .
  6. 24/10 10:07 : 19675

    Finalement 19430 n’était qu’une formalité.
    Maintenant pour aller jusqu’à 21700 il va falloir trouver une autre méthode, celle-ci est un peu longue, mais comme il faut chauffer un peu la maison je ne suis responsable d’aucun meurtre supplémentaire de pingouin.
  7. 24/10 21:13 : 20180

    500 points de plus ! Et c’est pas fini !
  8. 28/10 22:12 : 20475

    Il me tarde de savoir comment a fait
    Pavel
    parce que j’ai tout donné et que j’ai 7 scripts qui moulinent sur mon PC...
  9. 28/10 22:12 : 20972

    Je ne perds pas espoir de finir 1er, mais stratégiquement je me dis que j’ai peut-être intérêt à envoyer mes scores le dernier jour pour que le 1er ne puisse pas réagir...
    C’est beau de rêver ... 20972 fut notre meilleur score.


CONCLUSIONS

Une estimation basse du nombre de tirages que nous avons réalisé donne 100 000 000 de tirages. Mais comme les scripts tournaient non stop en parallèle, nous pensons qu’on s’approche plus des 200 000 000 de tirages et simulations diverses pas du tout optimales.

Ne maîtrisant pas encore les
exports / imports
CSV
en
Python
nous avons été limités par la nécessité d’arrêter manuellement les scripts, de copier / coller les bons résultats et de relancer les scripts, mais pour le défi de l’année prochaine nous seront prêts.

Félicitation une nouvelle fois à
Pavel
qui a dominé les 3 épreuves mais semble ne pas partir avec les mêmes connaissances de base que le simple visiteur des sites
TI-Planet
et
Planète Casio
.

L’année prochaine, il est probable que l’on donnera le concours
Python
en devoir maison facultatif aux élèves de spé
NSI
de Terminale de notre lycée, histoire de voir s’ils ont fixé des connaissances et s’ils font preuve d’initiative et d’autonomie.

Se classer dans les 10 premiers : 18/20, coefficient 0,42.
Se classer devant le prof : 20/20, coefficient 0,666.
https://nsi.xyz/concours-de-rentree-201 ... -en-python


1er
:

Pavel
omniprésent sur
TI-Planet
et sur
Planète Casio
intervient quant à lui jusqu'à
10
fois
:
  • 3
    fois au nom du peuple
    Atlante
  • puis
    7
    fois au nom du peuple
    Muen
Il explose ainsi le score en l'an
42
avec
21960
points ! :bj:
Mais ce n'est pas tout car
Pavel
nous exhibe également la configuration ultime. A partir de l'an
26
les deux populations font la paix et entrent ainsi en stabilité parfaite. Le score atteint ainsi des sommets avec par exemple pas moins de
191160
points au record de
277
ans, et continue ensuite son chemin vers l'infini et au-delà, une première place largement méritée ! :#tritop#:
Pavel wrote:
Voici quelques explications de ma méthode pour obtenir 21960 points. J'ai commencé à jouer sur ma
TI-83 Premium CE
mais je n'étais pas assez patient pour attendre au moins 15 secondes après chaque tour et j'ai vite abandonné cette idée. Ensuite, j'ai légèrement modifié le script
Numworks
en remplaçant
Kandinsky
par
tkinter
et j'ai continué à jouer sur un
PC
. La version modifiée du script ci-contre se trouve également dans ce dépôt.
Code: Select all
from math import log10,sqrt
from tkinter import *

master = Tk()
master.resizable(0, 0)

canvas = Canvas(master, width=320, height=240)
canvas.pack()

def color(r, g, b):
  return '#%02x%02x%02x' % (r, g, b)

def fill_rect(x, y, w, h, color):
  y += 18
  canvas.create_rectangle(x, y, x + w, y + h, fill=color, outline='')

def draw_string(text, x, y, fg=color(0,0,0), bg=None):
  y += 18
  t = canvas.create_text(x, y, anchor=NW, text=text, fill=fg)
  if bg is not None:
    r = canvas.create_rectangle(canvas.bbox(t), fill=bg, outline='')
    canvas.tag_lower(r, t)

def clear():
  canvas.delete('all')
  canvas.create_rectangle(0, 18, 320, 240, fill=color(255, 255, 255), outline='')
  canvas.create_rectangle(0, 0, 320, 18, fill=color(255, 183, 52), outline='')

def init():
  global atmu,n,j,s,ma,mb,mc,w,fp,fm
  atmu,n,j,s,w,fp,fm=[],9,0,0,5,0,0
  ma,mb,mc=[[0]*n for k in range(n)],[[0]*n for k in range(n)],[[0]*n for k in range(n)]

def dr():
  global s,j,w
  sw=320
  d,h=min(sw//n,221//n),(color(0,0,0),color(255,255,255))
  b=sw-1-n*d
  clear()
  for i in range(0,n*d+1,d):
    fill_rect(b,i,n*d,1,h[0])
    fill_rect(b+i,0,1,n*d,h[0])
  for y in range(0,n):
    for x in range(0,n):
      t=255-(255*abs(ma[y][x])//w)
      fill_rect(b+x*d+1,y*d+1,d-1,d-1,ma[y][x]<0 and color(t,t,255) or ma[y][x]>0 and color(255,t,t) or h[1])
  draw_string(" ATLEMU ",1,1,color(255,255,0),color(127,127,127))
  draw_string("Muen\ndo(-1,c,l)",0,19,color(0,0,255),h[1])
  draw_string("Atlante\ndo(1,c,l)",0,53,color(255,0,0),h[1])
  draw_string("Passer\ndo(0)",0,87,color(255,0,255),h[1])
  draw_string("Recommencer\ninit()",0,121,color(0,0,0),h[1])
  draw_string("An: "+str(j)+"\nScore:\n"+str(s)[:10],0,n*d-49)

def do(*ar):
  global j,gp,gm,fp,fm,s
  j,k,v,(sc,sl)=j+1,ar[0],(len(ar)%2) or ar[len(ar)-1],(len(ar)>=3) and (ar[1],ar[2]) or (0,0)
  k,gp,gm=k and k//abs(k),fp,fm
  for y in range(n):mb[y]=mc[y].copy()
  for y in range(n):
    for x in range(n):
      o,ma[y][x]=ma[y][x],ma[y][x]+w*(ma[y][x]==0 and x==sc and y==sl)*((k>0)-(k<0))+(ma[y][x]<=0 and (x-sc or y-sl or k==0) and mb[y][x]//10==3)*((ma[y][x]==0)*w-ma[y][x]*(not(not(ma[y][x]))))-(ma[y][x]>=0 and (x-sc or y-sl or k==0) and mb[y][x]-10*(mb[y][x]//10)==3)*((ma[y][x]==0)*w+ma[y][x]*(not(not(ma[y][x]))))
      if o and ma[y][x]==o:
        ls=(-1,w>abs(ma[y][x]))
        ma[y][x]=ma[y][x]+(ma[y][x]>0)*ls[mb[y][x]//10==3 or mb[y][x]//10==4]-(ma[y][x]<0)*ls[mb[y][x]-10*(mb[y][x]//10)==3 or mb[y][x]-10*(mb[y][x]//10)==2]
      if ma[y][x]-o:
        fp,fm=fp+(ma[y][x]>0 and not(o))-(o>0 and not(ma[y][x])),fm+(ma[y][x]<0 and not(o))-(o<0 and not(ma[y][x]))
        if not(o) and ma[y][x] or o and not(ma[y][x]):
          for dl in range(-1,2):
            for dc in range(-1,2):
              if dl or dc:mc[y+dl+(dl<0 and y==0)*n-(dl>0 and y==n-1)*n][x+dc+(dc<0 and x==0)*n-(dc>0 and x==n-1)*n]+=(ma[y][x]<0)-(o<0 and 0==ma[y][x])+10*((ma[y][x]>0)-(o>0 and 0==ma[y][x]))
  if max(fp,gp)*max(fm,gm):s=s/(1+abs(k)*log10(sqrt(j)))+fp*fm*min(fp,gp)*min(fm,gm)/max(fp,gp)/max(fm,gm)
  atmu.append((sc*k+k,sl*k+k))
  if v:
    dr()
    print("Bon score ? Envoie la liste\n'atmu' a info@tiplanet.org")
  return s

def st(l,v=True):
  init()
  for p in l:s=do((p[0]>0)-(p[0]<0),abs(p[0])-1,abs(p[1])-1,v)
  dr()
  return s

init()

dr()

if __name__== "__main__":
  master.mainloop()

Je me suis beaucoup amusé avec le mode interactif de ce jeu et en même temps j'ai remarqué les particularités suivantes de ce jeu :
  • il faut trois colonies de la même civilisation pour que les colonies commencent à se multiplier
  • le calcul du score n'est pas sensible au décalage horizontal ou vertical et toute solution peut être transformée en l'un des deux types de solutions suivantes :
    • la toute première colonie est en position
      (0,0)
      et cette colonie est Muenne
    • la toute première colonie est en position
      (0,0)
      et cette colonie est Atlante
Pour maximiser le score, j'ai utilisé l'algorithme de recuit simulé et j'ai réécrit le calcul du score en
C
pour pouvoir calculer le score le plus rapidement possible.

J'ai passé beaucoup de temps à ajuster les paramètres de l'algorithme et j'ai aussi remarqué les points suivants:
  • les solutions où la première colonie est Atlante ont tendance à apporter plus de points
  • les meilleures solutions prennent moins de 12 tours pour réaliser le semis
Enfin, ma méthode a pris la forme suivante:
  • au premier tour, mettre une colonie Atlante à
    (0,0)
  • à chaque itération de recuit simulé, faire les modifications suivantes:
    • changer aléatoirement l'un des 10 prochains tours en plaçant une colonie sur une position libre
    • vérifier les 10 prochains tours un par un en essayant tous les 163 mouvements possibles et garder une combinaison avec le score maximum
  • recommencer plusieurs fois avec différentes séquences de nombres pseudo-aléatoires
Pour être sûr d'avoir de bonnes séquences de nombres pseudo-aléatoires, j'ai pris l'algorithme
WELL512
.
Code: Select all
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

struct STATE
{
  int8_t code[42];
  int8_t board[81 * 42];
  double score;
};

/*
WELL512 algorithm
http://www.iro.umontreal.ca/~panneton/WELLRNG.html
implemented by Chris Lomont
http://lomont.org/papers/2008/Lomont_PRNG_2008.pdf
*/
uint32_t buf[16];
uint32_t pos;
uint32_t wellrng512()
{
  uint32_t a, b, c, d;
  a = buf[pos];
  c = buf[(pos + 13) & 15];
  b = a ^ c ^ (a << 16) ^ (c << 15);
  c = buf[(pos + 9) & 15];
  c ^= (c >> 11);
  a = buf[pos] = b ^ c;
  d = a ^ ((a << 5) & 0xDA442D24UL);
  pos = (pos + 15) & 15;
  a = buf[pos];
  buf[pos] = a ^ b ^ d ^ (a << 2) ^ (b << 18) ^ (c << 28);
  return buf[pos];
}

double score(struct STATE *state)
{
  double s;
  int8_t i, j, k, l, dx, dy, lp, lm, o, x, y, xn, yn;
  int8_t dp, dm, fp, fm, gp, gm, maxp, maxm, minp, minm;
  int8_t ma[81], mp[81], mm[81], np[81], nm[81];

  s = 0.0;
  fp = 0;
  fm = 0;
  memset(ma, 0, 81);
  memset(mp, 0, 81);
  memset(mm, 0, 81);

  for(j = 0; j < 42; ++j)
  {
    i = state->code[j];
    l = abs(i) - 1;
    k = (i > 0) - (i < 0);

    gp = fp;
    gm = fm;

    memcpy(np, mp, 81);
    memcpy(nm, mm, 81);

    memcpy(state->board + j * 81, ma, 81);

    for(i = 0; i < 81; ++i)
    {
      o = ma[i];
      if(i == l && k != 0)
      {
        if(ma[i] == 0) ma[i] = 5 * k;
      }
      else
      {
        ma[i] += (np[i] == 3) * ((ma[i] == 0) * 5 - (ma[i] < 0) * ma[i]) - (nm[i] == 3) * ((ma[i] == 0) * 5 + (ma[i] > 0) * ma[i]);
      }
      if(ma[i] == o && o != 0)
      {
        lp = np[i] == 3 || np[i] == 4 ? abs(ma[i]) < 5 : -1;
        lm = nm[i] == 3 || nm[i] == 2 ? abs(ma[i]) < 5 : -1;
        ma[i] += (ma[i] > 0) * lp - (ma[i] < 0) * lm;
      }
      if(ma[i] != o && (ma[i] == 0 || o == 0))
      {
        dp = (ma[i] > 0) - (o > 0);
        dm = (ma[i] < 0) - (o < 0);
        fp += dp;
        fm += dm;
        x = i % 9;
        y = i / 9;
        for(dx = -1; dx < 2; ++dx)
        {
          for(dy = -1; dy < 2; ++dy)
          {
            if(dx == 0 && dy == 0) continue;
            yn = y + dx;
            yn = yn < 0 ? 8 : yn > 8 ? 0 : yn;
            xn = x + dy;
            xn = xn < 0 ? 8 : xn > 8 ? 0 : xn;
            mp[yn * 9 + xn] += dp;
            mm[yn * 9 + xn] += dm;
          }
        }
      }
    }
    maxp = fp > gp ? fp : gp;
    maxm = fm > gm ? fm : gm;
    minp = fp < gp ? fp : gp;
    minm = fm < gm ? fm : gm;
    if(maxp != 0 && maxm != 0)
    {
      s = s / (1 + abs(k) * log10(sqrt(j + 1))) + 1.0 * fp * fm * minp * minm / maxp / maxm;
    }
  }
  return s;
}

void init(struct STATE *state)
{
  memset(state->code, 0, 42);

  state->code[0] = 1;

  memset(state->board, 0, 81 * 42);

  state->score = score(state);
}

void random_walk(struct STATE *state)
{
  int8_t i, imax, j, l;
  double s, smax;

  for(l = 0; l < 2; ++l)
  {
    while(1)
    {
      i = wellrng512() % 163 - 81;
      j = wellrng512() % 10 + 1;

      if(i == 0 || state->board[j * 81 + abs(i) - 1] == 0)
      {
        state->code[j] = i;
        break;
      }
    }
  }

  for(l = 0; l < 1; ++l)
  {
    for(j = 1; j < 12; ++j)
    {
      imax = 0;
      smax = 0.0;
      for(i = -81; i < 82; ++i)
      {
        state->code[j] = i;
        s = score(state);
        if(smax < s)
        {
          imax = i;
          smax = s;
        }
      }
      state->code[j] = imax;
      state->score = smax;
    }
  }
}

void print(struct STATE *state)
{
  int8_t i, j, k, l;

  printf("%.9f ", state->score);
  for(j = 0; j < 42; ++j)
  {
    i = state->code[j];
    l = abs(i) - 1;
    k = (i > 0) - (i < 0);
    printf("(%d, %d), ", k * (l % 9 + 1), k * (l / 9 + 1));
  }
  printf("\n");
}

int main(int argc, char *argv[])
{
  struct STATE current, next;
  double delta, result, t;
  unsigned seed;
  int8_t i;

  result = 0.0;

  while(1)
  {
    seed = time(NULL);
    srand(seed);
    printf("seed: %d\n", seed);
    pos = 0;
    for(i = 0; i < 16; ++i)
    {
      buf[i] = rand() ^ (rand() << 16) ^ (rand() << 31);
    }

    init(&current);

    t = 1.0;

    while(t > 0.001)
    {
      t *= 0.999;

      next = current;

      random_walk(&next);

      if(result < next.score)
      {
        result = next.score;
        print(&next);
      }

      delta = next.score - current.score;
      if(delta >= 0 || wellrng512() < RAND_MAX * exp(delta / t))
      {
        current = next;
      }
    }
  }

  return EXIT_SUCCESS;
}

Après plusieurs heures, j'ai eu la chance de trouver une séquence de nombres aléatoires permettant à mon code de converger vers 21960 en quelques minutes. Je suis très heureux que cette solution, en même temps, apporte beaucoup de points et crée un monde absolument stable dans lequel les deux civilisations coexisteront pendant des millions d'années.

Enfin, voici un lien vers mon code en
C
également ci-contre.
Code: Select all
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>

struct STATE
{
  int8_t code[42];
  int8_t board[81 * 42];
  double score;
};

/*
WELL512 algorithm
http://www.iro.umontreal.ca/~panneton/WELLRNG.html
implemented by Chris Lomont
http://lomont.org/papers/2008/Lomont_PRNG_2008.pdf
*/
uint32_t buf[16];
uint32_t pos;
uint32_t wellrng512()
{
  uint32_t a, b, c, d;
  a = buf[pos];
  c = buf[(pos + 13) & 15];
  b = a ^ c ^ (a << 16) ^ (c << 15);
  c = buf[(pos + 9) & 15];
  c ^= (c >> 11);
  a = buf[pos] = b ^ c;
  d = a ^ ((a << 5) & 0xDA442D24UL);
  pos = (pos + 15) & 15;
  a = buf[pos];
  buf[pos] = a ^ b ^ d ^ (a << 2) ^ (b << 18) ^ (c << 28);
  return buf[pos];
}

double score(struct STATE *state)
{
  double s;
  int8_t i, j, k, l, dx, dy, lp, lm, o, x, y, xn, yn;
  int8_t dp, dm, fp, fm, gp, gm, maxp, maxm, minp, minm;
  int8_t ma[81], mp[81], mm[81], np[81], nm[81];

  s = 0.0;
  fp = 0;
  fm = 0;
  memset(ma, 0, 81);
  memset(mp, 0, 81);
  memset(mm, 0, 81);

  for(j = 0; j < 42; ++j)
  {
    i = state->code[j];
    l = abs(i) - 1;
    k = (i > 0) - (i < 0);

    gp = fp;
    gm = fm;

    memcpy(np, mp, 81);
    memcpy(nm, mm, 81);

    memcpy(state->board + j * 81, ma, 81);

    for(i = 0; i < 81; ++i)
    {
      o = ma[i];
      if(i == l && k != 0)
      {
        if(ma[i] == 0) ma[i] = 5 * k;
      }
      else
      {
        ma[i] += (np[i] == 3) * ((ma[i] == 0) * 5 - (ma[i] < 0) * ma[i]) - (nm[i] == 3) * ((ma[i] == 0) * 5 + (ma[i] > 0) * ma[i]);
      }
      if(ma[i] == o && o != 0)
      {
        lp = np[i] == 3 || np[i] == 4 ? abs(ma[i]) < 5 : -1;
        lm = nm[i] == 3 || nm[i] == 2 ? abs(ma[i]) < 5 : -1;
        ma[i] += (ma[i] > 0) * lp - (ma[i] < 0) * lm;
      }
      if(ma[i] != o && (ma[i] == 0 || o == 0))
      {
        dp = (ma[i] > 0) - (o > 0);
        dm = (ma[i] < 0) - (o < 0);
        fp += dp;
        fm += dm;
        x = i % 9;
        y = i / 9;
        for(dx = -1; dx < 2; ++dx)
        {
          for(dy = -1; dy < 2; ++dy)
          {
            if(dx == 0 && dy == 0) continue;
            yn = y + dx;
            yn = yn < 0 ? 8 : yn > 8 ? 0 : yn;
            xn = x + dy;
            xn = xn < 0 ? 8 : xn > 8 ? 0 : xn;
            mp[yn * 9 + xn] += dp;
            mm[yn * 9 + xn] += dm;
          }
        }
      }
    }
    maxp = fp > gp ? fp : gp;
    maxm = fm > gm ? fm : gm;
    minp = fp < gp ? fp : gp;
    minm = fm < gm ? fm : gm;
    if(maxp != 0 && maxm != 0)
    {
      s = s / (1 + abs(k) * log10(sqrt(j + 1))) + 1.0 * fp * fm * minp * minm / maxp / maxm;
    }
  }
  return s;
}

void init(struct STATE *state)
{
  memset(state->code, 0, 42);

  state->code[0] = 1;

  memset(state->board, 0, 81 * 42);

  state->score = score(state);
}

void random_walk(struct STATE *state)
{
  int8_t i, imax, j, l;
  double s, smax;

  for(l = 0; l < 2; ++l)
  {
    while(1)
    {
      i = wellrng512() % 163 - 81;
      j = wellrng512() % 10 + 1;

      if(i == 0 || state->board[j * 81 + abs(i) - 1] == 0)
      {
        state->code[j] = i;
        break;
      }
    }
  }

  for(l = 0; l < 1; ++l)
  {
    for(j = 1; j < 12; ++j)
    {
      imax = 0;
      smax = 0.0;
      for(i = -81; i < 82; ++i)
      {
        state->code[j] = i;
        s = score(state);
        if(smax < s)
        {
          imax = i;
          smax = s;
        }
      }
      state->code[j] = imax;
      state->score = smax;
    }
  }
}

void print(struct STATE *state)
{
  int8_t i, j, k, l;

  printf("%.9f ", state->score);
  for(j = 0; j < 42; ++j)
  {
    i = state->code[j];
    l = abs(i) - 1;
    k = (i > 0) - (i < 0);
    printf("(%d, %d), ", k * (l % 9 + 1), k * (l / 9 + 1));
  }
  printf("\n");
}

int main(int argc, char *argv[])
{
  struct STATE current, next;
  double delta, result, t;
  unsigned seed;
  int8_t i;

  seed = 1571773356;
  srand(seed);
  printf("seed: %d\n", seed);
  pos = 0;
  for(i = 0; i < 16; ++i)
  {
    buf[i] = rand() ^ (rand() << 16) ^ (rand() << 31);
  }

  init(&current);

  result = 0.0;

  t = 1.0;

  while(t > 0.001)
  {
    t *= 0.999;

    next = current;

    random_walk(&next);

    if(result < next.score)
    {
      result = next.score;
      print(&next);
    }

    delta = next.score - current.score;
    if(delta >= 0 || wellrng512() < RAND_MAX * exp(delta / t))
    {
      current = next;
    }
  }

  return EXIT_SUCCESS;
}
viewtopic.php?f=49&t=23051&start=130#p247941


Merci beaucoup à tous pour ces participations de haute facture ! :bj:

14
lots
sont prévus pour vous récompenser, et nous allons maintenant pouvoir procéder à leur choix en commentaires. @
Pavel
, à toi l'honneur. ;)



Référence
:
https://www.planet-casio.com/Fr/forums/ ... sic-!.html
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 6.6%
 
Posts: 35601
Images: 9524
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Online

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby critor » 08 Dec 2019, 15:36

L'explication de Afyu a été rajoutée. :)
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 6.6%
 
Posts: 35601
Images: 9524
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby LePetitMage » 08 Dec 2019, 15:38

Je rappelle juste les lots disponibles pour ce défi (cela provient du post initial) :

Les
14
participants ayant réalisé les meilleurs scores distincts au
défi historique
pourront librement choisir et personnaliser leur lot parmi les propositions suivantes :

  • 2 lots
    Hélium
    :
    1
    calculatrice
    Casio Graph 90+E
    + 1
    pack de goodies
    Casio
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Fluor
    :
    1
    solution d'émulation
    Casio
    au choix + 1
    poster
    Casio
    plié
    au choix + 1
    bloc-notes
    Casio EX-word
    avec stylo
    ou
    porte-clés
    Casio
    + 1
    balle anti-stress
    Casio LampFree
    ou
    catalogue
    Casio
    + 1
    sac
    Casio
    au choix + 1
    cahier d'exercices
    Casio
    au choix + 1
    pack de goodies
    Casio
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Néon
    :
    1
    solution d'émulation
    Casio
    au choix + 1
    mémo
    Casio
    + 1
    calepin
    Casio
    ou
    trousse
    Casio
    + 1
    balle anti-stress
    Casio LampFree
    ou
    catalogue
    Casio
    + 1
    sac
    Casio
    au choix + 1
    cahier d'exercices
    Casio
    au choix + 1
    pack de goodies
    Casio
    + 1
    pack de goodies
    TI-Planète-Casio

    Détail des
    solutions d'émulation
    Casio
    au choix :
    • clé USB d'émulation permanente
      fx-92+ Spéciale Collège
      +
      Graph 35+E II
      +
      Graph 90+E
      pour
      Windows
    • licence 3 ans
      fx-CP400 Manager
      pour
      Windows/Mac
    Détail des
    posters
    Casio
    pliés
    au choix :
    • format
      A2
      (42×59,4 cm²)
      : mode examen
      Graph 25/35/90+E
    • format
      55,8×79,6 cm²
      :
      fx-92+ Spéciale Collège

    116171159411605115251167611675116021160011513115971167211601
  • Lot
    Hydrogène
    :
    1
    calculatrice
    HP Prime G2
    + 1
    pack de goodies
    HP
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Phosphore
    :
    1
    application
    HP Prime Pro
    + 1
    poster
    HP
    roulé 59,2×40 cm²
    + 1
    bloc-notes
    HP
    + 1
    pack de goodies
    HP
    + 1
    pack de goodies
    TI-Planète-Casio

    Application
    HP Prime Pro
    au choix pour / / .

    98339832116559817
  • 2 lots
    Chlore
    :
    1
    calculatrice
    NumWorks N0110
    au choix + 1
    pack de goodies
    NumWorks
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Argon
    :
    1
    poster
    NumWorks
    roulé
    au choix ou
    casse-tête
    NumWorks
    + 1
    couvercle
    NumWorks
    + 1
    sticker
    NumWorks
    + 1
    pack de goodies
    NumWorks
    + 1
    pack de goodies
    TI-Planète-Casio

    Détail des
    calculatrices
    NumWorks N0110
    au choix :
    • calculatrice
      NumWorks N0110
      de production
    • calculatrice
      NumWorks N0110
      de présérie
      (rare/historique)
    Détail des
    posters
    NumWorks
    au choix :
    • format
      A0
      (118,9×84,1 cm²)
      :
      NumWorks N0100
    • format
      A2
      (42×59,4 cm²)
      :
      • NumWorks N0100
        +
        Eduscol / Ministère de l'Education Nationale
        rentrée 2017
      • NumWorks N0100
        +
        Eduscol / Ministère de l'Education Nationale
        rentrée 2018
      • NumWorks N0100
        +
        Pims / @qabosse / @antalpilipili
      • NumWorks N0100
        +
        Xavier Andréani / TI-Planet
        dédicacé

    11651116491167411664116529657
  • Lot
    Brome
    :
    1
    calculatrice
    TI-Nspire CX II-T CAS
    au choix ou
    calculatrice
    TI-Nspire CX CAS
    Ndlessable
    au choix + 1
    licence logiciel
    TI-Nspire CAS
    élève
    + 1
    pack de goodies
    TI
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Krypton
    :
    1
    calculatrice
    TI-Nspire CX II-T
    + 1
    licence logiciel
    TI-Nspire
    élève
    + 1
    pack de goodies
    TI
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Iode
    :
    1
    calculatrice
    TI-83 Premium CE Edition Python
    + 1
    cahier
    TI-83 Premium CE
    au choix + 1
    pack de goodies
    TI
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Xénon
    :
    1
    licence logiciel
    TI
    au choix + 1
    cahier
    TI-83 Premium CE
    au choix + 1
    pin's
    TI-Nspire CX
    ou
    pochette CD
    TI-Nspire
    + 1
    décalcomanie
    TI-83 Premium CE
    au choix + 1
    balle anti-stress
    TI
    + 1
    sac
    TI
    au choix + 1
    dessous de verre
    TI
    ou
    lunettes de soleil
    #T3IC
    ou
    scellé de sécurité
    TI
    + 1
    pack de goodies
    TI
    + 1
    pack de goodies
    TI-Planète-Casio
  • Lot
    Radon
    :
    1
    licence logiciel
    TI
    au choix + 1
    cahier
    TI-83 Premium CE
    au choix + 1
    polo
    TI
    ou
    T-shirt
    TI
    au choix + 1
    décalcomanie
    TI-83 Premium CE
    au choix + 1
    balle anti-stress
    TI
    + 1
    sac
    TI
    au choix + 1
    dessous de verre
    TI
    ou
    lunettes de soleil
    #T3IC
    ou
    scellé de sécurité
    TI
    + 1
    pack de goodies
    TI
    + 1
    pack de goodies
    TI-Planète-Casio

    Détail des
    calculatrices
    TI-Nspire CX II-T CAS
    au choix :
    • TI-Nspire CX II-T CAS
      sous blister version B
      (rentrée 2019)
    • TI-Nspire CX II-T CAS
      en boîte de timbre à date
      N-0519AH
      (rentrée 2019 - révision matérielle
      AH
      )
    Détail des
    calculatrices
    TI-Nspire CX CAS
    Ndlessables
    au choix :
    • TI-Nspire CX CAS
      sous blister version A
      (rentrées 2012+ - probablement génération
      CR1
      , révision matérielle
      J-N
      , processeur
      132MHz
      , Boot1
      3.0.0
      , batterie Getac
      1060mAh
      )
    • TI-Nspire CX CAS
      sous blister version C
      (rentrées 2015-2016 - probablement batterie Samsung
      1200mAh
      , hésitation sur le reste)
    • TI-Nspire CX CAS
      en boîte de timbre à date
      P-0916Y
      (rentrée 2016 - génération
      CR6
      , révision matérielle
      Y
      , processeur
      156MHz
      , Boot1
      4.0.1
      , batterie Samsung
      1200mAh
      )
      sous emballage d'expédition
    • TI-Nspire CX CAS
      sous blister version D
      (rentrée 2017 - probablement génération
      CR4+
      , révision matérielle
      W+
      , processeur
      156MHz
      , Boot1
      4.0.1
      , batterie Samsung
      1200mAh
      )
    Détail des
    licences logiciel
    TI
    au choix :
    • TI-SmartView 83 Premium CE
      pour
      Windows/Mac
    • TI-Nspire CAS
      pour
      Windows/Mac
    Détail des
    polo
    TI
    et
    T-shirts
    TI
    au choix :
    • polo noir
      TI-University Program
      taille
      XL
    • T-shirt
      T3IC 2019
      taille
      M
    • T-shirt
      EAT. SLEEP. MATH. REPEAT.
      taille
      XXL
    Aperçus
    cahiers d'activités
    TI-83 Premium CE Python 2nde
    au choix:
1162411623117659845984698479848984398491150611505113251132411613116081153311534878611590115911160711532115361159311592

Détail des packs de goodies communs accompagnants les lots :
  • 1
    stylo
    Casio
    au choix
  • 1
    clé USB
    Casio
    au choix :
    • clé USB
      Casio fx-CP400+E
      -
      4 Go
    • clé USB
      Casio
      petit logo bleu foncé -
      8 Go
    • clé USB
      Casio
      grand logo bleu clair -
      4 Go
11509116201161811619
  • 1
    stylo
    HP
  • 1
    clé USB
    HP 16 Go
96561165411653
11660113019812116661166211663
  • 1
    autocollant
    TI
    au choix
  • 1
    stylo
    TI
    au choix
  • 1
    porte-documents
    TI
    au choix
  • 1
    poster
    TI
    plié
    au choix :
    • format
      ANSI-D
      (55,9×86,4 cm²)
      :
      TI-10
      ,
      TI-30XS MultiView
      ,
      TI-73 Explorer
      ,
      TI-Nspire CAS TouchPad
      , double face
      TI-Nspire CX
      /
      TI-Nspire TouchPad
      , double face
      TI-Nspire CAS TouchPad
      /
      TI-Nspire CX CAS
    • format
      A1
      (59,4×84,1 cm²)
      : mode examen
      TI-83 Premium CE
      &
      TI-82 Advanced
      ,
      TI-89 Titanium
    • format
      55,75×83,5 cm²
      :
      TI-Collège Plus
      ,
      TI-Nspire CX
      ,
      TI-Nspire CX CAS
  • 1
    clé USB
    TI
    au choix :
    • clé USB
      T3 France
      bleue -
      2 Go
    • clé USB petite
      TI-Primaire Plus
      -
      4 Go
    • clé USB grande
      TI-Primaire Plus
      -
      4 Go
    • clé USB
      TI-Innovator Rover
      -
      4 Go
    • clé USB petite
      TI-83 Premium CE
      -
      2 Go
    • clé USB grande
      TI-83 Premium CE
      avec lanière -
      4 Go
    • clé USB grande
      TI-83 Premium CE
      avec chaînette -
      4 Go
    • clé USB
      TI-Nspire CX CAS
      -
      2 Go
    • clé USB
      TI
      rouge -
      1 Mo
      (promotion
      TI-Primaire Plus
      défectueuse)
11535117821158711588115891156411565115661156711568116061153111530
  • 1
    autocollant
    TI-Planet
    au choix
  • 1
    autocollant
    Planète Casio
  • 1
    compte premium
    TI-Planet
1161411615
Je dis que je ne dis rien, à part que mes programmes sont disponibles
ici
. Image

En mettant à profit mes pouvoirs de devin, sachant que j'ai écris ma signature bien avant ta venue, ton pseudo est Anonymous.:whistle:
User avatar
LePetitMagePremium
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 58.1%
 
Posts: 266
Images: 20
Joined: 25 Oct 2018, 17:41
Location: Chez moi
Gender: Male
Calculator(s):
Class: TS
GitHub: LePetitMage

Online

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby critor » 08 Dec 2019, 15:41

Merci. :)
Je suis en train de voir ce qu'il faut y barrer, certains goodies étant épuisés.

Mais après Pavel peut toujours partir là-dessus, ça reste valable pour les calculatrices. Et pour les goodies, au pire je lui dirai si y'a plus.
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 6.6%
 
Posts: 35601
Images: 9524
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby Lephe » 08 Dec 2019, 16:07

Voilà, j'ai été plus malin cette fois, donc j'ai terminé la traduction en une petite heure. Voici l'article sur Planète Casio : https://www.planet-casio.com/Fr/forums/ ... sic-!.html :)
User avatar
LephePartenaire
Niveau 9: IC (Compteur Infatigable)
Niveau 9: IC (Compteur Infatigable)
Level up: 37.7%
 
Posts: 261
Joined: 15 Jun 2018, 19:53
Gender: Male

Online

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby critor » 08 Dec 2019, 16:08

Ah super. Je rajoute ça, merci. :)
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 6.6%
 
Posts: 35601
Images: 9524
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby cent20 » 08 Dec 2019, 16:37

Tu en as profité pour corriger mes fôtes d'orthographe ? Je peux mettre à jour avec tes corrections ? :D
Image
Enseignant de mathématiques et de spécialité NSI ( projets, tutos ...)
:favorite: NumWork, Python : démineur, snake, tétris
User avatar
cent20Généreux
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 14.6%
 
Posts: 382
Images: 28
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):

Online

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby critor » 08 Dec 2019, 16:40

L'orthographe est excellente, de grammaire plutôt. Et je pensais que c'était celles de ton disciple/esclave. :p
Ne me fais pas une confiance aveugle, j'en ai possiblement raté, j'étais pressé. ;)
Image
User avatar
critorAdmin
Niveau 19: CU (Créateur Universel)
Niveau 19: CU (Créateur Universel)
Level up: 6.6%
 
Posts: 35601
Images: 9524
Joined: 25 Oct 2008, 00:00
Location: Montpellier
Gender: Male
Calculator(s):
Class: Lycée
YouTube: critor3000
Twitter: critor2000
Facebook: critor.ti
GitHub: critor

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby cent20 » 08 Dec 2019, 16:47

critor wrote:L'orthographe est excellente, de grammaire plutôt. Et je pensais que c'était celles de ton disciple/esclave. :p
Ne me fais pas une confiance aveugle, j'en ai possiblement raté, j'étais pressé. ;)


On s'est partagé la rédaction ... Donc on est co-responsable des fautes mais tu as raison, je vais le charger et lui demander de comparer les deux versions pour trouver les différences :D

Après sur la programmation en python, après avoir vu son Solveur de Sudoku je sais que l'élève a dépassé le maître.
Bon en fait je le sais depuis longtemps, mais j'avais juste du mal à l'accepter :mmm:

Maintenant concernant le mot "esclave" ... :troll: ... :~o
Last edited by cent20 on 08 Dec 2019, 17:18, edited 1 time in total.
Image
Enseignant de mathématiques et de spécialité NSI ( projets, tutos ...)
:favorite: NumWork, Python : démineur, snake, tétris
User avatar
cent20Généreux
Niveau 12: CP (Calculatrice sur Pattes)
Niveau 12: CP (Calculatrice sur Pattes)
Level up: 14.6%
 
Posts: 382
Images: 28
Joined: 17 May 2012, 09:49
Location: Avignon
Gender: Male
Calculator(s):

Re: Résultat concours rentrée 2019 - défi langage calculatri

Unread postby Golden Man » 08 Dec 2019, 16:56

Je trouve que "esclave" est bien choisi :troll:
L'algorithmique, ça me passionne.
Mon dernier projet
: un API javascript pour https://nsi.xyz
User avatar
Golden ManPremium
Niveau 5: MO (Membre Overclocké)
Niveau 5: MO (Membre Overclocké)
Level up: 43.8%
 
Posts: 11
Joined: 12 Oct 2019, 13:03
Location: Marseille
Gender: Male
Calculator(s):
Class: PeiP 1A

Next

Return to News Divers

Who is online

Users browsing this forum: No registered users and 9 guests

-
Search
-
Featured topics
L'OS 5.5 de la TI-83 Premium CE / 84 Plus CE supprime l'assembleur - la plupart des jeux et certains programme ne fonctionneront plus
Omega, le fork étendant les capacités de ta NumWorks, même en mode examen !
Découvre les nouvelles fonctionnalités en Python de l'OS 5.5 pour la 83PCE/84+C-T Python Edition
Comparaisons des meilleurs prix pour acheter sa calculatrice !
1234
-
Donations / Premium
For more contests, prizes, reviews, helping us pay the server and domains...

Discover the the advantages of a donor account !
JoinRejoignez the donors and/or premium!les donateurs et/ou premium !


Partner and ad
Notre partenaire Jarrety Calculatrices à acheter chez Calcuso
-
Stats.
545 utilisateurs:
>533 invités
>7 membres
>5 robots
Record simultané (sur 6 mois):
6892 utilisateurs (le 07/06/2017)
-
Other interesting websites
Texas Instruments Education
Global | France
 (English / Français)
Banque de programmes TI
ticalc.org
 (English)
La communauté TI-82
tout82.free.fr
 (Français)