I pushed a bunch of commits
today yesterday and now rotate has touchscreen support. Like, whoa, literally nobody requested that feature because literally nobody knows about that project anyway. I haven’t committed the solver code yet, and probably won’t for a while since it’s really kinda ugly. (I have five or six similar algorithms to solve rotate4 and there’s a lot of duplicated code because IDA* really needs the code to be heavily optimised to run fast. The loop overhead for looping over four elements is just too much when it has to be done hundreds of millions of times.)
I must say, programming things for touch screens is kinda hard without actually having a touchscreen device to test. I do have one of those “smartphone” thingamajigs that run Android but I don’t really use it a lot, so I had to charge it just to check the touch code was working correctly. Well, it almost was, and you can check the git commit history if you care to know about what I did wrong. Anyhow, I started off by making a generic handler which’d be easy to interface with mouse and touch events, then wrote code for pretending mouse events were touch events, then finally got to writing the touch event handlers.
Touch input didn’t quite work as intuitively as I expected it to, which is unfortunate because I actually spent a fair amount of time thinking “what if I implemented touchscreen support”. The layout’s also somewhat broken in mobile Firefox in a way I cannot reproduce with desktop Firefox. This really makes me wonder how people manage to design mobile websites at all; nothing ever works!
The next feature to land is probably going to be a timed solve function, and maybe macros because solving size-6 or larger puzzles is prohibitively time consuming without them. (Especially if you miss a move mid-sequence and everything just ends up wrong, then you have to redo a huge chunk of the solving. This incidentally was something that happened quite often when I did my gigaminx solve.)
Oh, and I wrote a solver for rotate5 (without orientation). I initially thought of directly adapting my human method of solving it, but came to realise that human methods are good only for humans because we can pull from all our non-domain-specific knowledge to attack problems, which is not so easily done within code. Common sense simply isn’t common when you’re a computer interpreting instructions from a human overlord. The approach of blindly generating and using lookup tables is rather easy to express in code; IDA* is trickier, but it’s not a very complicated algorithm either. There’s still human guidance involved in the sense that I’m telling it what intermediate phases to use, which could, in theory, be done away with entirely. GAP manages to decompose an element in a group into a product of elements from a specified generating set, so there surely has to be a way to automate it completely, though this might not run performantly.
That said, I’m not sure what to do with rotate5 with orientation. It’s very annoyingly nontrivial to just split it into intermediate phases that have coset spaces which are not too large (because we want it to not take 10 days to initialise the solver) and are easily described (because we want it to be easy to code). The difference here compared to rotate4o is that rotate4 has only two possible orientations per piece while rotate5o has four, and given that this grows exponentially with the number of pieces (of which there are also more) and that lookup tables for a phase are proportional in size to the coset space… you get the idea. Another contributing factor to this difference is that rotate4o has an subgroup with a simple set of generators, but rotate5o doesn’t have a simple set of generators generating . (But the quotient group would still have 424 elements, which is too large to compute full lookup tables for anyway, so maybe this isn’t as useful as I thought it’d be. There’re no meaningful intermediate subgroups that can be used for solving orientation: either you solve it all at once, or the symmetric subgroup will allow the unsolved parts to leak into the solved parts.)
Relatedly, rotate6 is sort of a deep-cut puzzle, since every pair of moves intersect in a “nontrivial” manner. To twist the definition of “triviality” a bit here, I suppose we can consider rotate5 to not be a deep-cut puzzle because it’s easy to separate pieces and manipulate them individually. rotate5 with the top row and leftmost column fixed, though, does not have individually-manipulable pieces, which is much the same situation as rotate6. This is what makes rotate6 a fundamentally distinct puzzle from rotate4 or rotate5, while any larger size is simply a direct generalisation of rotate6 and can be solved in much the same way.