# Count count count! if you can

How many pentagons are there in the shape below by filling the triangles as shows on the second graph?

For example if this question was asked for the shape below on the left side, the result would be 9!

• That example is a huge hint! – dcfyj Oct 6 '16 at 17:51
• @dcfyj I think the OP might actually be looking for the solution (doesn't know it). This was originally asked on code golf looking for a coded solution I believe before being put on hold or migrated somewhere. – gtwebb Oct 6 '16 at 18:01
• I don't quite understand the example. So are you filling there pentagons too? What the heck do you think is a pentagon? – Matsmath Oct 6 '16 at 19:58
• @Matsmath Pentagon means "a plane figure with five straight sides and five angles." I dont quite understand what you did not understand, I believe the question is quite clear after given example. – helloworld Oct 6 '16 at 20:10
• Ahh, my bad. So the gray objects are the pentagons. I got confused because of the triangles. Thank you, it is all clear now. – Matsmath Oct 6 '16 at 20:18

there are

138 pentagons.

Before putting the code, I will explain the methodology that I have used to solve this. First of all, I have given all triangles the numbers to show you this solution is correct:

As the methodology I have used some steps:

1- I have found all possible polygons by defining neighbour matrices for each triangles as below:

and put this matrices into the code and find all possible polygons which consist of at least 5 triangles since you cannot create a pentagon with less then 5 triangles. (To be honest it does not matter if you consider the polygons with less than 5 triangles anyway.)

To do this, I have checked all possible combination starting with C(19;5) to C(19,19) and check whether if it is polygon or not by using matrices that I have mentioned above.

2- I have put a coordination system to the triangles to define their position and find the number of sides of the polygon. Since they have three directions, 3D coordination system fits very well to find # of sides:

Here is the coordination system, which consists of x,y,z coordinates and every single triangles has coordinates such as, $T_1={1,5,4}$. The rest is as below:

3- So we have unique coordinates for each triangles and and we have all possible polygons. The only part is to find the # of sides of each polygons:

In order to find the sides, I check every single direction for all x,y,z possibilities and see whether if there is a side.

I will give an example how I have done it:

Here is an example where there are 5 triangles. If you check the coordinates, $T_1={1,5,4}$ and $T_4={2,4,4}$ has the same dimension as on $z=4$ direction and there is no other triangle between them even they are not counted as neighbours. so only one side over there and will be counted as one side. Similarly, $T_1$ and $T_2$.

While counting the sides, if there is neighbouring and they are the only common triangles on that direction, I do not count them as sides, such as $z=3$; On that direction, there is only $T_2$ and $T_3$ exist and since there are neighbours, I do not count them.

Lastly, sometimes there are neighbours and non-neighbour triangles on some directions, such as $x=2$; for that kind of situations, I neglected the neighbours and count all non-neighbours as one side.

As a result, all possible polygons which could be counted as pentagon becomes:

138, you may find the results with numbers in the code below to check.

You may check and run the code as you wish: (dont bother with Turkish comments, they are for my own purposes.)

You may also play with number of side check in the code and see how many quadrilateral, octagon etc.

There are exactly:

111 pentagons

in the figure.

How do I know that? Simple, I created a computer program in Java to find out that:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
* @author Victor Stafusa
*/
public class Penta {

private static class Point {
private final int x, y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

return new Point(x + p2.x, y + p2.y);
}*/

public Point sub(Point p2) {
return new Point(x - p2.x, y - p2.y);
}

/*public int dot(Point p2) {
return x * p2.x + y * p2.y;
}*/

/*public double len() {
return Math.sqrt(x * x + y * y);
}*/

public static boolean line(Point p1, Point p2, Point p3) {
Point pa = p3.sub(p1);
Point pb = p2.sub(p1);
int determinant = pa.x * pb.y - pa.y * pb.x;
return determinant == 0;
}

@Override
public int hashCode() {
return Objects.hash(x, y);
}

@Override
public boolean equals(Object other) {
if (!(other instanceof Point)) return false;
Point u = (Point) other;
return u.x == x && u.y == y;
}

@Override
public String toString() {
return "[" + x + "," + y + "]";
}
}

private static class Poly {
private final List<Point> points;

private Poly(List<Point> points) {
List<Point> copy = new ArrayList<>(points);
out: while (true) {
int s = copy.size();
for (int i = 0; i < s; i++) {
if (Point.line(copy.get(i), copy.get((i + 1) % s), copy.get((i + 2) % s))) {
copy.remove((i + 1) % s);
continue out;
}
}
break;
}
this.points = copy;
}

public static Poly tri1(int x, int y) {
return create(new Point(x, y), new Point(x + 1, y + 1), new Point(x - 1, y + 1));
}

public static Poly tri2(int x, int y) {
return create(new Point(x, y), new Point(x + 1, y - 1), new Point(x - 1, y - 1));
}

public static Poly create(Point... p) {
return create(Arrays.asList(p));
}

public static Poly create(List<Point> p) {
Poly pp = new Poly(p);
if (pp.points.size() < 3) return null;
return pp;
}

public static Poly join(Poly a, Poly b) {
List<Point> d = new ArrayList<>(a.points);
d.retainAll(b.points);
if (d.size() < 2) return null;
Point pa = d.get(0);
Point pb = d.get(d.size() - 1);
int c1 = a.points.indexOf(pa);
int c2 = a.points.indexOf(pb);
int c3 = b.points.indexOf(pa);
int c4 = b.points.indexOf(pb);
List<Point> border1 = new ArrayList<>(10);
List<Point> border2 = new ArrayList<>(10);
List<Point> border3 = new ArrayList<>(10);
List<Point> border4 = new ArrayList<>(10);
for (int i = c1; i != c2; i = (i + 1) % a.points.size()) {
}
for (int i = c1; i != c2; i = (i + a.points.size() - 1) % a.points.size()) {
}
for (int i = c3; i != c4; i = (i + 1) % b.points.size()) {
}
for (int i = c3; i != c4; i = (i + b.points.size() - 1) % b.points.size()) {
}
List<Point> result = new ArrayList<>(10);
List<Point> aa, bb;
if (border1.equals(border3)) {
aa = border2;
bb = border4;
} else if (border2.equals(border3)) {
aa = border1;
bb = border4;
} else if (border1.equals(border4)) {
aa = border2;
bb = border3;
} else if (border2.equals(border4)) {
aa = border1;
bb = border3;
} else {
return null;
}
bb.remove(bb.size() - 1);
bb.remove(0);
Collections.reverse(bb);
return new Poly(result);
}

@Override
public String toString() {
return points.toString();
}
}

public static void main(String[] args) {
Poly[] tris = new Poly[] {
Poly.tri1(0, 0),
Poly.tri2(0, 2),
Poly.tri1(-1, 1),
Poly.tri2(-1, 3),
Poly.tri1(1, 1),
Poly.tri2(1, 3),
Poly.tri1(-2, 2),
Poly.tri2(-2, 4),
Poly.tri1(0, 2),
Poly.tri2(0, 4),
Poly.tri1(2, 2),
Poly.tri2(2, 4),
Poly.tri1(-1, 3),
Poly.tri2(-1, 5),
Poly.tri1(1, 3),
Poly.tri2(1, 5),
Poly.tri1(-2, 4),
Poly.tri1(0, 4),
Poly.tri1(2, 4)
};
int found = 0;
for (int i = 0; i < (1 << tris.length); i++) {
List<Poly> polys = new ArrayList<>();
for (int j = 0; j < tris.length; j++) {
if (((1 << j) & i) != 0) polys.add(tris[j]);
}
back: while (true) {
for (int d = 0; d < polys.size() - 1; d++) {
Poly p1 = polys.get(d);
for (int e = d + 1; e < polys.size(); e++) {
Poly p2 = polys.get(e);
Poly r = Poly.join(p1, p2);
if (r != null) {
polys.remove(p1);
polys.remove(p2);
continue back;
}
}
}
break;
}
if (polys.size() != 1) continue;
Poly single = polys.get(0);
if (single.points.size() == 5) {
System.out.println(single);
found++;
}
}
System.out.println(found);
}
}


I will describe the program avoiding most of its gory details:

• The class Point declares a point as a pair of coordinates x and y. They are also used to represent 2D vectors. There are a method (a.k.a operation) to do vectorial subtraction and decide if three points are collinear (the line method).

• An older version of this program also featured vectorial addition, the dot product, and the length of the vector for determining collinearity in the Point class, but I removed those because I am not using them anymore. I left them commented-out in the code though. Collinearity is now determined by using vector subtraction and a 2x2 matrix determinant, which is far easier and faster to calculate.

• The class Poly represents a polygon. It features a list of points, in the order that they are defined, either clockwise or counter-clockwise, as long as they are properly ordered.

• In Poly's constructor (the private Poly(List<Point> points) thing), I used a while loop to look at each point triplet to see if they are collinear. If a collinear triplet is found, the middle point is deleted from the vertexes list. When no more collinear triplets are found, the polygon is done. This procedure ensures that larger sides are properly built from smaller ones and that I wouldn't overcount vertexes and consider a quadrilateral or a triangle as if it were a pentagon.

• Poly also features the tri1 and tri2 methods. They produces small triangles pointing upwards (for tri1) or pointing downwards (for tri2). They receive the vertex coordinate of the uppermost (for tri1) or lowermost (for tri2) vertexes and calculate the position of the other two vertexes, producing the triangle.

• Poly also features two versions of the create method, which produces a polygon from a list of vertexes. If the resulting polygon would end having less than 3 vertexes, it is discarded. This ensures that degenerate polygons are not generated.

• The join method is the hardest one in Poly. It produces a new polygon from the union of two smaller polygons:

• To work with that, first I get the set of shared vertexes.

• If there are less than two shared vertexes, then there is no result polygon (either they don't touch with zero shared vertexes or they touch only in a single point with one shared vertex). So, I discard those (if (d.size() < 2) return null;).

• Knowing that the obtained set of vertexes is properly ordered from the sides of one of the polygons, lets call its endpoints as pa and pb. Then, walking from vertex to vertex on both of the polygons and on both directions (clockwise and counter-clockwise) should produce 4 vertex paths. If the polygons are touching in more than a vertex (but not overlapping), then there should be a vertex path from one of the polygons that is the same as a vertex path from another polygon. If there aren't then they are either overlapping or featuring a hole when joined.

• After knowing what are the two paths that touch, I produce a vertex cycle from the other two paths. I just need to remove the end points of the second path (to avoid repeating vertexes) and reverse its order.

• In the main method, I produce an array (tris) of the 19 small triangles by using the tri1 and tri2 methods.

• Having the 19 triangles, there are $2^{19}$ ways of selecting them, which I brute-force:

• For every iteration, I create a list of polygons containing those triangles and try to join two of them by brute-forcing each possible pair. When a pair is found, I remove them from the list and add the joined polygon there. The pair brute-force is then started over again until no more polygons could be joined.

• After no more joinable pairs are found if there is only a single polygon left on the list and it is a pentagon, then the selected set of triangles forms one of our pentagons.

• For each pentagon found, I print the five vertexes coordinates and increment a counter, showing the counter final value in the very end of the program.

The full output is in the block below.

I couldn't find a way for convincing SE's markdown to spoiler-protect the output
without also destroying the formatting, so I added a bunch of blank lines
and this note before the actual output.

Scroll down to see the actual output.

[[0,2], [-1,3], [-2,2], [0,0], [2,2]]
[[0,2], [-2,2], [0,0], [2,2], [1,3]]
[[0,2], [2,2], [0,0], [-3,3], [-1,3]]
[[-2,4], [-3,3], [0,0], [2,2], [0,2]]
[[1,3], [-1,3], [-2,2], [0,0], [2,2]]
[[0,2], [1,1], [-1,1], [-3,3], [1,3]]
[[0,2], [2,2], [1,3], [-3,3], [-1,1]]
[[1,3], [-3,3], [-1,1], [1,1], [2,2]]
[[-1,3], [-2,4], [-3,3], [-1,1], [1,3]]
[[0,2], [-1,1], [-2,2], [0,4], [2,2]]
[[0,2], [1,1], [2,2], [0,4], [-2,2]]
[[0,4], [-2,2], [-1,1], [1,1], [2,2]]
[[-1,3], [-3,3], [-1,1], [1,3], [0,4]]
[[-1,3], [-3,3], [-2,2], [2,2], [0,4]]
[[0,0], [2,2], [0,4], [-1,3], [-3,3]]
[[0,2], [-2,2], [0,0], [3,3], [1,3]]
[[0,2], [-1,1], [1,1], [3,3], [-1,3]]
[[0,2], [-2,2], [-1,3], [3,3], [1,1]]
[[3,3], [1,1], [-1,1], [-2,2], [-1,3]]
[[-3,3], [-1,1], [0,2], [2,2], [3,3]]
[[0,2], [-2,2], [-3,3], [3,3], [1,1]]
[[0,0], [3,3], [-1,3], [-2,4], [-3,3]]
[[1,3], [3,3], [2,2], [-2,2], [0,4]]
[[1,3], [0,4], [-1,3], [1,1], [3,3]]
[[0,0], [-2,2], [0,4], [1,3], [3,3]]
[[3,3], [2,4], [0,2], [-2,2], [0,0]]
[[1,3], [-1,3], [1,1], [3,3], [2,4]]
[[0,0], [-3,3], [1,3], [2,4], [3,3]]
[[2,2], [-2,2], [-1,3], [-2,4], [0,4]]
[[0,4], [-2,4], [-3,3], [-1,1], [1,3]]
[[0,4], [2,2], [-2,2], [-3,3], [-2,4]]
[[0,4], [-2,4], [-3,3], [0,0], [2,2]]
[[1,3], [3,3], [1,1], [-2,4], [0,4]]
[[-1,3], [-2,2], [-3,3], [-1,5], [1,3]]
[[2,2], [-2,2], [-1,3], [-2,4], [-1,5]]
[[-1,3], [0,2], [1,3], [-1,5], [-3,3]]
[[2,2], [0,2], [-1,3], [-3,3], [-1,5]]
[[-1,5], [-3,3], [-1,3], [1,1], [2,2]]
[[-1,5], [-3,3], [-2,2], [0,2], [1,3]]
[[-1,1], [0,2], [2,2], [-1,5], [-3,3]]
[[1,1], [2,2], [-1,5], [-3,3], [-1,1]]
[[-1,5], [-2,4], [1,1], [3,3], [1,3]]
[[-3,3], [-1,5], [1,3], [3,3], [0,0]]
[[1,3], [2,2], [-2,2], [0,4], [2,4]]
[[-1,3], [-3,3], [-1,1], [2,4], [0,4]]
[[2,4], [3,3], [2,2], [-2,2], [0,4]]
[[2,4], [0,4], [-1,3], [1,1], [3,3]]
[[0,0], [-2,2], [0,4], [2,4], [3,3]]
[[-1,3], [-2,2], [0,2], [2,4], [-2,4]]
[[1,3], [2,2], [0,2], [-2,4], [2,4]]
[[-1,3], [-3,3], [-2,4], [2,4], [0,2]]
[[2,4], [0,2], [-2,2], [-3,3], [-2,4]]
[[1,3], [3,3], [2,4], [-2,4], [0,2]]
[[2,4], [-2,4], [0,2], [2,2], [3,3]]
[[-2,4], [-3,3], [0,0], [3,3], [2,4]]
[[0,4], [2,4], [1,3], [-3,3], [-1,5]]
[[0,4], [-1,5], [-2,4], [0,2], [2,4]]
[[-1,1], [-3,3], [-1,5], [0,4], [2,4]]
[[3,3], [2,4], [0,4], [-1,5], [-3,3]]
[[1,3], [2,2], [-2,2], [1,5], [2,4]]
[[2,4], [1,5], [-1,3], [-3,3], [-1,1]]
[[1,3], [0,2], [-1,3], [1,5], [3,3]]
[[1,5], [3,3], [1,3], [-1,1], [-2,2]]
[[1,3], [2,2], [3,3], [1,5], [-1,3]]
[[1,5], [-1,3], [0,2], [2,2], [3,3]]
[[-2,2], [0,2], [1,1], [3,3], [1,5]]
[[1,1], [3,3], [1,5], [-2,2], [-1,1]]
[[3,3], [1,5], [-1,3], [-3,3], [0,0]]
[[0,4], [-2,4], [0,2], [2,4], [1,5]]
[[0,4], [-2,4], [-1,3], [3,3], [1,5]]
[[1,1], [3,3], [1,5], [0,4], [-2,4]]
[[1,3], [-3,3], [-2,4], [-3,5], [-1,5]]
[[-1,5], [-3,5], [-1,3], [-2,2], [2,2]]
[[-1,5], [-3,5], [1,1], [3,3], [1,3]]
[[0,4], [2,4], [0,2], [-3,5], [-1,5]]
[[0,4], [1,3], [-3,3], [-1,5], [1,5]]
[[3,3], [-1,3], [0,4], [-1,5], [1,5]]
[[1,5], [2,4], [1,3], [-3,3], [-1,5]]
[[1,5], [-1,5], [-2,4], [0,2], [2,4]]
[[-1,1], [-3,3], [-1,5], [1,5], [2,4]]
[[1,5], [3,3], [-1,3], [-2,4], [-1,5]]
[[1,5], [-1,5], [-2,4], [1,1], [3,3]]
[[-3,3], [-1,5], [1,5], [3,3], [0,0]]
[[-2,4], [-3,3], [-1,3], [1,5], [-3,5]]
[[0,4], [1,3], [-1,3], [-3,5], [1,5]]
[[0,4], [1,5], [-3,5], [0,2], [2,2]]
[[0,4], [2,4], [1,5], [-3,5], [-1,3]]
[[1,5], [-3,5], [-1,3], [1,3], [2,4]]
[[-2,4], [-3,3], [3,3], [1,5], [-3,5]]
[[0,2], [1,3], [3,3], [1,5], [-3,5]]
[[2,2], [3,3], [1,5], [-3,5], [0,2]]
[[1,5], [3,5], [1,3], [2,2], [-2,2]]
[[1,5], [3,5], [-1,1], [-3,3], [-1,3]]
[[2,4], [3,3], [-1,3], [1,5], [3,5]]
[[0,4], [-2,4], [0,2], [3,5], [1,5]]
[[0,4], [-1,3], [1,3], [3,5], [-1,5]]
[[3,5], [-1,5], [0,4], [-2,2], [0,2]]
[[2,4], [3,3], [1,3], [-1,5], [3,5]]
[[0,4], [-2,4], [-1,5], [3,5], [1,3]]
[[3,5], [1,3], [-1,3], [-2,4], [-1,5]]
[[-3,3], [-1,3], [0,2], [3,5], [-1,5]]
[[0,2], [3,5], [-1,5], [-3,3], [-2,2]]
[[-3,3], [3,3], [2,4], [3,5], [-1,5]]
[[-3,5], [-1,3], [0,4], [2,4], [3,5]]
[[0,4], [-2,4], [-3,5], [3,5], [1,3]]
[[-2,4], [-3,3], [1,3], [3,5], [-3,5]]
[[0,2], [-2,2], [-1,3], [-3,5], [3,5]]
[[0,2], [2,2], [1,3], [3,5], [-3,5]]
[[3,5], [-1,1], [-3,3], [-1,3], [-3,5]]
[[3,5], [1,3], [3,3], [1,1], [-3,5]]
[[-1,3], [3,3], [2,4], [3,5], [-3,5]]
111


Note: It is easy to modify this program to count pentagons in different given figures by poking with the tris array (don't need to all be triangles, any non-overlapping non-self-intersecting polygons would do). Also, to count something other than pentagons, it should suffice to poke around the if (single.points.size() == 5). However, this thing grows exponentially in execution time as more polygons are added to the given figure, so it would become intractable quickly.

• the actual answer is more than this. You did something wrong with your program :) – helloworld Oct 23 '16 at 7:23