importjava.util.Scanner;

class turing

{

finalintINIT_ALLOC_SIZ = 1000;

intallocSiz;

char[]tapeContents;

intcurrHeadPos;

intendOfTape;

public turing()

{

allocSiz = INIT_ALLOC_SIZ;

tapeContents = new char[ allocSiz ];

// ------//

// initialize tape to all spaces //

// ------//

for( int i = 0; i < INIT_ALLOC_SIZ; i++ )

{

tapeContents[ i ] = ' ';

}

currHeadPos = 0;

endOfTape = 1;

}

public void cmdLoop()

{

ScannergetReq = new Scanner( System.in );

for( ; ; reallocIfMust() )

{

say( "" );

say( "current read/write head position: " + currHeadPos );

say( "" );

postMenu();

StringuserInput = getReq.nextLine().toUpperCase();

charcommand = userInput.charAt( 0 );

say( "" );

// ------//

// if-else if-else is less error-prone than //

// switch and doesn't require as much indentation //

// ------//

if( command == '?' )

{

dumpTape( currHeadPos, currHeadPos + 1 );

}

else

if( command == '=' )

{

say( "Enter value of cell: " );

StringnewValue = getReq.nextLine();

tapeContents[ currHeadPos ] = newValue.charAt( 0 );

if( ++currHeadPos > endOfTape )

{

endOfTape++;

}

}

else

if( command == 'E' )

{

// ------//

// we use a space to signal 'empty' so //

// that cells will print out reasonably //

// ------//

tapeContents[ currHeadPos ] = ' ';

}

else

if( command == 'L' )

{

if( currHeadPos == 0 )

{

say( "" );

say( "Tape rewound, unable to move LEFT" );

}

else

{

currHeadPos--;

}

}

else

if( command == 'R' )

{

currHeadPos++;

endOfTape++;

}

else

if( command == 'B' )

{

currHeadPos = 0;

}

else

if( command == 'D' )

{

dumpTape( 0, endOfTape );

}

else

if( command == 'X' )

{

System.exit( 0 );

}

}

}

public void reallocIfMust()

{

if( endOfTape >= allocSiz )

{

// ------//

// if out of tape memory, double its size //

// ------//

intreallocSiz = 2 * allocSiz;

char[]newTapeContents = new char[ reallocSiz ];

for( int i = 0; i < endOfTape; i++ )

{

newTapeContents[ i ] = tapeContents[ i ];

}

tapeContents = newTapeContents;

allocSiz = reallocSiz;

}

}

public void dumpTape( int startPos, int endPos )

{

String[]outRows = new String[ 5 ];

for( int i = startPos; i < endPos; i++ )

{

// ------//

// output max ten positions per row, each //

// printed position being six bytes wide //

// ------//

if( ( i - startPos ) % 10 == 0 )

{

if( i != startPos )

{

for( int row = 0; row < 5; row++ )

{

say( outRows[ row ] );

}

}

outRows[ 0 ] = " +";

outRows[ 1 ] = "POS |";

outRows[ 2 ] = " +";

outRows[ 3 ] = "VAL |";

outRows[ 4 ] = " +";

say( "" );

}

outRows[ 0 ] += "-----+";

outRows[ 1 ] += " " + String.format( "%3d", i ) + " |";

outRows[ 2 ] += "-----+";

outRows[ 3 ] += " " + ( Character.isISOControl( tapeContents[ i ] )

? " "

: Character.toString( tapeContents[ i ] )

)

+ " |";

outRows[ 4 ] += "-----+";

if( i == endPos - 1 )

{

for( int row = 0; row < 5; row++ )

{

say( outRows[ row ] );

}

}

}

}

public void postMenu()

{

say( "Enter command:" );

say( "" );

say( "\t?\tprint current cell" );

say( "\t=\tassign new symbol to current cell" );

say( "\tE\terase current cell" );

say( "\tL\tmove tape to left" );

say( "\tR\tmove tape to right" );

say( "\tB\trewind to beginning of tape" );

say( "\tD\tdump contents of tape" );

say( "\tX\texit program" );

say( "" );

}

public void say( String s )

{

// ------//

// convenience function enables us to avoid cluttering //

// the code with System.out.println() all over the place //

// ------//

System.out.println( s );

}

public static void main( String[] argv )

{

turingt = new turing();

t.cmdLoop();

}

}