#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define D_LEFT -1
#define D_RIGHT 1
#define MAX_STATE (100*1000)
typedef struct tree_t{
int state;
int zero;
int one;
} tree;
typedef struct rule_t{
int state1;
unsigned char read;
int state2;
unsigned char write;
int direction;
} rule;
rule rules[1024];
int nrules;
rule converted[1024*128];
int nconverted;
int used_state[1024*128];
int nuseds;
int fused_symbol[256];
int bits = 1;
tree trees[1024*128];
int ntrees;
unsigned char symbit[256][8];
int isused( int state )
{
int i;
for( i = 0 ; i < nuseds ; i++ ) {
if( used_state[i] == state ) {
return 1;
}
}
return 0;
}
int find_unused( void )
{
int i;
for( i = 1 ; i < MAX_STATE ; i++ ) {
if( isused(i) == 0 ) {
return i;
}
}
return -1;
}
void init( void )
{
int i;
int cnt;
int n;
int k;
nconverted = 0;
nuseds = 0;
ntrees = 0;
for( i = 0 ; i < nrules ; i++ ) {
if( rules[i].state1 != -1 && isused( rules[i].state1 ) == 0 ) {
used_state[nuseds++] = rules[i].state1;
}
if( rules[i].state2 != -1 && isused( rules[i].state2 ) == 0 ) {
used_state[nuseds++] = rules[i].state2;
}
}
for( i = 0 ; i < 256 ; i++ ) {
fused_symbol[i] = 0;
}
for( i = 0 ; i < nrules ; i++ ) {
fused_symbol[rules[i].read] = 1;
fused_symbol[rules[i].write] = 1;
}
cnt = 0;
for( i = 0 ; i < 256 ; i++ ) {
if( fused_symbol[i] ) cnt++;
}
n = 1;
for( i = 2 ; i <= 256 ; i *= 2 ) {
if( cnt <= i ) break;
n++;
}
bits = n;
n = 0;
k = 1;
for( i = 0 ; i < bits-1 ; i++ ) {
k *= 2;
}
for( i = 0 ; i < 256 ; i++ ) {
if( fused_symbol[i] ) {
int j = 0;
int m = k;
for( j = 0 ; j < bits ; j++ ) {
if( n & m ) symbit[i][j] = 1;
else symbit[i][j] = 0;
m /= 2;
}
n++;
}
}
}
int find_tree( int state )
{
int i;
for( i = 0 ; i < ntrees ; i++ ) {
if( trees[i].state == state ) {
return i;
}
}
return -1;
}
/* change and move right */
void case2( int i , int n )
{
int j;
int n2;
int s;
int b,b2;
converted[n].direction = D_LEFT;
b = symbit[rules[i].write][bits-1];
converted[n].write = b ? '1' : '0';
s = find_unused();
used_state[nuseds++] = s;
converted[n].state2 = s;
for( j = 0 ; j < bits-1 ; j++ ) {
b = symbit[rules[i].write][bits-j-2];
b2 = symbit[rules[i].read][bits-j-2];
n2 = nconverted++;
converted[n2].direction = ( j == bits-2 ) ? D_RIGHT : D_LEFT;
converted[n2].state1 = s;
converted[n2].read = b2 ? '1' : '0';
converted[n2].write = b ? '1' : '0';
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
}
for( j = 0 ; j < bits-1 ; j++ ) {
b = symbit[rules[i].write][j+1];
n2 = nconverted++;
converted[n2].direction = D_RIGHT;
converted[n2].state1 = s;
converted[n2].read = b ? '1' : '0';
converted[n2].write = b ? '1' : '0';
if( j != bits-2 ) {
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
} else {
converted[n2].state2 = rules[i].state2;
}
}
}
/* not change and move left */
void case3( int i , int n )
{
int j;
int n2,n3;
int s;
int b;
converted[n].direction = D_LEFT;
s = find_unused();
used_state[nuseds++] = s;
converted[n].state2 = s;
for( j = 0 ; j < bits-1 ; j++ ) {
b = symbit[rules[i].read][bits-j-2];
n2 = nconverted++;
converted[n2].direction = D_LEFT;
converted[n2].state1 = s;
converted[n2].read = b ? '1' : '0';
converted[n2].write = b ? '1' : '0';
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
}
for( j = 0 ; j < bits-1 ; j++ ) {
n2 = nconverted++;
n3 = nconverted++;
converted[n2].direction = D_LEFT;
converted[n2].state1 = s;
converted[n2].read = '0';
converted[n2].write = '0';
converted[n3].direction = D_LEFT;
converted[n3].state1 = s;
converted[n3].read = '1';
converted[n3].write = '1';
if( j != bits-2 ) {
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
converted[n3].state2 = s;
} else {
converted[n2].state2 = rules[i].state2;
converted[n3].state2 = rules[i].state2;
}
}
}
/* change and move left */
void case4( int i , int n )
{
int j;
int n2,n3;
int s;
int b,b2;
converted[n].direction = D_LEFT;
b = symbit[rules[i].write][bits-1];
converted[n].write = b ? '1' : '0';
s = find_unused();
used_state[nuseds++] = s;
converted[n].state2 = s;
for( j = 0 ; j < bits-1 ; j++ ) {
b = symbit[rules[i].write][bits-j-2];
b2 = symbit[rules[i].read][bits-j-2];
n2 = nconverted++;
converted[n2].direction = D_LEFT;
converted[n2].state1 = s;
converted[n2].read = b2 ? '1' : '0';
converted[n2].write = b ? '1' : '0';
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
}
for( j = 0 ; j < bits-1 ; j++ ) {
n2 = nconverted++;
n3 = nconverted++;
converted[n2].direction = D_LEFT;
converted[n2].state1 = s;
converted[n2].read = '0';
converted[n2].write = '0';
converted[n3].direction = D_LEFT;
converted[n3].state1 = s;
converted[n3].read = '1';
converted[n3].write = '1';
if( j != bits-2 ) {
s = find_unused();
used_state[nuseds++] = s;
converted[n2].state2 = s;
converted[n3].state2 = s;
} else {
converted[n2].state2 = rules[i].state2;
converted[n3].state2 = rules[i].state2;
}
}
}
void convert( void )
{
int i,j;
int n;
int b;
int t,t2;
int s;
for( i = 0 ; i < nrules ; i++ ) {
s = rules[i].state1;
n = -1;
for( j = 0 ; j < bits ; j++ ) {
t = find_tree( s );
b = symbit[rules[i].read][j];
if( t == -1 ||
( trees[t].one == -1 && b ) ||
( trees[t].zero == -1 && b == 0 ) ) {
n = nconverted++;
converted[n].state1 = s;
converted[n].direction = D_RIGHT;
if( b == 0 ) {
converted[n].read = '0';
converted[n].write = '0';
} else {
converted[n].read = '1';
converted[n].write = '1';
}
if( t == -1 ) {
t = ntrees++;
trees[t].state = s;
trees[t].zero = -1;
trees[t].one = -1;
}
if( j != bits-1 ) {
t2 = ntrees++;
s = find_unused();
used_state[nuseds++] = s;
trees[t2].state = s;
if( b ) {
trees[t].one = t2;
} else {
trees[t].zero = t2;
}
trees[t2].zero = -1;
trees[t2].one = -1;
converted[n].state2 = s;
}
} else {
if( b && trees[t].one != -1 ) {
int t3 = trees[t].one;
s = trees[t3].state;
}
if( b == 0 && trees[t].zero != -1 ) {
int t3 = trees[t].zero;
s = trees[t3].state;
}
}
}
/* not change and move right */
if( rules[i].direction == D_RIGHT &&
( rules[i].read == rules[i].write ) ) {
if( n != -1 ) {
converted[n].state2 = rules[i].state2;
}
}
/* change and move right */
if( rules[i].direction == D_RIGHT &&
( rules[i].read != rules[i].write ) ) {
if( n != -1 ) {
case2( i , n );
}
}
/* not change and move left */
if( rules[i].direction == D_LEFT &&
( rules[i].read == rules[i].write ) ) {
if( n != -1 ) {
case3( i , n );
}
}
/* change and move left */
if( rules[i].direction == D_LEFT &&
( rules[i].read != rules[i].write ) ) {
if( n != -1 ) {
case4( i , n );
}
}
}
}
void ReadRule( char *filename )
{
FILE *fp;
char buf[1024];
fp = fopen_s( &fp , filename , "r" );
if( fp == NULL ) {
return;
}
nrules = 0;
for(;;) {
char *p
= fgets( buf
, sizeof(buf
) , fp
); char *pa[5];
int i,l,i2,f;
if( p == NULL ) break;
if( buf[l-1] == '\n' ) {
buf[l-1] = '\0';
l -= 1;
}
i2 = 0;
f = 0;
for( i = 0 ; i < l ; i++ ) {
if( !( buf[i] == ' ' || buf[i] == ',' ) && f == 0 ) {
if( i2 == 5 ) {
i2 = -1;
break;
}
pa[i2++] = &buf[i];
f = 1;
continue;
}
if( buf[i] == ' ' || buf[i] == ',' ) {
buf[i] = '\0';
f = 0;
}
}
if( i2 != 5 ) break;
rules
[nrules
].
state1 = atoi( pa
[0] );
break;
}
if( pa[1][0] == '_' ) pa[1][0] = ' ';
rules[nrules].read = pa[1][0];
if( strcmp( pa
[2] , "H" ) == 0 ) { rules[nrules].state2 = -1;
} else {
rules
[nrules
].
state2 = atoi( pa
[2] ); }
break;
}
if( pa[3][0] == '_' ) pa[3][0] = ' ';
rules[nrules].write = pa[3][0];
break;
}
if( pa[4][0] == '<' ) {
rules[nrules].direction = D_LEFT;
} else if( pa[4][0] == '>' ) {
rules[nrules].direction = D_RIGHT;
} else {
break;
}
nrules++;
}
}
void print( void )
{
int i,j;
for( i = 0 ; i < nconverted ; i++ ) {
converted[i].state1 ,
converted[i].read );
if( converted[i].state2 == -1 ) {
} else {
printf( "%d" , converted
[i
].
state2 ); }
converted[i].write ,
( converted[i].direction == D_RIGHT ) ? '>' : '<' );
}
for( i = 0 ; i < 256 ; i++ ) {
if( fused_symbol[i] ) {
printf( "%c : " , (unsigned char)i
== ' ' ? '_' : (unsigned char) i
); for( j = 0 ; j < bits ; j++ ) {
printf( "%d" , symbit
[i
][j
] ); }
}
}
}
int main( int argc , char *argv[] )
{
if( argc != 2 ) {
return 0;
}
ReadRule( argv[1] );
init();
if( bits == 1 ) {
printf( "no more work for this rule list\n" ); return 0;
}
convert();
print();
return 0;
}