
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 :- 3participants ont utilisé uneCasio Graph 90+Eou son logiciel d'émulation
- 3participants ont utilisé uneTI-Nspire CXou son logiciel d'émulation
- 4participants ont utilisé entre autres uneTI-83 Premium CE Edition Pythonou son logiciel d'émulation
- 2participants ont utilisé uneHP Primeou son logiciel d'émulation
22ème
:
thecamouflage
Terminale S
à l'aide de sa Casio Graph 90+E
, réalise dès le départ pas moins de 15
interventions divines :- fois en faveur des4Muens
- puis fois en faveur des11Atlantes
15460
42
.Précisons que dans sa simulation les
Atlantes
Muens
64
21970
21ème
:
ggauny@live.fr
HP Prime
, intervient pour sa part 17
fois :- fois pour aider les4Atlantes
- puis fois pour aider les13Muens
16588
42
.Précisons que dans sous cette configuration les
Atlantes
Muens
173
81410

20ème
:
TI-83 Premium CE Edition Python
qu'Azerpogba
TI-Planet
et sur Planète Casio
, use 8
fois de son pouvoir divin sans favoritisme :- fois à l'avantage des4Muens
- fois à l'avantage des4Atlantes
16647
42
.Dans cette réalité alternative ce sont les
Muens
Atlantes
87
34787
19ème
:
TI-Nspire CX
, Ti64CLi++
TI-Planet
que Planète Casio
, fait appel 11
fois à ses capacités divines :- fois pour semer une colonies4Muenne
- puis fois pour semer une colonies7Atlante
16647
42
.Avec un tel semis, les
Atlantes
Muens
86
29051
18ème
:
TI-83 Premium CE Edition Python
est maintenant de retour avec LePetitMage
11
fois mais de façon alternative des affaires humaines :- fois à l'avantage des5Muens
- fois à l'avantage des6Atlantes
16699
42
.Ici encore la cohabitation n'est pas bien durable, les
Atlantes
71
28455
17ème
:
TI-83 Premium CE Edition Python
, grandben49
6
fois :- fois pour créer une colonie3Muenne
- puis fois pour créer une colonie3Atlante
17257
42
.Une vision à plus long terme dans son cas, les
Muens
Atlantes
134
58203

16ème
:
Leno
TI-Planet
que sur Planète Casio
, ne se mêle lui aussi que 6
fois des affaires inférieures :- prenant fois parti pour les3Muens
- prenant fois parti pour les3Atlantes
17922
42
.Une bonne durabilité là encore, les
Muens
144
52750

15ème
:
Astrostellar
6
fois ses talents de créateur :- fois au service de la cause3Muenne
- fois au service de la cause3Atlante
17989
42
.Mais hélas l'équilibre n'est sans lui qu'éphémère, les
Muens
88
35375
14ème
:
Encephalogramme
10
fois sur les 11
premières années :- fois au au nom des3Atlantes
- puis fois au nom des7Muens
18142
42
. 
Une cohabitation de ces populations qui a le mérite de durer
247
Atlantes
Muens
117607

13ème
:
Amiga68000
7
fois sur les 8
premières années :- fois pour le bien des3Atlantes
- fois pour le bien des4Muens
18425
42
. 
Une durabilité toutefois en retrait, les
Atlantes
149
65274

viewtopic.php?f=49&t=23051&start=150#p248013Amiga68000 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):Voilà les 2 fonctions utilisées:
- la taille zone de départ où mettre les habitants
(variables carrex et carrey)- le nombre d’habitants
atmu=run(100,False)
Routine qui à partir d'une composition fait varier chaque position de chaque habitant et prend la meilleure configuration :
- 100 = nombre de tirages de 42 ans
- 0 = pas de limite
- True = sauvegarde de chaque tirage pour faire des statistiques
variercompo()
Et le code global ci-contre(merci.Pavelpour la transpo surPC)
- 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)]
12ème
:
Ne0tuX
TI-Planet
et Planète Casio
, met la main à la pâte 9
fois sur les 13
premières années :- fois pour aider les5Atlantes
- fois pour aider les4Muens
18467
42
. 
Saluons la durée exceptionnelle de cohabitation de ces deux populations, les
Muens
263
130039

viewtopic.php?f=49&t=23051&start=140#p247951Ne0tuX 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 :Pour ce qui est de ma méthode, j'ai pressenti que l'algorithme génétique n'était pas terrible à l'état brut
- 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, maissurjectif(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).(voir la première raison ci-dessus). J'ai donc rapidement implémenté enPythonun 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 dumouvement é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 surTI-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 !
11ème
:
Thomas F.
10
fois sur les 12
premières années :- fois pour aider les4Atlantes
- fois pour aider les6Muens
18835
42
. 
Par contre c'est bien moins solide, les
Atlantes
Muens
86
30546
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
TI-83 Premium CE Edition Python
présent à la fois sur TI-Planet
et sur Planète Casio
modère le monde 11
fois :- fois pour la gloire6Atlantes
- fois pour la gloire des5Muens
42
le récompense alors de 19013

La durabilité est améliorée, avec les
Muens
Atlantes
148
64383

viewtopic.php?f=49&t=23051&start=140#p247946edgar13 wrote:Alors moi aussi j'ai commencé surTI-83 Premium CEmais c’était très long!
Avec laTI-83 Premium CEj'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 enPython. Et là avec un simplebrute forcej'ai fait 19013.
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.
9ème
:
RdB
HP Prime
choisit d'éditer le monde 9
fois sur les 10
premières années :- fois pour augmenter5Atlantes
- fois pour augmenter4Muens
19236
42
! 
Mais les
Atlantes
Muens
116
46842
8ème
:
M4x1m3
10
fois la réalité :- fois en faveur des3Atlantes
- fois en faveur des7Muens
19534
42
! 
Meilleure durabilité puisque les
Atlantes
Muens
193
78423

7ème
:
TI-Nspire CX
qu'Extra44
10
fois :- fois en l'honneur des5Muens
- en l'honneur des5Atlantes
19743
42
! 
Meilleure durabilité puisque les
Atlantes
96
36335
viewtopic.php?f=49&t=23051&p=249019#p249019Extra44 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 fichierstnsintermé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 :Bravo encore aux organisateurs pour ce joli concours, et aux participants !
- 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'éditeurLUAdu logicielTI-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
LUAenC++et j'ai compilé des versions successives enC++, 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, j'ai essayé d'autres algos, d'autres paramètres d'algo génétique sans obtenir de meilleur résultats ;-(i5à uni3;-( )
6ème
:
Sentaro21
TI-Planet
et sur Planète Casio
fait réaliser 9
miracles à sa Casio Graph 90+E
:- en faveur des3Atlantes
- en faveur des6Muens
19907
42
! 
Et c'est du solide, les
Muens
225
108463

viewtopic.php?f=49&t=23051&start=160#p248950sentaro21 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.![]()
In this participate,Casio's traditional languageBasicwas too slow. However, it was very good that it was able to work withC.Basic.
5ème
:
Zocipal
8
fois :- fois pour aider les4Atlantes
- fois pour aider les4Muens
20130
42
! 
C'est un peu plus fragile, les deux populations n'arrivant à cohabiter que jusqu'à l'an
142
Atlantes
62652

4ème
:
Golden Man
12
fois :- fois pour avantager5Atlantes
- fois pour avantager les7Muens
20311
42
! 
Un net mieux en terme de cohabitation, qui dure maintenant jusqu'à l'an
183
Muens
78167

https://nsi.xyz/concours-de-rentree-201 ... -en-pythonGolden Man wrote:Après le passionnant nous nous sommes attaqué au défi historique, proposé par les sites internetTI-PlanetetPlanète Casioet les équipes de bénévoles passionnés qui animent ces communautés.LE CONTEXTEIl 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 enCasio-Basic,TI-Basic, ou enPython. Nous avons bien évidement choisi le langagePythonpour sa souplesse, et la capacité que nous avions à le faire tourner sur unPCsur diversIDE Python.
Dans la suite de l’article, le "nous" fait référence aux participantscent20etGolden Man, car nous avons réalisé les recherches en commun.PREMIERS TESTSTout 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 COUPLESBien évidemment, on lance les fonctionsaleatn(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 uniqueIDE 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 DUMULTI-THREADNous n’arrivons pas à faire tourner nos scripts en
multi threadsurPythonen utilisant les outils adéquates, nous commençons donc par faire dumulti threadmanuel :
- 2
PCs= 2 scripts qui tournent 😄- 3
IDE= 3 scripts qui tournent. 😅- 2
PCsavec 3IDE= 6 scripts 🤣
Et puis surpycharmnous 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 lemulti threadcela fut le début de folles nuits des tirages aléatoiresIl faut bien occuper leRyzen 7 2700et ses 16threads!
La première nuit, les fonctionsaleatn(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 GRAPHIQUEEn 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 choisittKinterpour ce travail et fixé un cahier des charges :Ainsi, il a fallu créer la fenêtre.
- 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.
- 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 fonctionevent()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 aveckandinsky.
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 codeRGB, ortKintern’accepte que des chaines de caractères, donc(cours de, on convertit les valeurs en hexadécimal et on crée un code de la formeNSI)
"#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é queavait 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.PavelANALYSE DES RÉSULTATSA 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 desudokufurent 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 :Pour affiner les résultats, nous avons décidé de sauvegarder les bonnes listes et non plus uniquement les meilleures listes.
- 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.NUITS DE FOLIE : 6 À 12 SCRIPTS QUI TOURNENT EN PARALLÈLEQuelques 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 GRAPHIQUEA 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 IANos 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’IAavait sonné.Oui on utilise facilement le motIAalors 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 variablegoodlistecontenait à 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.913058803344liste = [(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]
DERNIÈRE APPROCHE GAGNANTELa 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 parforcealeatIA(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 variablegoodlistecontenait à ce moment là une unique liste, que l’on voulait compléter.Nous n’avons pas testé
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 tiragesadd_liste(goodliste, an, 4)par manque de temps.
Par contre, sur 6,8,12 thread le scriptadd_liste(goodliste, an, 3)a tourné non stop sur des listes sélectionnées avec amour au moyen des scriptsforcealeatIA(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
15/10 17:00 : 15016
Pour l’instant on pédale dans la semouleglobal s,j,w # sjw
, je ne sais pas si c’est fait exprès mais... 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. 16/10 14:16 : 18157
Score de la nuit sur 10 000 000 de tirages pas vraiment optimisés. 23/10 10:30 : 18860
Objectif 19000 avant la fin de la journée. 23/10 11:30 : 19117
Prochain objectif : 19430(pour doubler un autre candidat). 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. 24/10 21:13 : 20180
500 points de plus ! Et c’est pas fini ! 28/10 22:12 : 20475
Il me tarde de savoir comment a faitparce que j’ai tout donné et que j’ai 7 scripts qui moulinent sur mon PC...Pavel 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 lesexports / importsenCSVPythonnous 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 àqui a dominé les 3 épreuves mais semble ne pas partir avec les mêmes connaissances de base que le simple visiteur des sitesPavelTI-PlanetetPlanète Casio.
L’année prochaine, il est probable que l’on donnera le concoursPythonen devoir maison facultatif aux élèves de spéNSIde 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.
3ème
:
Afyu
10
fois :- fois pour les3Atlantes
- fois pour les7Muens
20453
42
! 
Une longévité de plus exceptionnelle, les
Atlantes
277
Muens
136275

viewtopic.php?f=49&t=23051&p=249030#p249029Afyu 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 desdo(1,c,l)
et desdo(-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 dugetkey()
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 ?).
Partant de ce constat et trouvant que taper desdo(+-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 listescores
qui stocke les meilleurs scores obtenus et une listegagnant
qui stocke les listes correspondantes. On stocke la valeur -1 dansscores
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)
dansgagnant
.
- 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 maliste0
, 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 variablenb_chgt
qui stocke le nombre de changements effectués, au même moment que je crée maliste0
. 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 listegagnant
TOUS les meilleurs scores obtenus et ne garder que le dernier. Pour ça, il faut déclarer la variablegagnant
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.
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é lerandint(0,9)
pour que le choix des colonies à modifier ne soit plus parmi les 10 premières, mais seulement parmi les 6 premièresrandint(0,5)
, etc.Uniquement pour la recherche du meilleur seed de 6 de long, j'ai effectué une recherche exhaustive (enfin, je crois) 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 avecla 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
- Code: Select all
for k in range(c-2,c+2+1):
cc=(k+9-1)%9+1for 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 à :Et pour alterner les civilisations, il suffit de remplacer l'ordre 0,1,2,3,4,5 des indices x donnés dans
- 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)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 rangsrang1
etrang2
) 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.![]()
La ligne avec les fractions permet simplement d'afficher le pourcentage d'avancement de la recherche.
- 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)
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...
Je tiens à remercier toutes les personnes qui ont permis l'organisation de ce concours avec un aussi grand nombre de lots de qualité ! Merci !!
2nd
:
cent20
9
fois :- fois pour doper les3Atlantes
- puis fois pour doper les6Muens
20972
42
! 
Dommage toutefois que cela dure moins, les
Atlantes
102
44277
https://nsi.xyz/concours-de-rentree-201 ... -en-pythoncent20 wrote:Après le passionnant nous nous sommes attaqué au défi historique, proposé par les sites internetTI-PlanetetPlanète Casioet les équipes de bénévoles passionnés qui animent ces communautés.LE CONTEXTEIl 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 enCasio-Basic,TI-Basic, ou enPython. Nous avons bien évidement choisi le langagePythonpour sa souplesse, et la capacité que nous avions à le faire tourner sur unPCsur diversIDE Python.
Dans la suite de l’article, le "nous" fait référence aux participantscent20etGolden Man, car nous avons réalisé les recherches en commun.PREMIERS TESTSTout 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 COUPLESBien évidemment, on lance les fonctionsaleatn(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 uniqueIDE 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 DUMULTI-THREADNous n’arrivons pas à faire tourner nos scripts en
multi threadsurPythonen utilisant les outils adéquates, nous commençons donc par faire dumulti threadmanuel :
- 2
PCs= 2 scripts qui tournent 😄- 3
IDE= 3 scripts qui tournent. 😅- 2
PCsavec 3IDE= 6 scripts 🤣
Et puis surpycharmnous 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 lemulti threadcela fut le début de folles nuits des tirages aléatoiresIl faut bien occuper leRyzen 7 2700et ses 16threads!
La première nuit, les fonctionsaleatn(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 GRAPHIQUEEn 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 choisittKinterpour ce travail et fixé un cahier des charges :Ainsi, il a fallu créer la fenêtre.
- 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.
- 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 fonctionevent()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 aveckandinsky.
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 codeRGB, ortKintern’accepte que des chaines de caractères, donc(cours de, on convertit les valeurs en hexadécimal et on crée un code de la formeNSI)
"#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é queavait 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.PavelANALYSE DES RÉSULTATSA 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 desudokufurent 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 :Pour affiner les résultats, nous avons décidé de sauvegarder les bonnes listes et non plus uniquement les meilleures listes.
- 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.NUITS DE FOLIE : 6 À 12 SCRIPTS QUI TOURNENT EN PARALLÈLEQuelques 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 GRAPHIQUEA 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 IANos 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’IAavait sonné.Oui on utilise facilement le motIAalors 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 variablegoodlistecontenait à 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.913058803344liste = [(5, 5), (4, 5), (4, 3), (-6, -8), (-5, -8), (-4, -8)]
DERNIÈRE APPROCHE GAGNANTELa 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 parforcealeatIA(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 variablegoodlistecontenait à ce moment là une unique liste, que l’on voulait compléter.Nous n’avons pas testé
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 tiragesadd_liste(goodliste, an, 4)par manque de temps.
Par contre, sur 6,8,12 thread le scriptadd_liste(goodliste, an, 3)a tourné non stop sur des listes sélectionnées avec amour au moyen des scriptsforcealeatIA(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
15/10 17:00 : 15016
Pour l’instant on pédale dans la semouleglobal s,j,w # sjw
, je ne sais pas si c’est fait exprès mais... 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. 16/10 14:16 : 18157
Score de la nuit sur 10 000 000 de tirages pas vraiment optimisés. 23/10 10:30 : 18860
Objectif 19000 avant la fin de la journée. 23/10 11:30 : 19117
Prochain objectif : 19430(pour doubler un autre candidat). 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. 24/10 21:13 : 20180
500 points de plus ! Et c’est pas fini ! 28/10 22:12 : 20475
Il me tarde de savoir comment a faitparce que j’ai tout donné et que j’ai 7 scripts qui moulinent sur mon PC...Pavel 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 lesexports / importsenCSVPythonnous 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 àqui a dominé les 3 épreuves mais semble ne pas partir avec les mêmes connaissances de base que le simple visiteur des sitesPavelTI-PlanetetPlanète Casio.
L’année prochaine, il est probable que l’on donnera le concoursPythonen devoir maison facultatif aux élèves de spéNSIde 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.
1er
:
Pavel
TI-Planet
et sur Planète Casio
intervient quant à lui jusqu'à 10
fois :- fois au nom du peuple3Atlante
- puis fois au nom du peuple7Muen
42
avec 21960

Mais ce n'est pas tout car
Pavel
nous exhibe également la configuration ultime. A partir de l'an 26
191160
277

viewtopic.php?f=49&t=23051&start=130#p247941Pavel wrote:Voici quelques explications de ma méthode pour obtenir 21960 points. J'ai commencé à jouer sur maTI-83 Premium CEmais 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 scriptNumworksen remplaçantKandinskypartkinteret j'ai continué à jouer sur unPC. 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 :Pour maximiser le score, j'ai utilisé l'algorithme de recuit simulé et j'ai réécrit le calcul du score en
- 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 AtlanteCpour 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:Enfin, ma méthode a pris la forme suivante:
- 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
Pour être sûr d'avoir de bonnes séquences de nombres pseudo-aléatoires, j'ai pris l'algorithme
- 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
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(¤t);
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 enCé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(¤t);
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;
}
Référence
: