import DataStructures.*;
import Supporting.*;
import Exceptions.*;

public final class Josephus
{
    /**
     * Return the winner in the Josephus problem.
     * Linked list implementation.
     */
    public static int jos1( int people, int passes )
    {
        LinkedListItr p = new LinkedListItr( new LinkedList( ) );

            // Construct the list
        try
        {
            for( int i = 1; i <= people; i++ )
                p.insert( new Integer( i ) );
        }
        catch( ItemNotFound e ) { }  // Cannot happen

            // Play the game;
            // Note: p is always one player before
        while( people-- != 1 )
        {
            for( int i = 0; i < passes; i++ )
            {
                p.advance( );        // Advance
                if( !p.isInList( ) ) // If we just went past last player
                    p.first( );      // then go back to first
            }

            if( !p.removeNext( ) )   // Remove next player
            {
                // removeNext fails if p is last item,
                p.zeroth( );         // so for last item, set p
                p.removeNext( );     // to 0th player to remove first player
            }
        }

        p.first( );                    // Get first and only player and return
        return  ( (Integer)( p.retrieve( ) ) ).intValue( ); // player's number
    }

    /**
     * Recursively construct a perfectly balanced OrderedSearchTree
     * by repeated insertions in O( N log N ) time
     * t should be empty on the initial call
     */
    public static void buildTree( BinarySearchTreeWithRank t, int low, int high )
    {
        int center = ( low + high ) / 2;

        if( low <= high )
        {
            try
              { t.insert( new MyInteger( center ) ); }
            catch( DuplicateItem e ) { }  // Cannot happen

            buildTree( t, low, center - 1 );
            buildTree( t, center + 1, high );
        }
    }

    /**
     * Return the winner in the Josephus problem.
     * Search Tree implementation.
     */
    public static int jos2( int people, int passes )
    {
        BinarySearchTreeWithRank t = new BinarySearchTreeWithRank( );

        try
        {
            buildTree( t, 1, people );

            int rank = 1;
            while( people > 1 )
            {
                rank = ( rank + passes ) % people;
                if( rank == 0 )
                    rank = people;

                t.remove( t.findKth( rank ) );
                people--;
            }

            return ( ( MyInteger ) ( t.findKth( 1 ) ) ).intValue( );
        }
        catch( Exception e )
          { return -1; } // Cannot happen
    }


    // Quickie main to test

    public static void main( String [ ] args )
    {
        try
        {
            if( args.length == 2 )
            {
                int arg1 = Integer.parseInt( args[ 0 ] );
                int arg2 = Integer.parseInt( args[ 1 ] );
                System.out.println( jos1( arg1, arg2 ) );
                System.out.println( jos2( arg1, arg2 ) );
            }
            else
                System.err.println( "Usage: Jos People Passes" );
        }
        catch( NumberFormatException e )
          { System.err.println( "Usage: Jos People Passes" ); }
    }
}

