If a piece has been successfully placed then a check is made not to create spaces smaller than a piece or in which it is impossible to place pieces by using another 11-th lookup table ( for the moment it has 313 entries ) . If impossible spaces are created then give up testing the rest of the pieces and start another loop.

Thus running ( just for fun) on a PIC16F18857 microcontroller running at 32 MHz (8 MIPS) , starting from a purple part position (there are 228 possible positions but 114 unique starting positions without rotations) all positions are calculated in about 3 days with the remaining 9 pieces.

In total about 1 year all 1.14 x 10 exp 22 positions of the parts are tested ]]>

Just a quick follow-up — my friend and I both managed to create solvers using python that generate the full set of solutions. Mine runs in about 191 seconds, which is *far* slower than yours, but fast enough to not inhibit me.

We made some density plots for each of the pieces to see where each piece tends to be placed the most often, and have identified many 2-piece “starts” where there is only a single solution. I’m still running the tool to see if there are any single-piece starts with a single solution, i.e., if you put piece X in a certain spot, there’s only one solution after that. I suspect there aren’t any, but I haven’t confirmed that yet.

I’m also curious what … say… 5-piece start results in the largest number of unique solutions, meaning if you started someone with that board they have the easiest job of finishing.

I realized this problem is a little bit like an ant colony climbing up a tree looking for fruit on the branches. The ants can search every branch, which will take a long time (what else do they have to do), but if they could figure out how to eliminate branches without searching them that could save them a huge amount of time.

I still have no clue how your tool actually attacks this problem to identify dead-ends as shallowly as possible. My tool borrows an idea from my friend and takes the “L” (“+”-shaped) piece and moves it around the top left quadrant, then tries to fill in the remaining pieces, starting in the top left corner. Switching to this approach, I went from a few dozen solutions a second to like 1800 solutions per second (not all of them unique).

Thanks for the fun problem, help, and discussion!

]]>That fixed it, thx.

I have no understanding how this code could possibly be 25000 times more efficient than mine at finding solutions. Trying to parse DK’s dancing links, it seems like it’s just a method of adding and removing pieces from the solution quickly… Is the code really just brute-force trying every combination of every placement of every piece? And with dancing links it’s just ridiculously fast?

]]>I’m guessing that you perhaps (1) ran the *original* boards.py to generate inputs kanoodle.txt, (2) ran “test_dlx kanoodle.txt -2 > solutions.txt” to generate a list of solutions, then (3) ran the *updated* boards.py to get the integer-to-piece rows[] mapping? Instead, re-run test_dlx with the *updated* kanoodle.txt output from the new version of boards.py. If that doesn’t correct the disconnect, please let me know and we’ll track down the problem.

This was me trying to be helpful :). That is, in the original implementation, the rows container starts life as a *set*, which handles elimination of duplicate positioning/orientation of pieces as we move/rotate them throughout the grid. But when that set is *enumerated* to convert it to a sparse zero-one matrix for input to test_dlx.exe, the result is an *arbitrary* ordering of the rows (i.e., integer-to-piece mapping), that in general can even vary from one run of boards.py to the next (see here).

Now that we’re exposing that rows container, we convert it to a sorted(rows) list, which guarantees that its order will be deterministic and repeatable… but we have to re-run test_dlx.exe to get solutions that correspond to this new/fixed row ordering.

]]>@possiblywrong — ok, so I dumped the solutions from your tool, and the very first solution says that it has both placements 12 and 14. If I’m interpreting the output of todays update to board_cover(), both of those are piece C (blue), which seems to indicate that it’s placing the C piece twice. Do you see that?

]]>