Bit-packed multiway code

StringToBits[s_String,letters_List,intsize_:32]:=Module[{chunk=Ceiling[Log[2,Length[letters]]],c=Flatten[Position[letters,#]&/@Characters[s]]-1,n},{StringLength[s]*chunk,If[#>=2^(intsize-1),#-2^intsize,#]&/@Reverse[IntegerDigits[FromDigits[Reverse[c],2^chunk],2^intsize]]}];
BitsToString[{n_Integer,bits_List},letters_List,intsize_:32]:=Module[{chunk=Ceiling[Log[2,Length[letters]]],b=If[#<0,#+2^intsize,#]&/@bits,f},If[(f=FromDigits[Reverse[b],2^intsize])>=2^n,Print["Error: ",{n,b}]];StringJoin[letters〚#+1〛&/@Reverse[IntegerDigits[f,2^chunk,n/chunk]]]];
FSM[lhs_List,chunk_Integer,intsize_:32]:=Block[{lh=MapIndexed[{First[#2],#1〚1〛,FromDigits[Reverse[#1〚2〛],2^intsize]}&,lhs],ch=chunk,states,new,match={},index,index2,m,n=0,q},states={lh};FSMRecurse[1,1];m=Length[states]-1;Do[q=First/@Cases[states〚i〛,{_,0,0}];If[Length[q]>0,match=Append[match,q-1];index[n]=i;index2[i]=n;n++,index[m]=i;index2[i]=m;m--],{i,Length[states]}];{Table[{index2[#〚1〛],index2[#〚2〛]}&@new[index[i]],{i,0,Length[states]-1}],match}]
FSMRecurse[s_Integer,c_Integer]:=Module[{state=states〚s〛,newstate,next,newc=If[c==ch,1,c+1],p},Do[newstate={};Do[If[state〚j,2〛>0,If[Xor[OddQ[state〚j,3〛],i==0],newstate=Append[newstate,{state〚j,1〛,state〚j,2〛-1,Floor[state〚j,3〛/2]}]]],{j,Length[state]}];If[c==ch,newstate=Join[newstate,lh]];p=Position[states,newstate,{1}];If[Length[p]>0,next[i]=p〚1,1〛,states=Append[states,newstate];next[i]=Length[states];FSMRecurse[Length[states],newc]],{i,0,1}];new[s]={next[0],next[1]}];
MWToBits[rules_List,init_List,intsize_:32]:=Module[{letters=Union[Flatten[Characters[{Apply[List,#]&/@rules,init}]]]},If[Length[letters]==1,letters=Append[letters,If[letters〚1〛=="A","B","A"]]];{Map[StringToBits[#,letters,intsize]&,rules,{2}],StringToBits[#,letters,intsize]&/@init,letters,Ceiling[Log[2,Length[letters]]]}];
This is a crude wrapper to MWBitsX (the MathLink C function) which doesn't process its output.
MWBits[rules_List,init_List,maxlevel_Integer,outflag_Integer,maxlen_Integer:0,intsize_Integer:32]:=MWBitsX[maxlevel,outflag,maxlen,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}]&@MWToBits[rules,init,intsize]
This function outputs all of the new strings at each level. (The U stands for "unique", signifying that only new strings are output, rather than all the strings.)
XMWUEvolveList[rules_List,init_List,maxlevel_Integer,intsize_Integer:32]:=Map[Function[y,BitsToString[y,#〚3〛,intsize]],MWBitsX[maxlevel,0,0,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}],{2}]&@MWToBits[rules,init,intsize]
This function outputs the new strings too, except they are given in bits form instead of string form.
XMWUEvolveListBits[rules_List,init_List,maxlevel_Integer,intsize_Integer:32]:=MWBitsX[maxlevel,0,0,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}]&@MWToBits[rules,init,intsize]
This function outputs a list of the lengths of the new strings at each level.
XMWUEvolveLengthsList[rules_List,init_List,maxlevel_Integer,intsize_Integer:32]:=Map[Function[y,y/#〚4〛],MWBitsX[maxlevel,1,0,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}],{2}]&@MWToBits[rules,init,intsize]
This function outputs the lengths of the new strings at each level in the form {length, number of strings with that length}.
XMWUEvolveLengths[rules_List,init_List,maxlevel_Integer,intsize_Integer:32]:=Map[Function[y,{y〚1〛/#〚4〛,y〚2〛}],MWBitsX[maxlevel,3,0,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}],{2}]&@MWToBits[rules,init,intsize]
Map[({#[[1]]+1,#[[2]]})&,{{{3,5},{2,8},{4,6}},{{2,1}}},{2}]
{{{4,5},{3,8},{5,6}},{{3,1}}}
This function outputs the total number of new strings at each level.
XMWUEvolveTotals[rules_List,init_List,maxlevel_Integer,intsize_Integer:32]:=MWBitsX[maxlevel,2,0,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}]&@MWToBits[rules,init,intsize]
This function outputs at each level a list of the form {{list of new strings of length <= maxlen},total # of new strings, {min length of new strings, max length of new strings}} (with the last element of the list occurring only if there are new strings).
XMWUShortStrings[rules_List,init_List,maxlevel_Integer,maxlen_Integer,intsize_Integer:32]:=Map[Function[y,Function[w,If[Length[y]2,w,Append[w,y〚3〛/#〚4〛]]]@{Function[z,BitsToString[z,#〚3〛,intsize]]/@(y〚1〛),y〚2〛}],MWBitsX[maxlevel,4,maxlen*#〚4〛,{Function[x,{x〚1,1〛,x〚2,1〛,x〚2,2〛}]/@#〚1〛,#〚2〛,FSM[First/@#〚1〛,#〚4〛,intsize]}]]&@MWToBits[rules,init,intsize]
$MWLink=Install["MultiwaySystems`mwlink`"];
LinkObject[".\MultiwaySystems\mwlink.exe\Windows\mwlink.exe",3,3]