#Matthew Russell's Maple code for Chomp that won him second prize (almost tied with first) #at the Experimental Math Class Final Contest, May 6, 2013 ############################################### # Two-dimensional case ############################################### # Chomp(K): # inputs a (possibly partially-eaten) chocolate bar # written as a partition (in nonincreasing order) # outputs the Sprague-Grundy function # associated with the position Chomp:=proc(K) local SS, i, j, K1: option remember: if K=[1] then return 0: fi: SS:={}: for i from 1 to nops(K) do for j from 1 to K[i] do if i<>1 or j<>1 then SS:=SS union {Chomp(ChompRewrite(K,i,j))}: fi: od: od: return mex(SS): end: # ChompRewrite(K,a,b): # inputs a (possibly partially-eaten) chocolate bar # written as a partition (in nonincreasing order) # along with a position (a,b) to chomp at # outputs the new partition, after it is chomped ChompRewrite:=proc(K,a,b) local K1, i: option remember: K1:=K: for i from a to nops(K) do K1[i]:=min(b-1,K1[i]): od: for i from 1 to nops(K) do if K1[i]=0 then return [op(1..i-1,K)]: fi: od: return K1: end: # G(M,N): # inputs positive integers M, N # outputs the list of lists # L[i][j] # with # 1 <= i <= M # 1 <= j <= N # such that L[i][j] is the Sprague-Grundy function # of Chomp of an i x j chocolate bar G:=proc(M,N) local i, j: return [seq([seq(Chomp(ChompBar(i,j)),j=1..N)],i=1..M)]: end: # ChompBar(i,j): # inputs positive integers i, j # outputs the correct format for an i x j chocolate bar ChompBar:=proc(i,j) local k: return [seq(j,k=1..i)]: end: ############################################### # Three-dimensional case ############################################### # Chomp3D(K): # inputs a (possibly partially-eaten) 3D chocolate bar # written as a plane partition # as a list of lists # outputs the Sprague-Grundy function # associated with the position Chomp3D:=proc(K) local SS, i, j, k, K1: option remember: if K=[[1]] then return 0: fi: SS:={}: for i from 1 to nops(K) do for j from 1 to nops(K[i]) do for k from 1 to K[i][j] do if i<>1 or j<>1 or k<>1 then SS:=SS union {Chomp3D(Chomp3DRewrite(K,i,j,k))}: fi: od: od: od: return mex(SS): end: # Chomp3DRewrite(K,a,b,c): # inputs a (possibly partially-eaten) 3D chocolate bar # written as a plane partition # as a list of lists # along with a position (a,b,c) to chomp at # outputs the new partition, after it is chomped Chomp3DRewrite:=proc(K,a,b,c) local K1, i, j, K2: option remember: K1:=K: for i from a to nops(K) do for j from b to nops(K[i]) do K1[i][j]:=min(c-1,K1[i][j]): od: od: K2:=[]: for i from 1 to nops(K) do if CutZeroes(K1[i])<>[] then K2:=[op(K2),CutZeroes(K1[i])]: fi: od: return K2: end: # CutZeroes(L): # inputs a list L (assumed to be in nonincreasing order) # outputs the list with trailing zeroes deleted CutZeroes:=proc(L) local i: option remember: for i from 1 to nops(L) do if L[i]=0 then return [op(1..i-1,L)]: fi: od: return L: end: # GG(M,N,P): # inputs positive integers M, N, P # outputs the list of lists of lists # L[i][j][k] # with # 1 <= i <= M # 1 <= j <= N # 1 <= k <= P # such that L[i][j][k] is the Sprague-Grundy function # of Chomp of an i x j x k 3D chocolate bar GG:=proc(M,N,P) local i, j, k: return [seq([seq([seq(Chomp3D(Chomp3DBar(i,j,k)),k=1..P)],j=1..N)],i=1..M)]: end: # Chomp3DBar(i,j,k): # inputs positive integers i, j, k # outputs the correct format for an i x j x k chocolate bar Chomp3DBar:=proc(i,j,k) local l, m: return [seq([seq(k,m=1..j)],l=1..i)]: end: ############################################### # Prior code ############################################### # mex(S): # inputs a set of non-neg. integers and outputs #the minimum of the set {0,1,2,3,...}\S mex:=proc(S) local i: for i from 0 to nops(S) while i in S do od: i: end: