home

About the Pattern Blocks app

Here are some very nerdy details about my journey in creating this version of the game.

Scenario:

A pattern-matching game has square tiles that are radially divided into 8 segments. Each segment can be black or white. The varying distribution of the black/white segments create the tile patterns. (The game involves aligning the tiles so that the touching sides have matching patterns. But that's a talk for a later time.)
The original game comes with When I encountered the game,the box had 36 tiles which, when placed in perfect arrangement, produces a 6 x 6 grid of tiles.

Query:

Are there only 36 possible tile patterns? Are there other patterns not included in the original set?

Problem:

How to generate the complete set of possible tiles without duplicates?

Background:

Each tile has 8 segments:
By numbering each of the 8 segments, the tile can be represented by string containing the numbers of "on" segments.
For example this is tile "1236":
Starting clockwise from the top left: segments 1, 2, 3, and 6 are in the "on" state.
The tile elment is a Custom Element. I converted the original tile set into a list of numeric representations that the script uses to generate the tiles programmatically

Brainstorming:

In my first attempt at finding all possible combinations, I enumerated the tiles with randomly assigned values, collected them in an array, and filtered out duplicates.
Because of imperfect randomization this approach was inefficient, requiring more iterations than the `maxtiles` value. But the main problem is that this does not actually identify duplicates since the tiles can be rotated.
In the real world, (1236) is the same tile as (2567) and (1478). (You can verify this yourself by clicking the tiles to rotate them until they are oriented the same way.)

Epihpany:

We get one step closer to the solution by converting the numeric representation into a binary notation.
So the above tile 1236 would be notated 11100100. The "1"s represent positive segments, and the "0"s represent negative segments.
In my first attempt at identifying possible binary combinations, I randomly assigned 1 or 0 to the 8 positions of a string, and collected those in an array.
Filtering out rotational duplicates turned out to be easier than I had anticipated. With help from the internet, I learned that string_b is a rotated version of string_a if string_b can be found in the concatenated/duplicated (string_a + string_a).

Hold it...

But there were 2 problems. First, I realized that I didn't have to randomly search for value combinations. It turned out to be even more inefficient than the numeric randomization, taking 400-500 iterations to get all the values. Plus, I was now essentially dealing with binary numbers. The tiles have 8 segments, each with a binary value (on or off). So 28 = 256 meant that I would only need to evaluate the loop 256 times max in order to identify all possible combinations.
But the second problem arose when checking for duplicates.
All 3 rotations of the binary notation above can be found within the comparison string, but rot1 and rot3 are not valid rotation patterns for the pattern tile, so they should have been considered "not a duplicate" and added to the list of found patterns.
Because the tiles have 2 segments on each side, each rotation has to involve 2 segments at a time.

Solution!

By splitting the 8-character string into 2 character chunks, the rotation-checking algorithm would not identify a match on single-character rotation:
Success!
The Custom Element I wrote to generate each tile takes numeric representation as input, so the next step was to convert it to the numeric string:
I wanted to optimize the numeric representations, partly for fun, partly for easier debugging, partly to compare with the original tileset.
On my first attempt at this, I subtracted one less than the first (smallest) value from each digit in the tile value:
Example:
For tile "3568"
The smallest value is 3
The minimizer quotient is 3 - 1 = 2
Subtract 2 from each digit of 3568 → 1346
However this presents a problem when encountering even-numbered first digits, again because of the paired segments. Using the above code, the delta alwayse reduced the first number to 1. The solution was to incorporate the modulus (remainder) operator in the calculation.

Done!

It turn out there are 70 unique patterns. According to this interesting page all about this game, the official set excludes these patterns:
So the full official set has 64 tiles. Since the set is non-random and static, rather than wasting time and CPU cycles generating the tiles on the fly every time, I included the resulting numeric representations in the code. Here is the finished code.

Conclusion

You're still here??? Well, I hope you enjoyed this journey into my mind. Have fun playing!