#!/usr/bin/python
#-*- coding: utf-8 -*-
import numpy as np
import operator
import matplotlib.pyplot as plt
import pandas as panda
''' ============ RULES =========== '''
def rules(a):
return [a-1,a/2]
''' =========== CALCULS ========== '''
def mex(arr):
arr = np.unique(arr)
for i in range(arr.size):
if arr[i]!=i:
return i
return arr.size
def losing(k):#function returning all the losing positons from 0 to k
if k <= 0:
return None
i=0
arr = np.array([0])
i=i+1
while i < k:
losing = True
for option in rules(i):
if option in arr:
losing = False
break
if losing:
arr = np.append(arr, np.array([i]))
i=i+1
return arr
def Grundy(k):#function returning all the nimbers from 0 to k
if k <= 0:
return None
i=0
dico = {i:i}
i=i+1
while i < k:
tmp = [dico[int(option)] for option in rules(i)]
dico[i] = mex(tmp)
i=i+1
return sorted(dico.items(), key=operator.itemgetter(0))
def GrundyValue(n):# function returning the nimber of a given position
if n < 0 :
return None
dico = {0:0}# save all the nimbers
if n in dico:
return dico[n]
stack = [n]# utilise une pile pour creer une sorte de recursivité
stack.extend(rules(n))
while n not in dico:
IN = True
if stack[-1] in dico:
stack.pop()
else:
tmp = rules(stack[-1])
for option in tmp:
if option not in dico:
IN = False
break
if IN:
dico[stack[-1]] = mex([dico[option] for option in tmp])
stack.pop()
else:
stack.extend(tmp)
return dico[n]
''' =========== SAUVEGARDE ========== '''
def saveCSV(tab):#Save a csv file from an array.
df = panda.DataFrame(tab)
df.to_csv("save.csv")
if __name__ == '__main__':
print " Menu :"
print " 1 - Search losing positions"
print " 2 - Search nimbers"
print " 3 - Search a nimber for a given position"
choice1 = input("Your choice : ")
if choice1 != 3:
print " Menu 2 :"
print " 1 - Print results"
print " 2 - Save results"
choice2 = input("Your 2e choice : ")
else:
choice2 = 1
retour = None
if choice1 == 1:
choice3 = input("Upper bound : ")
retour = losing(choice3)
elif choice1 == 2:
choice3 = input("Upper bound : ")
retour = Grundy(choice3)
elif choice1 == 3:
choice3 = input("Position to look for : ")
retour = GrundyValue(choice3)
if choice2 == 1:
print retour
elif choice2 == 2:
saveCSV(retour)
Rules allows us to define what you can play for a given position in a game. It takes an integer as an input. This is the size of the heap. And it return a python list. In this list you will find all the allowed move in the current context. We recommend to use list comprehension, because it's faster.
For example, in the code above, the rules allows only to pick one token or to pick the half of the heap.
#!/usr/bin/python
import numpy as np
import operator
def rules(a):
return [a-1,a/2]