#OK to post homework #Austin DeCicco, 2/25/26, Assignment 10 #Summary of procs #CompsMod(n,a,S) - As desired for Q1 #OddParStupid(n) - As desired for Q2 #DistinctParStupid(n) - As desired for Q3 #ContainsEven(pi), FirstEven(pi), SplitPart(pos,pi), HasTwins(pi), TwinFinder(pi), MergeTwins(index,pi) - Supporting procs for Q5 #Distinct2Odd(S), Odd2Distinct(S) - Transformation functions for bijection in Q5 #binvectorspace(n) - Binary Vector Space described in Q6 #Bin2Comps(S), Comps2Bin(S) - Transformation functions for bijection in Q6 #OddComps(n), OneTwos(n) - Sets described in Q7 #OneTwos2OddComps(S), OddComps2OneTwos(S) - Transformation functions for bijection in Q7 #BEGIN REFORMATTED C10 ############################################################################################################################################################ with(combinat): #xnk(n,k): The solution of the recurrence xn(n)=(1+add(xn(i)^2,i=0..n-1))/n: From Austin DeCicco and others xnk:=proc(n,k) option remember: local i: if n=0 then 1; else (1+add(xnk(i,k)^k,i=0..n-1))/n; end if; end proc: #xnkC(n,k): clever version of xn(n) only having to remember what happened yesterday From Austin DeCicco and others xnkC:=proc(n,k) option remember: if n=1 then 2; else (xnkC(n-1,k)^(k-1)+n-1)*xnkC(n-1,k)/n; end if; end proc: #xnkP(n,k,p): For a prime p, a fast way to compute xnk(n,k) mod p for n`), s in S)}; end proc: #Park(n,k): The set of partitions of n into exactly k parts Park:=proc(n,k) option remember: local S, k1, S1, s1: if n SplitPart:=proc(pos,pi): local p: p:=[op(pi[1..pos-1]),(pi[pos])/2,(pi[pos])/2,op(pi[pos+1..nops(pi)])]: sort(p, `>`); end proc: #Boolean for if it has duplicate values, only has to check neighbors because all inputs are sorted by > HasTwins:=proc(pi): local check, i, j: check:=false: for i from 1 to nops(pi)-1 do for j from i+1 to nops(pi) do if pi[i]=pi[j] then check:=true; end if; end do; end do; check; end proc: #Gives index of first duplicate neighbor i.e. TwinFinder([3,1,1])=2, TwinFinder([45,45,45])=1 TwinFinder:=proc(pi): local i, j: for i from 1 to nops(pi)-1 do for j from i+1 to nops(pi) do if pi[i]=pi[j] then return i; end if; end do; end do; end proc: #Merges two duplicate values by addition to form a new listed sorted > of length nops(pi)-1, index from TwinFinder MergeTwins:=proc(index,pi): local p: p:=[op(pi[1..index-1]),(pi[index]+pi[index+1]),op(pi[index+2..nops(pi)])]: sort(p, `>`); end proc: #Now for the bijection functions Distinct2Odd:=proc(S): local s, A: A:={}: for s in S do while ContainsEven(s) do s:=SplitPart(FirstEven(s),s): end do; A:=A union {s}: end do; A; end proc: Odd2Distinct:=proc(S): local s, A: A:={}: for s in S do while HasTwins(s) do s:=MergeTwins(TwinFinder(s),s): end do; A:=A union {s}: end do; A; end proc: #seq(evalb(Distinct2Odd(DistinctParStupid(n))=OddParStupid(n)),n=1..10); #The above verifies that Distinct2Odd is a mapping from DistinctParStupid to OddParStupid using the construction process described above. #seq(evalb(DistinctParStupid(n)=Odd2Distinct(OddParStupid(n))),n=1..10); #The above verifies that Odd2Distinct is a mapping from OddParStupid to DistinctParStupid using the construction process described above. #seq(evalb(Odd2Distinct(Distinct2Odd(DistinctParStupid(n)))=DistinctParStupid(n)),n=1..10); #This shows the two transformation functions are inverses of each other #6. [Optional Challenge, 5 dollars (modified 2/26/26)] # Give a bijective proof that the number of compositions of n equals 2^n-1 by constructing a bijection between the set of compositions of n and 0-1 vectors of length n that start with 1. # You should implement it in Maple, by coding both directions. #I claim you can build the set Comps(n) starting from the set Comps(n-1) using the following process, for each element in Comps(n-1) form two new elements in Comps(n), one by adding one to the last integer in the #list or adding a 1 onto the end to form a new longer list. #Aurora hypthesis trivial for n=1. Suppose the Aurora hypothesis hold's for 1 to n-1, consider n. It is clear the above construction process would generate two new elements for each previous element in Comps(n-1), #therefore since |Comps(n-1)| = 2^(n-2), |Comps(n)| =< 2 * 2^(n-2) = 2^(n-1). We can write equally as desired provided there is no overlap in our construction process, i.e. it's impossible for two inputs to create the same output #or one input to not create two outputs as desired. Trivially it must be the case that there is no overlap as one process only produces lists ending in 1 and the other only produces lists ending in >1, and it's impossible for two #different inputs to create the same output since they would have had to share all values and thus are not different. Similarily there must be no elements of Comps(n) that cannot be achieved through this construction process #as again one process produces all lists in Comps(n) ending in 1 and the other all lists in Comps(n) ending in >1. QED #It can also be observed the number of lists of length 1,2,3.. follow the pattern of pascal's triangle which also has the property that the sum of it's rows is 2^(n-1) #We can use this contruction process defined above to create a mapping that traces through the entire way that element was built starting from the seed of Comps(1) and going all the way to Comps(n). #We will define the history of how this string had to be constructed this way, start with a string of 1, if the first step to make this element was to add one to the last integer, add 1 to the end of the string, #if the first step was to add one to the end, add 0 to the end of the string. [1,1,1,1,1]=[5], [1,0,0,1,0]=[1,1,2,1] #Set of all n length binary vectors that begin with 1 binvectorspace:=proc(n) option remember: local v, i, V: if n=1 then return {[1]}; end if; V:={}: for v in binvectorspace(n-1) do for i from 0 to 1 do V:=V union {[op(v),i]}: end do; end do; V; end proc: Bin2Comps:=proc(S): local s, i, A, a: A:={}: for s in S do a:=[1]: for i from 2 to nops(s) do if s[i]=1 then a:=[op(a[1..nops(a)-1]),(a[nops(a)]+1)]; else a:=[op(a),1]; end if; end do; A:=A union {a}: end do; A; end proc: Comps2Bin:=proc(S): local A, a, s, i, c: A:={}: for s in S do a:=[1]: for i from 1 to nops(s) do c:=s[i]: while c > 1 do a:=[op(a),1]: c:=c-1: end do; if i<>nops(s) then a:=[op(a),0]; end if; end do; A:=A union {a}: end do; A; end proc: #seq(evalb(Comps(n)=Bin2Comps(binvectorspace(n))),n=1..10); #The above verifies that Bin2Comps is a mapping from binvectorspace to Comps using the construction process described above. #seq(evalb(Comps2Bin(Comps(n))=binvectorspace(n)),n=1..10); #The above verifies that Comps2Bin is a mapping from Comps to binvectorspace using the construction process described above. #seq(evalb(Bin2Comps(Comps2Bin(Comps(n)))=Comps(n)),n=1..10); #This shows the two transformation functions are inverses of each other #7. [Optional Challenge, 6 dollars (modified 2/26/26)] # Give a bijective proof that the number of compositions of n into odd parts equals fibonacci(n), by constructing a bijection between the set of compositions of n into odd parts and compositions # into parts from {1,2} that start with 1. You should implement it in Maple, by coding both directions. #As I mentioned in class on 2/26, you could always append 1 to any odd composition of n-1 to form an odd composition of n and you could also add 2 to an element of an odd composition of n-2 and #still be left with an odd element, thus you have the seq |OddComps(n)|=|OddComps(n-1)|+|OddComps(n-2)| which is the fibonacci seq. QED #We can use the same construction process described in 6 but modified so we add 2 to the last integer and the role of 1 was mapped to 2 and the role of 0 mapped to 1 in the binary representation #Generates the subset of comps with only odd parts OddComps:=proc(n): local s, A: A:={}: for s in Comps(n) do if not ContainsEven(s) then A:=A union {s}; end if; end do; A; end proc: #Generates the compositions into parts from {1,2} that start with 1 OneTwos:=proc(n): local s, A: A:={}: for s in CompsG(n,{1,2}) do if s[1]=1 then A:=A union {s}; end if; end do; A; end proc: OneTwos2OddComps:=proc(S): local s, i, A, a: A:={}: for s in S do a:=[1]: for i from 2 to nops(s) do if s[i]=2 then a:=[op(a[1..nops(a)-1]),(a[nops(a)]+2)]; else a:=[op(a),1]; end if; end do; A:=A union {a}: end do; A; end proc: OddComps2OneTwos:=proc(S): local A, a, s, i, c: A:={}: for s in S do a:=[1]: for i from 1 to nops(s) do c:=s[i]: while c > 1 do a:=[op(a),2]: c:=c-2: end do; if i<>nops(s) then a:=[op(a),1]; end if; end do; A:=A union {a}: end do; A; end proc: #seq(evalb(OddComps(n)=OneTwos2OddComps(OneTwos(n))),n=1..10); #The above verifies that OneTwos2OddComps is a mapping from OneTwos to OddComps using the construction process described above. #seq(evalb(OneTwos(n)=OddComps2OneTwos(OddComps(n))),n=1..10); #The above verifies that OddComps2OneTwos is a mapping from OddComps to OneTwos using the construction process described above. #seq(evalb(OddComps(n)=OneTwos2OddComps(OddComps2OneTwos(OddComps(n)))),n=1..10); #This shows the two transformation functions are inverses of each other