Heyawake Part 2: Penalty Theory

by greenturtle3141, Dec 31, 2021, 9:24 AM

Reading Difficulty: 2-3/5
Prerequisites: Some graph theory would be nice. Read the previous post here if you do not know the rules of Heyawake.

Last time, we left off looking at this very challenging Heyawake puzzle:

https://i.imgur.com/zUVszqt.png

https://puzz.link/p?heyawake/10/10/00000112244000000000003s00003s000000-1f2

I think it's safe to say that this is basically impossible to solve using basic logic alone, without a ton of guessing and/or trial and error. In this post, I will discuss a mathematical methodology for solving puzzles like the above that fundamentally changes the feel of this puzzle genre.

Credit: Heyawake Penalty Theory was originally discovered by "まり餡" (@agnomy on Twitter). The methodology was then generalized and propogated by Ivan Koswara.

If you don't care about the math and just want the method, scroll down to the section "Summary of the Penalty Method".


The Math

The key to these puzzles is that there are so many black squares that the number of ways to fit them all is extremely small (hopefully just one way, otherwise the puzzle has no unique solution, which is considered bad). This leads to the following natural questions:
  • What is the maximum number of black squares you can fit in a region, such that no two are adjacent and the white squares are connected? (We do not consider the essential rule and/or the interaction between multiple regions/rooms, it's hard to reason about them mathematically.)
  • By examining the equality case in the maximum bound obtained, what restrictions does this imply on the configuration of black squares, if the number of black squares were indeed maximal?

The grand scheme will be to use the conditions to obtain three different bounds on some variables that relate to the total number of black squares. Figuring out what those variables should be is motivated by looking at...

The Connectedness Condition

The key to thinking about this condition mathematically is to draw a graph whose vertices are the white squares, such that there is an edge exactly when two vertices are orthogonally adjacent.

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)));
    }
}

void shade(pair bl, real sqSide){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=gray(0.1));
}

unitsize(1cm);
int[][] board = {{0,0,0,0},
                 {0,1,0,1},
                 {1,0,0,0},
                 {0,0,0,0}};

// Draw Grids

real hgap = 2;

drawGrid((0,0), 4, 4, 1);
drawGrid((hgap+4,0), 4, 4, 1);

// Left Shading

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 1){
        	shade((j,3-i),1);
        }
	}
}

// Right Graph

for(int i1=0; i1 < 4; ++i1){
for(int j1=0; j1 < 4; ++j1){
    for(int i2=0; i2 < 4; ++i2){
	for(int j2=0; j2 < 4; ++j2){
    	if( (i1==i2 && abs(j1-j2)==1) || (j1==j2 && abs(i1-i2)==1) ){
        	if(board[i1][j1]==0 && board[i2][j2]==0){
            	draw(shift(4+hgap) * ((j1+.5,3-i1+.5)--(j2+.5,3-i2+.5)),p=linewidth(1.3)+rgb(.6,0,.4));
            }
        }
	}
	}
}
}

real r = 0.1;

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 0){
        	filldraw(circle(shift(4+hgap)*(j+.5,3-i+.5),r), rgb(.6,0,.4));
        }
	}
}

[/asy]

As you can see, the connectedness of the white squares is equivalent to the connectedness of the graph. That is, the graph is in one piece. Let's call this graph $G$.

Adding in a black square is identical to deleting a vertex (and all of its edges) from $G$.

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)));
    }
}

void shade(pair bl, real sqSide){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=gray(0.1));
}

unitsize(1cm);
int[][] board = {{0,0,0,0},
                 {0,1,0,1},
                 {1,0,1,0},
                 {0,0,0,0}};

// Draw Grids

real hgap = 2;

drawGrid((0,0), 4, 4, 1);
drawGrid((hgap+4,0), 4, 4, 1);

// Left Shading

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 1){
        	shade((j,3-i),1);
        }
	}
}

// Right Graph

for(int i1=0; i1 < 4; ++i1){
for(int j1=0; j1 < 4; ++j1){
    for(int i2=0; i2 < 4; ++i2){
	for(int j2=0; j2 < 4; ++j2){
    	if( (i1==i2 && abs(j1-j2)==1) || (j1==j2 && abs(i1-i2)==1) ){
        	if(board[i1][j1]==0 && board[i2][j2]==0){
            	draw(shift(4+hgap) * ((j1+.5,3-i1+.5)--(j2+.5,3-i2+.5)),p=linewidth(1.3)+rgb(.6,0,.4));
            }
        }
	}
	}
}
}

real r = 0.1;

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 0){
        	filldraw(circle(shift(4+hgap)*(j+.5,3-i+.5),r), rgb(.6,0,.4));
        }
	}
}

[/asy]

Now it's disconnected. In theory, adding too many black squares (deleting too many vertices) would have to eventually disconnect the graph. We can capitalize on this intuition via the following theorem:

Theorem: Let $G$ be a graph with $v$ vertices and $e$ edges. If $G$ is connected then we must have $e \geq v-1$.

Proof

To use this, we first compute $e$, the number of edges. Suppose that the board is $m \times n$. If there are no black squares, then $G$ is an $m \times n$ square lattice. So, an easy argument will give the starting number of edges as $(m-1)n + m(n-1) = 2mn - m - n$.

Now let's start adding in black squares. Shading a square black removes a vertex and its edges. How many edges? Well, that depends. Is it a corner square? A square on the edge? Or, is the square in the middle/center?

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)));
    }
}

void shade(pair bl, real sqSide,pen c){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=c);
}

unitsize(1cm);
int[][] board = {{1,2,2,2,1},
                 {2,3,3,3,2},
                 {2,3,3,3,2},
                 {2,3,3,3,2},
                 {1,2,2,2,1}};

pen c1 = rgb(1,0,0);
pen c2 = rgb(.7,0,.3);
pen c3 = rgb(.4,0,.6);
pen[] colors = {c1,c2,c3};
for(int i=0;i<5;++i){
	for(int j=0;j<5;++j){
    	shade((i,j),1,colors[board[i][j]-1]);
    }
}

drawGrid((0,0), 5, 5, 1);

draw((4.5,4.5)--(6.5,3.5),linewidth(1.5));
draw((4.5,2.5)--(6.5,2.5),linewidth(1.5));
draw((3.5,1.5)--(6.5,1.5),linewidth(1.5));
label("Corner",(6.5,3.5),align=E,p=c1);
label("Edge",(6.5,2.5),align=E,p=c2);
label("Center",(6.5,1.5),align=E,p=c3);
[/asy]

The number of edges removed is different for each of these cases, and this is what motivates dividing the total number of black squares into a sum of three variables:
  • $X := \text{Number of Corner Black Squares}$
  • $Y := \text{Number of Edge Black Squares}$
  • $Z := \text{Number of Center Black Squares}$
This gives $\sigma := X+Y+Z$ as the total number of black squares.

With this, we can now compute the number of edges. Observe that a corner black square will delete $2$ edges, an edge square deletes $3$ edges, and a center will delete $4$ edges. It follows that:
$$\text{Edges Deleted} = 2X+3Y+4Z$$A possible issue to keep in mind, however: Couldn't deleting a vertex delete less edges than what is listed above? For example, this "center vertex" deletes only $3$ edges:

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)));
    }
}

void shade(pair bl, real sqSide){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=gray(0.1));
}

unitsize(1cm);
int[][] board = {{0,0,0,0},
                 {0,1,2,0},
                 {0,0,0,0},
                 {1,0,0,1}};

// Draw Grids

real hgap = 2;

fill(shift((2,2)) * ((0,0)--(1,0)--(1,1)--(0,1)--cycle),p=gray(0.5));
drawGrid((0,0), 4, 4, 1);
drawGrid((hgap+4,0), 4, 4, 1);

// Left Shading

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 1){
        	shade((j,3-i),1);
        }
	}
}

// Right Graph

for(int i1=0; i1 < 4; ++i1){
for(int j1=0; j1 < 4; ++j1){
    for(int i2=0; i2 < 4; ++i2){
	for(int j2=0; j2 < 4; ++j2){
    	if( (i1==i2 && abs(j1-j2)==1) || (j1==j2 && abs(i1-i2)==1) ){
        	if(board[i1][j1]==0 && board[i2][j2]==0){
            	draw(shift(4+hgap) * ((j1+.5,3-i1+.5)--(j2+.5,3-i2+.5)),p=linewidth(1.3)+rgb(.6,0,.4));
            }
        }
	}
	}
}
}

real r = 0.1;

for(int i=0; i < 4; ++i){
	for(int j=0; j < 4; ++j){
    	if(board[i][j] == 0){
        	filldraw(circle(shift(4+hgap)*(j+.5,3-i+.5),r), rgb(.6,0,.4));
        }
	}
}

draw((8.5,2.5)--(8.5,3.5),rgb(.6,0,.4)+dashed);
draw((8.5,2.5)--(8.5,1.5),rgb(.6,0,.4)+dashed);
draw((8.5,2.5)--(9.5,2.5),rgb(.6,0,.4)+dashed);
[/asy]

Fortunately, this situation can never happen, because two black squares cannot be adjacent!

In sum, we may conclude that the number of edges in the graph must be $e = (2mn-m-n) - (2X+3Y+4Z)$. Next, we need to compute the number of vertices. This is really easy: Every black square deletes exactly one vertex. Hence $v = mn - (X+Y+Z)$. Plugging this into the theorem, we obtain the following bound:
$$(2mn-m-n) - (2X+3Y+4Z) \geq mn - (X+Y+Z) - 1$$This rearranges to:
$$\boxed{X+2Y+3Z \leq (m-1)(n-1)}$$This is the first bound we need. Note that this is not quite a bound on $\sigma = X+Y+Z$, so we need to find some other inequalities.

Important Exercise: Prove or convince yourself that $(m-1)(n-1) - [X+2Y+3Z]$ is the most number of edges that can be deleted from $G$ without disconnecting $G$. (Hint: The expression is $e-v+1$, now extend the Theorem.)

Bounds Along the Boundary

$X+Y$ is the number of black squares along the boundary. What is the maximum value of $X+Y$ for an $m \times n$ board?

The trick is to subdivide the boundary squares into the following pieces:

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)),gray(0.5));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)),gray(0.5));
    }
}

void shade(pair bl, real sqSide){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=gray(0.1));
}

unitsize(1cm);

pen wide = linewidth(2);
drawGrid((0,0), 8, 6, 1);
draw((0,0)--(0,6)--(8,6)--(8,0)--cycle,wide);
draw((1,1)--(1,5)--(7,5)--(7,1)--cycle,wide);
for(int i=1;i<=3;++i){
	draw((2*i,0)--(2*i,1),wide);
    draw((2*i,5)--(2*i,6),wide);
}
for(int j=1;j<=2;++j){
	draw((0,2*j)--(1,2*j),wide);
    draw((7,2*j)--(8,2*j),wide);
}
[/asy]

Essentially, we put an L-tromino piece over each corner, and then fill the rest of the boundary with dominoes. Key Point: Each of these pieces can contain at most one black square! To count the number of these pieces:
  • There are $4$ L-trominos
  • Along the bottom edge, the tetronimoes take up $4$ squares, so the rest of the $m-4$ squares are taken up by dominoes. Hence $\frac{m-4}{2}$ dominoes on the bottom edge. Doing the same for the other three edges, we get $\frac{m-4}{2}+\frac{m-4}{2}+\frac{n-4}{2}+\frac{n-4}{2}$ dominoes in total.
  • In total, this is $m+n-4$ pieces, so $X+Y \leq m+n-4$.

There's a bit of a gap in this logic though: We can only tile the sides cleanly with dominoes if $m$ and $n$ are both even. If either are odd, then we'd need a lone $1 \times 1$ piece somewhere, so the pieces could look like this:

[asy]
void drawGrid(pair bl, int width, int height, real sqSide){
	for(int i = 0; i <= width; ++i){
    	draw((bl+(i*sqSide,0))--(bl+(i*sqSide,height*sqSide)),gray(0.5));
    }
    for(int j = 0; j <= height; ++j){
    	draw((bl+(0,j*sqSide))--(bl+(width*sqSide,j*sqSide)),gray(0.5));
    }
}

void shade(pair bl, real sqSide){
	fill(shift(bl) * ((0,0)--(sqSide,0)--(sqSide,sqSide)--(0,sqSide)--cycle),p=gray(0.1));
}

unitsize(1cm);

pen wide = linewidth(2);
drawGrid((0,0), 9, 7, 1);
draw((0,0)--(0,7)--(9,7)--(9,0)--cycle,wide);
draw((1,1)--(1,6)--(8,6)--(8,1)--cycle,wide);
for(int i=1;i<=3;++i){
	draw((2*i,0)--(2*i,1),wide);
    draw((2*i,6)--(2*i,7),wide);
}
for(int j=1;j<=2;++j){
	draw((0,2*j)--(1,2*j),wide);
    draw((8,2*j)--(9,2*j),wide);
}
draw((0,5)--(1,5),wide);
draw((8,5)--(9,5),wide);
draw((7,0)--(7,1),wide);
draw((7,6)--(7,7),wide);
[/asy]

It doesn't really matter where the $1 \times 1$ is. All that matters is that each region can have at most one black square. Now, to fix the above math to account for both the odd and even cases, we can just introduce the ceiling function. That is, there are $\left\lceil\frac{m-4}{2}\right\rceil+\left\lceil\frac{m-4}{2}\right\rceil+\left\lceil\frac{n-4}{2}\right\rceil+\left\lceil\frac{n-4}{2}\right\rceil$ dominoes and $1 \times 1$ pieces. Altogether, we find the bound:
$$\boxed{X+Y \leq 2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil-4}$$
Exercise: Convince yourself that this bound is tight. That is, it is always possible to obtain $2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil-4$ black squares on the boundary of the grid.

Now we have two inequalities, but it's not enough. We need one more inequality. The next inequality we get is absolutely ingenious. Buckle your seatbelts and steel yourself, because the logic is absolutely wild. Prepare for the greatest piece of mathematics you have ever seen.

The Final Inequality

$\boxed{X \leq 4}$ because there are four corners.

Putting it All Together

We have the inequalities:
$$X+2Y+3Z \leq (m-1)(n-1)$$$$X+Y \leq 2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil-4$$$$X \leq 4$$We need a bound on $\sigma = X+Y+Z$. Fortunately this is really easy: Just add all the inequalities! This gives:
$$3\sigma = 3X+3Y+3Z \leq (m-1)(n-1) + 2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil$$The RHS might not be divisible by $3$, so we'll leave it as this. Our first goal is essentially done! We've found some sort of bound for $\sigma$.

Now, for the second goal: Define $3\sigma$ to be the score of a configuration of black squares, and define $\mathcal{M}(m,n) := (m-1)(n-1) + 2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil$ to be the upper bound we got. How can we use the "closeness" of the score to the "theoretically maximum" score $\mathcal{M}(m,n)$ to deduce properties of the configuration?

Penalty Theory

Suppose the score was equal to the theoretical maximum, i.e. $3\sigma = \mathcal{M}(m,n)$. What would that mean? Looking back at the three inequalities we got earlier, that would have to imply that each of those inequalities were, in turn, equalities. This means that:
  • We deleted the maximum possible number of edges from the white-square graph $G$.
  • Every piece along the boundary of the grid has a black square.
  • Every corner square is black.

If instead the score was strictly less than the theoretical maximum $\mathcal{M}(m,n)$, then certain factors, called penalties, must be causing this. Penalties decrease the counts $X+2Y+3Z$, $X+Y$, and $X$, widening the gaps between these values and their corresponding theoretical maximums. Evidently, the sum of these gaps must be $\mathcal{M}(m,n) - 3\sigma$.

More precisely, these gaps are given by the following counts of penalties:
  • $P_g := (m-1)(n-1) - [X+2Y+3Z]$, which (by an Exercise) is the most number of edges we may delete from the white-square adjacency graph $G$ without disconnecting it.
  • $P_b := 2\left\lceil\frac{m}{2}\right\rceil+2\left\lceil\frac{n}{2}\right\rceil-4 - [X+Y]$, which (quite directly) is the deviation from the maximum of the number of black squares on the boundary.
  • $P_c := 4 - X$, which is the number of corner squares that aren't black.

Some notes on how to spot/count these easily:
  • If $P_g = 0$, that means that there can't be any loops that can be formed by traversing white squares. For instance, there cannot exist a $2 \times 2$ pool of white squares. More generally, $P_g$ can be determined by counting the number of such white-square loops, with the caveat that you cannot count a loop that is formed by the loop segments of previously counted loops. For example, a $3 \times 2$ pool of white squares will form only $2$ loops of white squares, not $3$.
  • $P_b$ can be computed by first dividing the boundary into pieces in the way we did before. Then, count the number of pieces that are empty.
  • $P_c$ can be counted by using your fingers.

Example

To reiterate, the importance of these quantities is that they must satisfy:
$$\boxed{P_g+P_b+P_c = \mathcal{M}(m,n) - 3\sigma}$$In certain specially-constructed "penalty Heyawakes", the RHS would, ideally, be a low number. If the LHS is low, this can set some major restrictions in how the black squares can be arranged, especially if you can spot some obvious instances of penalties right off the bat.


Summary of the Penalty Method
  1. When a Heyawake puzzle seems difficult, and the total number of squares seems more or less known and near-maximal, consider Penalty Theory.
  2. Count the number of black squares and triple it. This is the score of the puzzle.
  3. If the board is $m \times n$, compute $(m-1)(n-1)+2\lceil m/2\rceil + 2\lceil n/2\rceil$. Then, subtract the score obtained from the previous step. The resulting number is the total penalty, $P$.
  4. $P$ must be equal to the sum of the following three quantities:
    • $P_c$, the number of corner squares that are not shaded black.
    • $P_b$, how far away the number of black squares along the boundary (including corners) is from the theoretical maximum.
    • $P_g$, the number of loops you can form by traversing white squares. In counting this, do not count loops that can be formed by segments from previously counted loops. More Formally
    We call these the "penalties".
  5. Look for easy-to-spot instances of penalties. If you can find $P$ penalties, then you have found all penalties, meaning that the rest of the grid cannot have any penalties (this is a TON of information!).

Example Solve

Let us solve the following Heyawake: https://puzz.link/p?heyawake/6/6/00c011021020b10

https://i.imgur.com/dgHAN7C.png

Step 1

Step 2

Step 3

Step 4

Step 5

Step 6

Step 7

Your Turn!
  1. Solve my "Floating orb": https://puzz.link/p?heyawake/6/6/000c0i0010gsb10
    Hint
  2. Solve my "P-Pentomino": https://puzz.link/p?heyawake/6/6/00k4000643g0c0
    Hint
  3. Solve my extremely sus puzzle: https://puzz.link/p?heyawake/14/12/000000000000c450pnj72cop105k0000000000000041u71oa02g070e10803c0-310051
    Hint
  4. Solve this puzzle by @agnomy: https://puzz.link/p?heyawake/10/10/04080g1020490i14280000000000vv000000f5526
    Hint
  5. Solve this puzzle by Ivan Koswara: https://puzz.link/p?heyawake/8/7/060o00000081g2000000-121g
    Hint
  6. Solve another one by @agnomy:
    https://puzz.link/p?heyawake/12/12/00000o0003063cc0o00030000000008020080a4a92a02008020000-2811111111
  7. Solve this puzzle by Plurmorant:
    https://puzz.link/p?heyawake/10/10/00000112244000000000003s00003s000000-1f2
    Hint
  8. Solve my variant Heyawake, in which the board is a rotated diamond shape rather than a rectangle. Ignore the outer region when solving. Answer check will not work, you should verify correctness manually. https://puzz.link/p?heyawake/v:/23/23/0000006000280011000g40080g040202508118p0g0048000k0k02g5012180g8a0812g4040200g10020g00880014000600000000080002g000h0004200104008080260g0g09043121000481g0900012000840020800g0hg401010020800420008g000k0001000g-56h1Ok Hint


...and that's all I have for you in terms of Heyawake penalty theory! I hope this was fun to read. It's a remarkable application of math!

Have a merry new year.
This post has been edited 14 times. Last edited by greenturtle3141, Jan 1, 2022, 4:21 AM

Comment

0 Comments

Turtle math!

avatar

greenturtle3141
Archives
+ October 2024
Shouts
Submit
  • Can you give some thought to dropping a guide to STS? Just like how you presented your research (in your paper), what your essays were about, etc. Also cool blog!

    by Shreyasharma, Mar 13, 2025, 7:03 PM

  • this is so good

    by purpledonutdragon, Mar 4, 2025, 2:05 PM

  • orz usamts grader

    by Lhaj3, Jan 23, 2025, 7:43 PM

  • Entertaining blog

    by eduD_looC, Dec 31, 2024, 8:57 PM

  • wow really cool stuff

    by kingu, Dec 4, 2024, 1:02 AM

  • Although I had a decent college essay, this isn't really my specialty so I don't really have anything useful to say that isn't already available online.

    by greenturtle3141, Nov 3, 2024, 7:25 PM

  • Could you also make a blog post about college essay writing :skull:

    by Shreyasharma, Nov 2, 2024, 9:04 PM

  • what gold

    by peace09, Oct 15, 2024, 3:39 PM

  • oh lmao, i was confused because of the title initially. thanks! great read

    by OlympusHero, Jul 20, 2024, 5:00 AM

  • It should be under August 2023

    by greenturtle3141, Jul 11, 2024, 11:44 PM

  • does this blog still have the post about your math journey? for some reason i can't find it

    by OlympusHero, Jul 10, 2024, 5:41 PM

  • imagine not tortoise math

    no but seriously really interesting blog

    by fruitmonster97, Apr 2, 2024, 12:39 AM

  • W blog man

    by s12d34, Jan 24, 2024, 11:37 PM

  • very nice blog greenturtle it is very descriptive and fascinating to pay attention to :-D

    by StarLex1, Jan 3, 2024, 3:12 PM

  • orz blog

    by ryanbear, Dec 6, 2023, 9:23 PM

67 shouts
Tags
About Owner
  • Posts: 3554
  • Joined: Oct 14, 2014
Blog Stats
  • Blog created: Oct 23, 2021
  • Total entries: 54
  • Total visits: 41043
  • Total comments: 126
Search Blog
a