###################################################################################################### ##This is ComboProject5.txt, a Maple package to generate and investigate integer sequences counting # #final Tie positions in k by n generalized TicTaoToe for specific (small) k # ####It is the Maple package created by Team 5 in Dr. Z.'s Combinatorics Class at # #Rutgers University, Fall 2020. # # Save this file as `ComboProject5.txt`, to use it # #Type, in a Maple session # #read `ComboProject5.txt`): # #and then to get a list of the functions type # #Help(): # #For Help with any of the functions, type # #Help(FunctionName) # #Team Leader: # #Team members: # ###################################################################################################### print(`This is ComboProject5.txt, a Maple package that is part of Project 5 in Dr. Z.'s Combinatorics Class at Rutgers University`): print(`Its purpose is the generate and study sequences enumerating Final tie positions in a k by n generalized TicTacToe`): print(`in a k by n board, for fixed k. The classical case is k=3 and n=3.`): print(``): print(`Team Leader: tbd `): print(``): print(`Other Team members: tbd `): print(`For a list of all the functions type: Help(); `): print(`For Help with any of the functions, type Help(FunctionName):`): with(combinat): Help:=proc() if nargs=0 then print(`The available procedures are: Alph3, EvenTTT3, GF3tx, IsBad, Findrec, Followers3, OddTTT3, PaperEven3, PaperOdd3, SeqFromRec, TicB, VecToMat `): print(` `): elif nargs=1 and args[1]=Alph3 then print(`Alpha3(): The "alphabet" in a 3 by n Tic-Tac-Toe board in other words the set of pairs`): print(`[v1,v2] where v1 and v2 are {[0,0,1],[0,1,0],[1,0,0],[0,1,1],[1,0,1],[1,1,0]}:`): print(`There are 36 "letters" . Try:`): print(`Alph3(); `): elif nargs=1 and args[1]=EvenTTT3k then print(`EvenTTT3(N): The first N terms of the sequence number of Tic-Tac-Toe positiong on a (2*k+1)x3 board`): print(`that ended in a tie, i.e. the number of (2*k)*3 0-1 (or O-X) matrices with 3*k 1 (X) and 3*k 0's (O)`): print(`without conecutive horizonal,vertical or diagonal triple of 111 and 000.`): print(` Try: `): print(`EvenTTT3(30);`): elif nargs=1 and args[1]=IsBad then print(`IsBad(A,k): Given a 0-1 matrix A (expressed as a list of lists) outputs true if there exist k consecutive`): print(`1's or 0's either horizonally, vertically, or diagonally. Try:`): print(`IsBad([[1,1,0],[0,1,0],[1,0,1]],3);`): elif nargs=1 and args[1]=Findrec then print(`Findrec(f,n,N,MaxC): Given a list f tries to find a linear recurrence equation with`): print(`poly coeffs.`): print(`of maximum DEGREE+ORDER<=MaxC`): print(`e.g. try Findrec([1,1,2,3,5,8,13,21,34,55,89],n,N,2);`): elif nargs=1 and args[1]=Followers3 then print(`Followers3(L): Given a letter L in Alph3(), outputs the set of letters that can follow it legally without causing harm. Try:`): print(`Followers3([[1,0,1],[0,0,1]]);`): elif nargs=1 and args[1]=GF3tx then print(`GF3tx(t,x): The rational function in x and t such that the coefficients of x^m*t^n is the exact number`): print(`of 3xn 0-1 matrices without three consectutive ones (horiz., vertically, and diagonally)`): print(`with n ones altogetger. Try:`): print(`GF3tx(t,x);`): elif nargs=1 and args[1]=OddTTT3 then print(`OddTTT3(N): The first N terms of the sequence number of Tic-Tac-Toe positiong on a (2*k+1)x3 board`): print(`that ended in a tie, i.e. the number of (2*k+1)*3 0-1 (or O-X) matrices with 3*k+2 1 (X) and 3*k+1 0's (O)`): print(`without conecutive horizonal,vertical or diagonal triple of 111 and 000.`): print(` Try: `): print(`OddTTT3(30);`): elif nargs=1 and args[1]=PaperEven3 then print(`PapeEven3(): A paper that enumerates 3 by 2*n Tic-Tao-Board that ended with a tie. Try:`): print(`PaperEven3():`): elif nargs=1 and args[1]=PaperOdd3 then print(`PaperOdd3(): A paper that enumerates 3 by 2*n+1 Tic-Tao-Board that ended with a tie. Try:`): print(`PaperOdd3():`): elif nargs=1 and args[1]=SeqFromRec then print(`SeqFromRec(ope,n,N,Ini,K): Given the first L-1`): print(`terms of the sequence Ini=[f(1), ..., f(L-1)]`): print(`satisfied by the recurrence ope(n,N)f(n)=0`): print(`extends it to the first K values. Try:`): print(`SeqFromRec(N-(n+1),n,N,[1],10);`): elif nargs=1 and args[1]=TicB then print(`TicB(m,n,k): Given pos. integers m,n,k, finds the set of all m by n matrices (given as lists-of-lists)`): print(`with m*n/2 1's (if m*n is even) or (m*n+1)/2 1's (if m*n is odd) that do NOT have a horiz. vertical`): print(`of diagonal k-streak of 1s. Try:`): print(`TicB(3,3,3);`): elif nargs=1 and args[1]=VecToMat then print(`VecToMat(v,m,n): Inputs a vector of length m*n fits it, row-by-row into an m by n matrix given as list of lists. Try`): print(`VecToMat([1,1,0,1],2,2);`); else print(`There is no Help for`): print(args): fi: end: ###Findrec #findrec(f,DEGREE,ORDER,n,N): guesses a recurrence operator annihilating #the sequence f of degree DEGREE and order ORDER #For example, try: findrec([seq(i,i=1..10)],0,2,n,N); findrecVerbose:=proc(f,DEGREE,ORDER,n,N) local ope,var,eq,i,j,n0,kv,var1,eq1,mu,a: if (1+DEGREE)*(1+ORDER)+3+ORDER>nops(f) then ERROR(`Insufficient data for a recurrence of order`,ORDER, `degree`,DEGREE): fi: ope:=0: var:={}: for i from 0 to ORDER do for j from 0 to DEGREE do ope:=ope+a[i,j]*n^j*N^i: var:=var union {a[i,j]}: od: od: eq:={}: for n0 from 1 to (1+DEGREE)*(1+ORDER)+2 do eq1:=0: for i from 0 to ORDER do eq1:=eq1+subs(n=n0,coeff(ope,N,i))*op(n0+i,f): od: eq:= eq union {eq1}: od: var1:=solve(eq,var): kv:={}: for i from 1 to nops(var1) do mu:=op(i,var1): if op(1,mu)=op(2,mu) then kv:= kv union {op(1,mu)}: fi: od: ope:=subs(var1,ope): if ope=0 then RETURN(FAIL): fi: ope:={seq(coeff(expand(ope),kv[i],1),i=1..nops(kv))} minus {0}: if nops(ope)>1 then print(`There is some slack, there are `, nops(ope)): print(ope): RETURN(Yafe(ope[1],N)[2]): elif nops(ope)=1 then RETURN(Yafe(ope[1],N)[2]): else RETURN(FAIL): fi: end: #findrec(f,DEGREE,ORDER,n,N): guesses a recurrence operator annihilating #the sequence f of degree DEGREE and order ORDER #For example, try: findrec([seq(i,i=1..10)],0,2,n,N); findrec:=proc(f,DEGREE,ORDER,n,N) local ope,var,eq,i,j,n0,kv,var1,eq1,mu,a: option remember: if not findrecEx(f,DEGREE,ORDER,ithprime(20)) then RETURN(FAIL): fi: if not findrecEx(f,DEGREE,ORDER,ithprime(40)) then RETURN(FAIL): fi: if not findrecEx(f,DEGREE,ORDER,ithprime(80)) then RETURN(FAIL): fi: if (1+DEGREE)*(1+ORDER)+5+ORDER>nops(f) then ERROR(`Insufficient data for a recurrence of order`,ORDER, `degree`,DEGREE): fi: ope:=0: var:={}: for i from 0 to ORDER do for j from 0 to DEGREE do ope:=ope+a[i,j]*n^j*N^i: var:=var union {a[i,j]}: od: od: eq:={}: for n0 from 1 to (1+DEGREE)*(1+ORDER)+4 do eq1:=0: for i from 0 to ORDER do eq1:=eq1+subs(n=n0,coeff(ope,N,i))*op(n0+i,f): od: eq:= eq union {eq1}: od: var1:=solve(eq,var): kv:={}: for i from 1 to nops(var1) do mu:=op(i,var1): if op(1,mu)=op(2,mu) then kv:= kv union {op(1,mu)}: fi: od: ope:=subs(var1,ope): if ope=0 then RETURN(FAIL): fi: ope:={seq(coeff(expand(ope),kv[i],1),i=1..nops(kv))} minus {0}: if nops(ope)>1 then RETURN(Yafe(ope[1],N)[2]): elif nops(ope)=1 then RETURN(Yafe(ope[1],N)[2]): else RETURN(FAIL): fi: end: Yafe:=proc(ope,N) local i,ope1,coe1,L: if ope=0 then RETURN(1,0): fi: ope1:=expand(ope): L:=degree(ope1,N): coe1:=coeff(ope1,N,L): ope1:=normal(ope1/coe1): ope1:=normal(ope1): ope1:= convert( [seq(factor(coeff(ope1,N,i))*N^i,i=ldegree(ope1,N)..degree(ope1,N))],`+`): factor(coe1),ope1: end: #Findrec(f,n,N,MaxC): Given a list f tries to find a linear recurrence equation with #poly coffs. #of maximum DEGREE+ORDER<=MaxC #e.g. try Findrec([1,1,2,3,5,8,13,21,34,55,89],n,N,2); Findrec:=proc(f,n,N,MaxC) local DEGREE, ORDER,ope,L: for L from 0 to MaxC do for ORDER from 0 to L do DEGREE:=L-ORDER: if (2+DEGREE)*(1+ORDER)+4>=nops(f) then print(`Insufficient data for degree`, DEGREE, `and order `,ORDER): RETURN(FAIL): fi: ope:=findrec([op(1..(2+DEGREE)*(1+ORDER)+4,f)],DEGREE,ORDER,n,N): if ope<>FAIL then if SeqFromRec(ope,n,N,[op(1..degree(ope,N),f)], nops(f))=f then RETURN(ope): fi: fi: od: od: FAIL: end: #SeqFromRec(ope,n,N,Ini,K): Given the first L-1 #terms of the sequence Ini=[f(1), ..., f(L-1)] #satisfied by the recurrence ope(n,N)f(n)=0 #extends it to the first K values. Try: #SeqFromRec(N-(n+1),n,N,[1],10); SeqFromRec:=proc(ope,n,N,Ini,K) local ope1,gu,L,n1,j1: ope1:=Yafe(ope,N)[2]: L:=degree(ope1,N): if nops(Ini)<>L then ERROR(`Ini should be of length`, L): fi: ope1:=expand(subs(n=n-L,ope1)/N^L): gu:=Ini: for n1 from nops(Ini)+1 to K do gu:=[op(gu), -add(gu[nops(gu)+1-j1]*subs(n=n1,coeff(ope1,N,-j1)), j1=1..L)]: od: gu: end: #end Findrec with(linalg): #findrecEx(f,DEGREE,ORDER,m1): Explores whether thre #is a good chance that there is a recurrence of degree DEGREE #and order ORDER, using the prime m1 #For example, try: findrecEx([seq(i,i=1..10)],0,2,n,N,1003); findrecEx:=proc(f,DEGREE,ORDER,m1) local ope,var,eq,i,j,n0,eq1,a,A1, D1,E1,Eq,Var,f1,n,N: option remember: f1:=f mod m1: if (1+DEGREE)*(1+ORDER)+5+ORDER>nops(f) then ERROR(`Insufficient data for a recurrence of order`,ORDER, `degree`,DEGREE): fi: ope:=0: var:={}: for i from 0 to ORDER do for j from 0 to DEGREE do ope:=ope+a[i,j]*n^j*N^i: var:=var union {a[i,j]}: od: od: eq:={}: for n0 from 1 to (1+DEGREE)*(1+ORDER)+4 do eq1:=0: for i from 0 to ORDER do eq1:=eq1+subs(n=n0,coeff(ope,N,i))*op(n0+i,f1) mod m1: od: eq:= eq union {eq1}: od: Eq:= convert(eq,list): Var:= convert(var,list): D1:=nops(Var): E1:=nops(Eq): if E10 then RETURN(false): fi: if E1-D1>=1 then for j from 1 to nops(Var) do A1[D1,j]:=coeff(Eq[D1+1],Var[j]): od: if det(A1) mod m1 <>0 then RETURN(false): fi: fi: if E1-D1>=2 then for j from 1 to nops(Var) do A1[D1,j]:=coeff(Eq[D1+2],Var[j]): od: if det(A1) mod m1 <>0 then RETURN(false): fi: fi: true: end: #GrowthConst(ope,n,N): The growth constant of the operator ope in n and the shift operator N. Try #GrowthConst(N^2-N-1,n,N); GrowthConst:=proc(ope,n,N) local ope1,champ,i,gu,rec: ope1:=lcoeff(numer(ope),n): gu:=[solve(ope1,N)]: champ:=gu[1]: rec:=evalf(abs(gu[1])): for i from 2 to nops(gu) do if evalf(abs(gu[i]))>rec then champ:=gu[i]: rec:=evalf(abs(gu[i])): fi: od: champ: end: ###END CODE taken from Dr. Z.'s Maple package Findrec.txt ####START ENUMERATING #IsBad(A,k): Given a 0-1 matrix A (expressed as a list of lists) outputs true if there exist k consecutive #1's or 0's either horizonally, vertically, or diagonally. Try: #IsBad([[1,1,0],[0,1,0],[1,0,1]],3): IsBad:=proc(A,k) local i, j,r: #Looking for horizontal occurrences of a streak of k 1's for i from 1 to nops(A) do for j from 1 to nops(A[1])-k+1 do if {seq(A[i][j+r],r=0..k-1)}={1} or {seq(A[i][j+r],r=0..k-1)}={0} then RETURN(true): fi: od: od: #Looking for vertical occurrences of a streak of k 1's for i from 1 to nops(A)-k+1 do for j from 1 to nops(A[1]) do if {seq(A[i+r][j],r=0..k-1)}={1} or {seq(A[i+r][j],r=0..k-1)}={0} then RETURN(true): fi: od: od: #Looking for NW-SE diagonal occurrences of a streak of k 1's for i from 1 to nops(A)-k+1 do for j from 1 to nops(A[1])-k+1 do if {seq(A[i+r][j+r],r=0..k-1)}={1} or {seq(A[i+r][j+r],r=0..k-1)}={0} then RETURN(true): fi: od: od: #Looking for NE-SW diagonal occurrences of a streak of k 1's for i from k to nops(A) do for j from 1 to nops(A[1])-k+1 do if {seq(A[i-r][j+r],r=0..k-1)}={1} or {seq(A[i-r][j+r],r=0..k-1)}={0} then RETURN(true): fi: od: od: false: end: #VecToMat(v,m,n): Inputs a vector of length m*n fits it, row-by-row into an m by n matrix given as list of lists VecToMat:=proc(v,m,n) local A,A1,v1,i,j: if nops(v)<>m*n then RETURN(FAIL): fi: A:=[]: v1:=v: for i from 1 to m do A1:=[]: for j from 1 to n do A1:=[op(A1),v1[1]]: v1:=[op(2..nops(v1),v1)]: od: A:=[op(A),A1]: od: A: end: #TicB(m,n,k): Given pos. integers m,n,k, finds the set of all m by n matrices (given as lists-of-lists) #with m*n/2 1's (if m*n is even) or (m*n+1)/2 1's (if m*n is odd) that do NOT have a horiz. vertical #of diagonal k-streak of 1s. Try: #TicB(3,3,3); TicB:=proc(m,n,k) local Vecs, Cands,v,G,g: if type(m*n/2, integer) then Vecs:=permute([1$(m*n/2),0$(m*n/2)]): else Vecs:=permute([1$((m*n+1)/2),0$((m*n-1)/2)]): fi: Cands:={seq(VecToMat(v,m,n) , v in Vecs)}: G:={}: for g in Cands do if not IsBad(g,k) then G:=G union {g}: fi: od: G: end: Kulam:=proc(m,n,k) local Vecs, Cands,v,G,g: if type(m*n/2, integer) then Vecs:=permute([1$(m*n/2),0$(m*n/2)]): else Vecs:=permute([1$((m*n+1)/2),0$((m*n-1)/2)]): fi: {seq(VecToMat(v,m,n) , v in Vecs)}: end: #Alph3(): The "alphabet" in a 3 by n Tic-Tac-Toe board in other words the set of pairs #[v1,v2] where v1 and v2 are {[0,0,1],[0,1,0],[1,0,0],[0,1,1],[1,0,1],[1,1,0]}: #There are 36 "letters" Alph3:=proc() local V,v1,v2: V:={[0,0,1],[0,1,0],[1,0,0],[0,1,1],[1,0,1],[1,1,0]}: {seq(seq([v1,v2],v1 in V),v2 in V)}: end: #Followers3(L): Given a letter L in Alph3(), outputs the set of letters that can follow it legally without causing harm. Try: #Followers3([[1,0,1],[0,0,1]]); Followers3:=proc(L) local V,v,cand,F: V:={[0,0,1],[0,1,0],[1,0,0],[0,1,1],[1,0,1],[1,1,0]}: F:={}: for v in V do cand:=[op(L),v]: if not IsBad(cand,3) then F:=F union {[L[2],v]}: fi: od: F: end: #GF3tx(t,x): The rational function in x and t such that the coefficients of x^m*t^n is the exact number #of 3xn 0-1 matrices without three consectutive ones (horiz., vertically, and diagonally) #with n ones altogetger. Try: #GF3tx(t,x); GF3tx:=proc(t,x) local A,eq,var,a,eq1,X,F,f: A:=Alph3(): eq:={}: var:={}: for a in A do var:=var union {X[a]}: eq1:=X[a]-x^2*t^(a[1][1]+a[1][2]+a[1][3]+a[2][1]+a[2][2]+a[2][3]): F:=Followers3(a): eq1:=eq1 -x*add(X[f]*t^(a[1][1]+a[1][2]+a[1][3]), f in F): eq:=eq union {eq1}: od: var:=solve(eq,var): normal(add(subs(var,X[a]), a in A)): end: #OddTTT3(N): The first N terms of the sequence number of Tic-Tac-Toe positiong on a (2*k+1)x3 board #that ended in a tie, i.e. the number of (2*k+1)*3 0-1 (or O-X) matrices with 3*k+2 1 (X) and 3*k+1 0's (O) #without conecutive horizonal,vertical or diagonal triple of 111 and 000. #Try: #OddTTT3(30); OddTTT3:=proc(N) local f,i,t,x: #This is the weight-enumerator of all k by 3 0-1 matrices with these restrictions according to the weight #x^k*t^NumberOfOnes f:=GF3tx(t,x): #Take the Taylor expansion up to x^(2*N+2) f:=taylor(f,x=0,2*N+3): #Extract the coefficients of x^(2*i+1)*t^(3*i+2) [seq(coeff(coeff(f,x,2*i+1),t,3*i+2),i=1..N)]: end: #EvenTTT3(N): The first N terms of the sequence number of Tic-Tac-Toe positiong on a (2*k)x3 board #that ended in a tie, i.e. the number of (2*k)*3 0-1 (or O-X) matrices with 3*k 1 (X) and 3*k 0's (O) #without conecutive horizonal,vertical or diagonal triple of 111 and 000. #Try: #EvenTTT3(30); EvenTTT3:=proc(N) local f,i,t,x: #This is the weight-enumerator of all k by 3 0-1 matrices with these restrictions according to the weight #x^k*t^NumberOfOnes f:=GF3tx(t,x): #Take the Taylor expansion up to x^(2*N+2) f:=taylor(f,x=0,2*N+3): #Extract the coefficients of x^(2*i)*t^(3*i) [seq(coeff(coeff(f,x,2*i),t,3*i),i=1..N)]: end: ###END ENUMERATING #PaperOdd3(): A paper that enumerates 3 by 2*n+1 Tic-Tao-Board that ended with a tie. Try: #PaperOdd3(): PaperOdd3:=proc() local L,n,N,i,a,ope: print(``): print(` Computing the number of (2*n+1) by 3 TicTaoToe Boards that ended in a tie `): L:=OddTTT3(50): print(`For the sake of the OEIS, the first 50 terms are`): print(``): print(L): print(``): ope:=Findrec(L,n,N,10): if ope=FAIL then RETURN(FAIL): fi: print(`Theorem: Let a(n) be the number of TicTacToe (2*n+1)x3 boards that ended in a tie, in other words the`): print(`the number of 3 by 2*n+1 matrices with 3*n+2 X's, 3*n+1 O's such that you NEVER have 3 consecutive Xs, or Os`): print(`either vertically or horizontally, then the following recurrence hold`): print(``): print(add(coeff(ope,N,i)*a(n+i),i=0..degree(ope,N))=0): print(`subject to the initial conditions`): print(``): print(seq(a(i)=L[i],i=1..degree(ope,N))): print(``): print(`Using this recurrence we can compute many values!. For example, the number of 2001 by 3 such TicTaoBoards is`): print(``): print(SeqFromRec(ope,n,N,[op(1..degree(ope,N),L)],1000)[1000]): print(``): end: #PaperEven3(): A paper that enumerates 3 by 2*n Tic-Tao-Board that ended with a tie. Try: #PaperEven3(): PaperEven3:=proc() local L,n,N,i,a,ope: print(``): print(` Computing the number of 2*n by 3 TicTaoToe Boards that ended in a tie `): L:=EvenTTT3(200): print(`For the sake of the OEIS, the first 50 terms are`): print(``): print(L): print(``): ope:=Findrec(L,n,N,10): if ope=FAIL then RETURN(FAIL): fi: print(`Theorem: Let a(n) be the number of TicTacToe (2*n)x3 boards that ended in a tie, in other words the`): print(`the number of 3 by 2*n matrices with 3*n X's, 3*n O's such that you NEVER have 3 consecutive Xs, or Os`): print(`either vertically or horizontally, then the following recurrence hold`): print(``): print(add(coeff(ope,N,i)*a(n+i),i=0..degree(ope,N))=0): print(`subject to the initial conditions`): print(``): print(seq(a(i)=L[i],i=1..degree(ope,N))): print(``): print(`Using this recurrence we can compute many values!. For example, the number of 2000 by 3 such TicTaoBoards is`): print(``): print(SeqFromRec(ope,n,N,[op(1..degree(ope,N),L)],1000)[1000]): print(``): end: