Code
In this application, you have to enter rules in a list, the following way : [0, 1, 4, 3, ...]. The first integer in the array has to be 0 or 4.
In this application, you have to enter rules in a list, the following way : [0, 1, 4, 3, ...]. The first integer in the array has to be 0 or 4.
#!/usr/bin/python
#-*- coding: utf-8 -*-
import numpy as np
import operator
import time
import pandas as panda
def mex(arr):#fonction Mex
arr = np.unique(arr)
for i in range(arr.size):
if arr[i]!=i:
return i
return arr.size
#cut#side#all
def rights(chiffre):#function converting a digit in binary. Named right because of the
return str(bin(chiffre)).replace("b","0")#UNIX right system
def option(rule, Game):# returning all the options for a given moment in the game
gameState=Game[:]
liste = [rights(i) for i in rule]
options = []
i=0
for num in liste:
if num[-3]=='1':
for it in range(len(gameState)):
if gameState[it] > i+1:
tmp = gameState[:]
gameState[it] -= i
bonus = gameState[it]/2 + gameState[it]%2
gameState[it]/=2
gameState.append(bonus)
options.append(gameState[:])
while gameState[it]>1:
gameState[it]-=1
gameState[-1]+=1
options.append(gameState[:])
gameState = tmp
if num[-2]=='1':
for it in range(len(gameState)):
if gameState[it] > i:
gameState[it] -= i
options.append(gameState[:])
gameState[it] += i
if num[-1]=='1':
for it in range(len(gameState)):
if gameState[it]==i:
gameState[it] -= i
options.append(gameState[:])
gameState[it] += i
i+=1
for o in options:
o.sort()
return options
def findG(tab, dico):#function returning the nimber of two heaps, using a xor
if len(tab)==1:
return dico[tab[0]]
tmp = dico[tab[0]] ^ dico[tab[1]]
if len(tab)>2:
for i in range(len(tab)-2):
tmp ^= dico[tab[i+2]]
return tmp
def findGstr(tab, dico):#same function, but for str parameters values.
if len(tab)<=1:
return dico[str([tab[0]])]
tmp = dico[str([tab[0]])] ^ dico[str([tab[1]])]
if len(tab)>2:
for i in range(len(tab)-2):
tmp ^= dico[str([tab[i+2]])]
return tmp
def Grundy(k, rule):#function returning the nimbers for positions between 0 and k
if rule[0] != 4 and rule[0] != 0:
print 'The first rule can only be 0 or 4'
return
t=time.time()
dico={0:0}
if k < 0:
return None
for i in range(k):
dico[i] = mex([findG(tab,dico) for tab in option(rule,[i])])
print "elapsed time in the grundy function : "+ str(time.time() - t)
return dico
def GrundyValeur(tabValeur, rule):#function returning a nimber for a given position
return findG(tabValeur, Grundy(max(tabValeur)+1, rule))
def GrundyComplet(taillePile, rule):#returning all the nimber, for all the possible
temps = time.time()#positions (even redundant like [0, 3, 2] and [3, 2, 0] and
dico = { str([x]) : y for x, y in Grundy(taillePile, rule).iteritems()}#[2, 0, 3])
stack = [[taillePile]]
while stack != []:
if str(stack[-1]) in dico:
stack.pop()
else:
IN = True
tmp = [[x for x in y if x != 0] for y in option(rule, stack[-1])]
for o in tmp:
if str(o) not in dico:
IN = False
break
if IN:
dico[str(stack[-1])] = mex([findGstr(tab,dico) for tab in tmp])
stack.pop()
else:
stack.extend(tmp)
print "elapsed time in GrundyComplet : "+str(time.time() - temps)
return dico
def save(dico):#save dictionnary in a file
marx = max(dico.iteritems(), key=operator.itemgetter(1))[1]
values = [['Val Grundy : '+str(nimber)] for nimber in range(marx)]
for i in range(marx):
values[i].extend(sorted([a for a in dico if dico[a] == i]))
df = panda.DataFrame(values)
df.to_csv("save.csv")
def findPeriod(qtt, rule): #e < n < 2(e + p) + t # check if it's periodic (for a sample)
tabValues = Grundy(qtt,rule).values()
t = rule[-1]
temps = time.time()
tab=[]
possibilite = []
current = []
mini = 0
actual = -1
for decalage in range(1,len(tabValues)):
for pos in (range(len(tabValues))):
if decalage+pos < len(tabValues) and tabValues[pos] == tabValues[pos + decalage]:
tab.append([pos,decalage])
for x in range(len(tab)-1):
if (2 *(tab[x][1]) + t) <= (len(tabValues)-mini) or actual != tab[x][1]:
if tab[x][0] + 1 == tab[x+1][0] and tab[x][1] == tab[x+1][1]:
current.append(tab[x])
else:
if tab[x][1] == tab[x+1][1] and tab[x][0] + 1 != tab[x+1][0]:
current = []
mini = tab[x][0]
actual = tab[x][1]
if tab[x][1] != tab[x+1][1]:
possibilite.extend(current)
debut = 0
taille = 0
valeur = 0
period = [0,0,0]
for p in possibilite:
if valeur == p[1]:
taille+=1
else:
if taille > period[0]:
period = [taille, debut, valeur]
debut = p[0]
valeur = p[1]
taille = 1
print "elapsed time in findPeriod : " + str(time.time() - temps)
if period[0] > (2 * (period[1] + period[2]) + t):
print 'period size : '+str(period[2])
print 'pre-period : '+ str(period[1])
else:
print "The sample doesn't allow us to clearly find a period"
print "The longuest period we found until now : "
print "[pre-period, period]"
print "[",period[1],",",period[2],"]"
print "This period is verified over a length of",period[0]
if __name__ == '__main__':
print "Menu : "
print " 1 - Search for nimbers"
print " 2 - Search a nimber for a given position"
print " 3 - Search periodicity in a nimber list"
choice1 = input("Your choice : ")
val = 0
rule = []
cpt = 2
val = input("First rule (0 or 4) : ")
if val == 4 or val == 0 :
rule.append(val)
else:
exit()
while val < 8 and val >= 0:
val = input("Rule n°"+str(cpt)+" (to stop, input an integer out of 0-7) : ")
if val <8 and val >=0:
rule.append(val)
cpt+=1
if choice1 == 1:
print "Menu 2 : "
print " 1 - Search only for main positions"
print " 2 - Search for all the possible positions (long)"
choice2 = input("Your choice : ")
print "Menu 3 : "
print " 1 - Display results"
print " 2 - Save results"
choice3 = input("Your choice : ")
bound = input("Upper bound : ")
if choice2==1:
resultat = Grundy(bound, rule)
else:
resultat = GrundyComplet(bound, rule)
if choice3 == 1:
print resultat
else:
save(resultat)
if choice1 == 2:
position = []
cpt = 1
val = 0
while val < 10 and val >= 0:
val = input("Position for heap n°"+str(cpt)+
" (to stop, input an integer out of 0-9) : ")
if val <10 and val >=0:
position.append(val)
cpt+=1
print GrundyValeur(position, rule)
if choice1 == 3:
bound = input("Upper bound for the list of values : ")
findPeriod(bound, rule)