Other sites

The Star Puzzle

The Star Puzzle is a puzzle presented on The Math Forum. I became aware of this problem by noticing the article and solution posted on Quantitative Decisions article section. It asks the question, “How many triangles, quadrilaterals, and irregular hexagons can we form from a star of David?”

In this post I will solve these questions using R as well as solve the more basic question, “How to we find the geometric placement of each of our nodes so as to graph all of our shapes perfectly?”

First off, we note that the star is constructed of two intersecting equilateral triangles which when connecting each intersection points creates a total of 12 smaller equilateral triangles.

Let us first define the origin as (0,0) and define the length of one of the larger sides as 9a (but for future reference just 9). The a is there to indicate that we can arbitrarily scale the star at any time.

Now we want to find all of the nodes (corner pieces in all of the 12 triangles) on the star. Some values we know already, for instance the x values are all -4.5, 0, or 4.5 because the star is centered at the origin and each side is 9. Also, we know the length of each side of the smaller triangles since 3 smaller triangle lengths spans the larger triangle length thus length of each smaller triangle is 3, giving us the coordinates of our first two nodes (-3,0) and (3,0).

Next we need calculate the height of one of the triangles. Using the Pythagorean Theorem.3^2=1.5^2+b^2b=(3^2-1.5^2)^.5=2.6

###### Now we are ready to try to solve the challenge. Let us first start by defining # a list of connections for each node.

connections list(c(12,2),# for 1c(1,12,13,4,3),# for 2 c(2,4),# for 3c(2,3,5,6,13),# for 4c(4,6),# for 5c(7,8,13,4,5),# for 6c(8,6),# for 7c(9,10,13,6,7),# for 8c(8,10),# for 9c(11,12,13,8,9),# for 10c(10,12),# for 11c(11,1,2,13,10),# for 12c(2,4,6,8,10,12)# for 13)

# In order to count the number of sides we will need to define a vector that # collapses nodes on the same side.collapser rbind(c(1,4),c(2,5),c(3,6),c(4,7),c(5,8),c(5,9),c(6,9),c(7,10),c(8,11),c(9,12),c(10,1),c(11,2),c(12,3),c(12,6),c(2,8),c(10,4))

# In the counting of sides. If there is a single node between

# any of the above sets# we will remove that node. Thus 1,2,4 will become 1,4 which counts as one side.# We only need to run the matching algorithm once because # 1,2,4,5 -> drops 2 and 4 -> 1,5

# Let us create a function to count the number of sides.nsides function(nodelist, collapser){# A list of nodes to keep keeper rep(T,length(nodelist))# Only evaluate sides if list of nodes >2if(length(nodelist)>2)# Cycle through each set of 3 nodesfor(i in1:(length(nodelist)))for(ii in1:nrow(collapser)){if(i+1 < length(nodelist)){if((nodelist[i]==collapser[ii,1]&nodelist[i+2]==collapser[ii,2])|(nodelist[i] ==collapser[ii,2]&nodelist[i+2]==collapser[ii,1])) keeper[i+1]}if(i+1 == length(nodelist))if((nodelist[i]==collapser[ii,1]&nodelist[1]==collapser[ii,2])|(nodelist[i] ==collapser[ii,2]&nodelist[1]==collapser[ii,1])) keeper[i+1]if(i == length(nodelist))if((nodelist[i]==collapser[ii,1]&nodelist[2]==collapser[ii,2])|(nodelist[i] ==collapser[ii,2]&nodelist[2]==collapser[ii,1])) keeper[1]}# Return both the list of condensed nodes and the number of sideslist(node=nodelist[keeper], sides=sum(keeper))}

# We will use a recursive algorithm to search each node and each connection# to each node.

nodesearch function(nodelist, connections, target.sides,

collapser, noisily=F){# Calculate number of side and shortest node list fsides (nodelist[-1], collapser)# Calculate possible connections to the current node cconct [[(rev(nodelist)[1])]]# Calculate available connections to current node given# some nodes have already been used. aconct [!(cconct %in% nodelist[-1])]

# If noisily option is selected then a print screen will occure any# time there is a end of path.if(noisily){print(nodelist)print(paste("sides", fsides[[2]]))}

if(nodelist[1]==rev(nodelist)[1]&fsides[[2]]==target.sides){# Search if the current solution is a duplicate of another dup for(i in ret.ls)if(rmatch(fsides[[1]], i)) dup if(!dup) ret.ls[[length(ret.ls)+1]] <rev(fsides[[1]])}}else{for(i in aconct) nodesearch(c(nodelist,i), connections, target.sides,

collapser,noisily)}}

# Stores the number of polygons starting at node 3 with a specific number # of sides. We know there are no 2 sided polygons.nodecount c(sides=2, matches=0)

# This will return all possible three sided objects # (triangles in this case) which pass through node 3sides 3; ret.ls list()nodesearch(3, connections, sides, collapser)

# Create a counter of number of polygons including point 3(nodecount rbind(nodecount,c(sides,length(ret.ls))))plot.node(1:12,col=gray(1), ntext=F, clear=T)for(i in ret.ls) plot.node(i, ntext=T, clear=F)# 3 exist

# Adding in the lines to the outer hexigonlines(node[c(seq(1,11,2),1),], lwd=2)

connections list(c(12,2,11,3),# for 1c(1,12,13,4,3),# for 2 c(2,4,1,5),# for 3c(2,3,5,6,13),# for 4c(4,6,3,7),# for 5c(7,8,13,4,5),# for 6c(8,6,5,9),# for 7c(9,10,13,6,7),# for 8c(8,10,11,7),# for 9c(11,12,13,8,9),# for 10c(10,12,9,1),# for 11c(11,1,2,13,10),# for 12c(2,4,6,8,10,12)# for 13)