import std.stdio: writeln;
import core.bitop: bsr;
import std.string: countchars;
/// Returns the number of the top bit that changed from self - 1.
uint topChangedBit(uint x) pure nothrow {
return bsr(x ^ (x - 1));
}
/// Creates XOR masks for the folds, generates the sequence directly.
uint[] fold(in uint h, in uint v, in string folds) pure /*nothrow*/ {
immutable uint hBits = folds.countchars("LR"); // Not nothrow.
immutable uint vBits = folds.countchars("TB");
// Pre-condition.
assert(hBits + vBits == folds.length, "Illegal folds");
assert((1 << hBits) == h && (1 << vBits) == v);
enum uint one = 1;
uint hMask = (one << hBits) - 1;
uint vMask = (one << vBits) - 1;
uint[] masks;
uint hFinal, vFinal;
foreach (immutable char fold; folds) {
if (fold == 'L' || fold == 'R') {
masks ~= hMask;
hMask /= 2;
hFinal = hFinal * 2 + (fold == 'L');
} else {
masks ~= vMask << hBits;
vMask /= 2;
vFinal = vFinal * 2 + (fold == 'T');
}
}
uint n = (vFinal << hBits | hFinal) ^ masks[$ - 1];
auto result = [n + 1];
while (true) {
immutable i = result.length.topChangedBit;
if (i >= masks.length)
return result;
n ^= masks[i];
result ~= n + 1;
}
}
void main() {
fold(16, 16, "TLBLRRTB").writeln;
}