Code

#!/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)

Example of rules

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]