java program

profileh66umi6q
stdlib.jar

META-INF/MANIFEST.MF

Manifest-Version: 1.0 Created-By: 1.8.0_191 (Oracle Corporation)

BinaryIn.java

BinaryIn.java

/******************************************************************************
 *  Compilation:  javac BinaryIn.java
 *  Execution:    java BinaryIn input output
 *  Dependencies: none             
 *  
 *  This library is for reading binary data from an input stream.
 *
 *  % java BinaryIn https://introcs.cs.princeton.edu/java/cover.png output.png
 *
 ******************************************************************************/

import  java . io . BufferedInputStream ;
import  java . io . File ;
import  java . io . FileInputStream ;
import  java . io . IOException ;
import  java . io . InputStream ;
import  java . net . Socket ;
import  java . net . URL ;
import  java . net . URLConnection ;
import  java . util . NoSuchElementException ;

/**
 *  <i>Binary input</i>. This class provides methods for reading
 *  in bits from a binary input stream, either
 *  one bit at a time (as a { @code  boolean}),
 *  8 bits at a time (as a { @code  byte} or { @code  char}),
 *  16 bits at a time (as a { @code  short}),
 *  32 bits at a time (as an { @code  int} or { @code  float}), or
 *  64 bits at a time (as a { @code  double} or { @code  long}).
 *  <p>
 *  The binary input stream can be from standard input, a filename,
 *  a URL name, a Socket, or an InputStream.
 *  <p>
 *  All primitive types are assumed to be represented using their 
 *  standard Java representations, in big-endian (most significant
 *  byte first) order.
 *  <p>
 *  The client should not intermix calls to { @code  BinaryIn} with calls
 *  to { @code  In}; otherwise unexpected behavior will result.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   BinaryIn   {
     private   static   final   int  EOF  =   - 1 ;     // end of file

     private   BufferedInputStream  in ;        // the input stream
     private   int  buffer ;                    // one character buffer
     private   int  n ;                         // number of bits left in buffer

    /**
     * Initializes a binary input stream from standard input.
     */
     public   BinaryIn ()   {
        in  =   new   BufferedInputStream ( System . in );
        fillBuffer ();
     }

    /**
     * Initializes a binary input stream from an { @code  InputStream}.
     *
     *  @param  is the { @code  InputStream} object
     */
     public   BinaryIn ( InputStream  is )   {
        in  =   new   BufferedInputStream ( is );
        fillBuffer ();
     }

    /**
     * Initializes a binary input stream from a socket.
     *
     *  @param  socket the socket
     */
     public   BinaryIn ( Socket  socket )   {
         try   {
             InputStream  is  =  socket . getInputStream ();
            in  =   new   BufferedInputStream ( is );
            fillBuffer ();
         }
         catch   ( IOException  ioe )   {
             System . err . println ( "Could not open "   +  socket );
         }
     }

    /**
     * Initializes a binary input stream from a URL.
     *
     *  @param  url the URL
     */
     public   BinaryIn ( URL url )   {
         try   {
             URLConnection  site  =  url . openConnection ();
             InputStream  is      =  site . getInputStream ();
            in  =   new   BufferedInputStream ( is );
            fillBuffer ();
         }
         catch   ( IOException  ioe )   {
             System . err . println ( "Could not open "   +  url );
         }
     }

    /**
     * Initializes a binary input stream from a filename or URL name.
     *
     *  @param  name the name of the file or URL
     */
     public   BinaryIn ( String  name )   {

         try   {
             // first try to read file from local file system
             File  file  =   new   File ( name );
             if   ( file . exists ())   {
                 FileInputStream  fis  =   new   FileInputStream ( file );
                in  =   new   BufferedInputStream ( fis );
                fillBuffer ();
                 return ;
             }

             // next try for files included in jar
            URL url  =  getClass (). getResource ( name );

             // or URL from web
             if   ( url  ==   null )   {
                url  =   new  URL ( name );
             }

             URLConnection  site  =  url . openConnection ();
             InputStream  is      =  site . getInputStream ();
            in  =   new   BufferedInputStream ( is );
            fillBuffer ();
         }
         catch   ( IOException  ioe )   {
             System . err . println ( "Could not open "   +  name );
         }
     }

     private   void  fillBuffer ()   {
         try   {
            buffer  =  in . read ();
            n  =   8 ;
         }
         catch   ( IOException  e )   {
             System . err . println ( "EOF" );
            buffer  =  EOF ;
            n  =   - 1 ;
         }
     }

     /**
     * Returns true if this binary input stream exists.
     *
     *  @return  { @code  true} if this binary input stream exists;
     *         { @code  false} otherwise
     */
     public   boolean  exists ()    {
         return  in  !=   null ;
     }

    /**
     * Returns true if this binary input stream is empty.
     *
     *  @return  { @code  true} if this binary input stream is empty;
     *         { @code  false} otherwise
     */
     public   boolean  isEmpty ()   {
         return  buffer  ==  EOF ;
     }

    /**
     * Reads the next bit of data from this binary input stream and return as a boolean.
     *
     *  @return  the next bit of data from this binary input stream as a { @code  boolean}
     *  @throws  NoSuchElementException if this binary input stream is empty
     */
     public   boolean  readBoolean ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );
        n -- ;
         boolean  bit  =   (( buffer  >>  n )   &   1 )   ==   1 ;
         if   ( ==   0 )  fillBuffer ();
         return  bit ;
     }

    /**
     * Reads the next 8 bits from this binary input stream and return as an 8-bit char.
     *
     *  @return  the next 8 bits of data from this binary input stream as a { @code  char}
     *  @throws  NoSuchElementException if there are fewer than 8 bits available
     */
     public   char  readChar ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );

         // special case when aligned byte
         if   ( ==   8 )   {
             int  x  =  buffer ;
            fillBuffer ();
             return   ( char )   ( &   0xff );
         }

         // combine last N bits of current buffer with first 8-N bits of new buffer
         int  x  =  buffer ;
        x  <<=   ( 8   -  n );
         int  oldN  =  n ;
        fillBuffer ();
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );
        n  =  oldN ;
        x  |=   ( buffer  >>>  n );
         return   ( char )   ( &   0xff );
         // the above code doesn't quite work for the last character if N = 8
         // because buffer will be -1
     }


    /**
     * Reads the next r bits from this binary input stream and return as an r-bit character.
     *
     *  @param   r number of bits to read
     *  @return  the next { @code  r} bits of data from this binary input streamt as a { @code  char}
     *  @throws  NoSuchElementException if there are fewer than { @code  r} bits available
     *  @throws  IllegalArgumentException unless { @code  1 <= r <= 16}
     */
     public   char  readChar ( int  r )   {
         if   ( <   1   ||  r  >   16 )   throw   new   IllegalArgumentException ( "Illegal value of r = "   +  r );

         // optimize r = 8 case
         if   ( ==   8 )   return  readChar ();

         char  x  =   0 ;
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
            x  <<=   1 ;
             boolean  bit  =  readBoolean ();
             if   ( bit )  x  |=   1 ;
         }
         return  x ;
     }


    /**
     * Reads the remaining bytes of data from this binary input stream and return as a string. 
     *
     *  @return  the remaining bytes of data from this binary input stream as a { @code  String}
     *  @throws  NoSuchElementException if this binary input stream is empty or if the number of bits
     *         available is not a multiple of 8 (byte-aligned)
     */
     public   String  readString ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );

         StringBuilder  sb  =   new   StringBuilder ();
         while   ( ! isEmpty ())   {
             char  c  =  readChar ();
            sb . append ( c );
         }
         return  sb . toString ();
     }


    /**
     * Reads the next 16 bits from this binary input stream and return as a 16-bit short.
     *
     *  @return  the next 16 bits of data from this binary input stream as a { @code  short}
     *  @throws  NoSuchElementException if there are fewer than 16 bits available
     */
     public   short  readShort ()   {
         short  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   2 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }

    /**
     * Reads the next 32 bits from this binary input stream and return as a 32-bit int.
     *
     *  @return  the next 32 bits of data from this binary input stream as a { @code  int}
     *  @throws  NoSuchElementException if there are fewer than 32 bits available
     */
     public   int  readInt ()   {
         int  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   4 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }

    /**
     * Reads the next r bits from this binary input stream return as an r-bit int.
     *
     *  @param   r number of bits to read
     *  @return  the next { @code  r} bits of data from this binary input stream as a { @code  int}
     *  @throws  NoSuchElementException if there are fewer than r bits available
     *  @throws  IllegalArgumentException unless { @code  1 <= r <= 32}
     */
     public   int  readInt ( int  r )   {
         if   ( <   1   ||  r  >   32 )   throw   new   IllegalArgumentException ( "Illegal value of r = "   +  r );

         // optimize r = 32 case
         if   ( ==   32 )   return  readInt ();

         int  x  =   0 ;
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
            x  <<=   1 ;
             boolean  bit  =  readBoolean ();
             if   ( bit )  x  |=   1 ;
         }
         return  x ;
     }

    /**
     * Reads the next 64 bits from this binary input stream and return as a 64-bit long.
     *
     *  @return  the next 64 bits of data from this binary input stream as a { @code  long}
     *  @throws  NoSuchElementException if there are fewer than 64 bits available
     */
     public   long  readLong ()   {
         long  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   8 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }

    /**
     * Reads the next 64 bits from this binary input stream and return as a 64-bit double.
     *
     *  @return  the next 64 bits of data from this binary input stream as a { @code  double}
     *  @throws  NoSuchElementException if there are fewer than 64 bits available
     */
     public   double  readDouble ()   {
         return   Double . longBitsToDouble ( readLong ());
     }

    /**
     * Reads the next 32 bits from this binary input stream and return as a 32-bit float.
     *
     *  @return  the next 32 bits of data from this binary input stream as a { @code  float}
     *  @throws  NoSuchElementException if there are fewer than 32 bits available
     */
     public   float  readFloat ()   {
         return   Float . intBitsToFloat ( readInt ());
     }


    /**
     * Reads the next 8 bits from this binary input stream and return as an 8-bit byte.
     *
     *  @return  the next 8 bits of data from this binary input stream as a { @code  byte}
     *  @throws  NoSuchElementException if there are fewer than 8 bits available
     */
     public   byte  readByte ()   {
         char  c  =  readChar ();
         return   ( byte )   ( &   0xff );
     }
    
    /**
     * Unit tests the { @code  BinaryIn} data type.
     * Reads the name of a file or URL (first command-line argument)
     * and writes it to a file (second command-line argument).
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         BinaryIn   in   =   new   BinaryIn ( args [ 0 ]);
         BinaryOut  out  =   new   BinaryOut ( args [ 1 ]);

         // read one 8-bit char at a time
         while   ( ! in . isEmpty ())   {
             char  c  =  in . readChar ();
            out . write ( c );
         }
        out . flush ();
     }
}

BinaryOut.java

BinaryOut.java

/******************************************************************************
 *  Compilation:  javac BinaryOut.java
 *  Execution:    java BinaryOut
 *  Dependencies: none
 *
 *  Write binary data to an output stream, either one 1-bit boolean,
 *  one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
 *  or one 64-bit long at a time. The output stream can be standard
 *  output, a file, an OutputStream or a Socket.
 *
 *  The bytes written are not aligned.
 *
 ******************************************************************************/

import  java . io . BufferedOutputStream ;
import  java . io . FileOutputStream ;
import  java . io . IOException ;
import  java . io . OutputStream ;
import  java . net . Socket ;

/**
 *  <i>Binary output</i>. This class provides methods for converting
 *  primtive type variables ({ @code  boolean}, { @code  byte}, { @code  char},
 *  { @code  int}, { @code  long}, { @code  float}, and { @code  double})
 *  to sequences of bits and writing them to an output stream.
 *  The output stream can be standard output, a file, an OutputStream or a Socket.
 *  Uses big-endian (most-significant byte first).
 *  <p>
 *  The client must { @code  flush()} the output stream when finished writing bits.
 *  <p>
 *  The client should not intermix calls to { @code  BinaryOut} with calls
 *  to { @code  Out}; otherwise unexpected behavior will result.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   BinaryOut   {

     private   BufferedOutputStream  out ;    // the output stream
     private   int  buffer ;                  // 8-bit buffer of bits to write out
     private   int  n ;                       // number of bits remaining in buffer


    /**
     * Initializes a binary output stream from standard output.
     */
     public   BinaryOut ()   {
        out  =   new   BufferedOutputStream ( System . out );
     }

    /**
     * Initializes a binary output stream from an { @code  OutputStream}.
     *  @param  os the { @code  OutputStream}
     */
     public   BinaryOut ( OutputStream  os )   {
        out  =   new   BufferedOutputStream ( os );
     }

    /**
     * Initializes a binary output stream from a file.
     *  @param  filename the name of the file
     */
     public   BinaryOut ( String  filename )   {
         try   {
             OutputStream  os  =   new   FileOutputStream ( filename );
            out  =   new   BufferedOutputStream ( os );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Initializes a binary output stream from a socket.
     *  @param  socket the socket
     */
     public   BinaryOut ( Socket  socket )   {
         try   {
             OutputStream  os  =  socket . getOutputStream ();
            out  =   new   BufferedOutputStream ( os );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }


    /**
     * Writes the specified bit to the binary output stream.
     *  @param  x the bit
     */
     private   void  writeBit ( boolean  x )   {
         // add bit to buffer
        buffer  <<=   1 ;
         if   ( x )  buffer  |=   1 ;

         // if buffer is full (8 bits), write out as a single byte
        n ++ ;
         if   ( ==   8 )  clearBuffer ();
     }  

    /**
     * Writes the 8-bit byte to the binary output stream.
     *  @param  x the byte
     */
     private   void  writeByte ( int  x )   {
         assert  x  >=   0   &&  x  <   256 ;

         // optimized if byte-aligned
         if   ( ==   0 )   {
             try   {
                out . write ( x );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
             return ;
         }

         // otherwise write one bit at a time
         for   ( int  i  =   0 ;  i  <   8 ;  i ++ )   {
             boolean  bit  =   (( >>>   ( 8   -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }

     // write out any remaining bits in buffer to the binary output stream, padding with 0s
     private   void  clearBuffer ()   {
         if   ( ==   0 )   return ;
         if   ( >   0 )  buffer  <<=   ( 8   -  n );
         try   {
            out . write ( buffer );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
        n  =   0 ;
        buffer  =   0 ;
     }

    /**
     * Flushes the binary output stream, padding 0s if number of bits written so far
     * is not a multiple of 8.
     */
     public   void  flush ()   {
        clearBuffer ();
         try   {
            out . flush ();
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Flushes and closes the binary output stream.
     * Once it is closed, bits can no longer be written.
     */
     public   void  close ()   {
        flush ();
         try   {
            out . close ();
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }


    /**
     * Writes the specified bit to the binary output stream.
     *  @param  x the { @code  boolean} to write
     */
     public   void  write ( boolean  x )   {
        writeBit ( x );
     }  

    /**
     * Writes the 8-bit byte to the binary output stream.
     *  @param  x the { @code  byte} to write.
     */
     public   void  write ( byte  x )   {
        writeByte ( &   0xff );
     }

    /**
     * Writes the 32-bit int to the binary output stream.
     *  @param  x the { @code  int} to write
     */
     public   void  write ( int  x )   {
        writeByte (( >>>   24 )   &   0xff );
        writeByte (( >>>   16 )   &   0xff );
        writeByte (( >>>    8 )   &   0xff );
        writeByte (( >>>    0 )   &   0xff );
     }

    /**
     * Writes the r-bit int to the binary output stream.
     *
     *  @param   x the { @code  int} to write
     *  @param   r the number of relevant bits in the char
     *  @throws  IllegalArgumentException unless { @code  r} is between 1 and 32
     *  @throws  IllegalArgumentException unless { @code  x} is between 0 and 2<sup>r</sup> - 1
     */
     public   void  write ( int  x ,   int  r )   {
         if   ( ==   32 )   {
            write ( x );
             return ;
         }
         if   ( <   1   ||  r  >   32 )   throw   new   IllegalArgumentException ( "Illegal value for r = "   +  r );
         if   ( >=   ( 1   <<  r ))     throw   new   IllegalArgumentException ( "Illegal "   +  r  +   "-bit char = "   +  x );
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
             boolean  bit  =   (( >>>   ( -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }


    /**
     * Writes the 64-bit double to the binary output stream.
     *  @param  x the { @code  double} to write
     */
     public   void  write ( double  x )   {
        write ( Double . doubleToRawLongBits ( x ));
     }

    /**
     * Writes the 64-bit long to the binary output stream.
     *  @param  x the { @code  long} to write
     */
     public   void  write ( long  x )   {
        writeByte (( int )   (( >>>   56 )   &   0xff ));
        writeByte (( int )   (( >>>   48 )   &   0xff ));
        writeByte (( int )   (( >>>   40 )   &   0xff ));
        writeByte (( int )   (( >>>   32 )   &   0xff ));
        writeByte (( int )   (( >>>   24 )   &   0xff ));
        writeByte (( int )   (( >>>   16 )   &   0xff ));
        writeByte (( int )   (( >>>    8 )   &   0xff ));
        writeByte (( int )   (( >>>    0 )   &   0xff ));
     }

    /**
     * Writes the 32-bit float to the binary output stream.
     *  @param  x the { @code  float} to write
     */
     public   void  write ( float  x )   {
        write ( Float . floatToRawIntBits ( x ));
     }

    /**
     * Write the 16-bit int to the binary output stream.
     *  @param  x the { @code  short} to write.
     */
     public   void  write ( short  x )   {
        writeByte (( >>>    8 )   &   0xff );
        writeByte (( >>>    0 )   &   0xff );
     }

    /**
     * Writes the 8-bit char to the binary output stream.
     *
     *  @param   x the { @code  char} to write
     *  @throws  IllegalArgumentException unless { @code  x} is betwen 0 and 255
     */
     public   void  write ( char  x )   {
         if   ( <   0   ||  x  >=   256 )   throw   new   IllegalArgumentException ( "Illegal 8-bit char = "   +  x );
        writeByte ( x );
     }

    /**
     * Writes the r-bit char to the binary output stream.
     *
     *  @param   x the { @code  char} to write
     *  @param   r the number of relevant bits in the char
     *  @throws  IllegalArgumentException unless { @code  r} is between 1 and 16
     *  @throws  IllegalArgumentException unless { @code  x} is between 0 and 2<sup>r</sup> - 1
     */
     public   void  write ( char  x ,   int  r )   {
         if   ( ==   8 )   {
            write ( x );
             return ;
         }
         if   ( <   1   ||  r  >   16 )   throw   new   IllegalArgumentException ( "Illegal value for r = "   +  r );
         if   ( >=   ( 1   <<  r ))     throw   new   IllegalArgumentException ( "Illegal "   +  r  +   "-bit char = "   +  x );
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
             boolean  bit  =   (( >>>   ( -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }

    /**
     * Writes the string of 8-bit characters to the binary output stream.
     *
     *  @param   s the { @code  String} to write
     *  @throws  IllegalArgumentException if any character in the string is not
     *         between 0 and 255
     */
     public   void  write ( String  s )   {
         for   ( int  i  =   0 ;  i  <  s . length ();  i ++ )
            write ( s . charAt ( i ));
     }


    /**
     * Writes the string of r-bit characters to the binary output stream.
     *  @param   s the { @code  String} to write
     *  @param   r the number of relevants bits in each character
     *  @throws  IllegalArgumentException unless r is between 1 and 16
     *  @throws  IllegalArgumentException if any character in the string is not
     *         between 0 and 2<sup>r</sup> - 1
     */
     public   void  write ( String  s ,   int  r )   {
         for   ( int  i  =   0 ;  i  <  s . length ();  i ++ )
            write ( s . charAt ( i ),  r );
     }


    /**
     * Test client. Read bits from standard input and write to the file
     * specified on command line.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         // create binary output stream to write to file
         String  filename  =  args [ 0 ];
         BinaryOut  out  =   new   BinaryOut ( filename );
         BinaryIn   in   =   new   BinaryIn ();

         // read from standard input and write to file
         while   ( ! in . isEmpty ())   {
             char  c  =  in . readChar ();
            out . write ( c );
         }
        out . flush ();
     }

}

BinaryStdIn.java

BinaryStdIn.java

/******************************************************************************
 *  Compilation:  javac BinaryStdIn.java
 *  Execution:    java BinaryStdIn < input > output
 *  Dependencies: none             
 *  
 *  Supports reading binary data from standard input.
 *
 *  % java BinaryStdIn < input.jpg > output.jpg
 *  % diff input.jpg output.jpg
 *
 ******************************************************************************/

import  java . io . BufferedInputStream ;
import  java . io . IOException ;
import  java . util . NoSuchElementException ;

/**
 *  <i>Binary standard input</i>. This class provides methods for reading
 *  in bits from standard input, either one bit at a time (as a { @code  boolean}),
 *  8 bits at a time (as a { @code  byte} or { @code  char}),
 *  16 bits at a time (as a { @code  short}), 32 bits at a time
 *  (as an { @code  int} or { @code  float}), or 64 bits at a time (as a
 *  { @code  double} or { @code  long}).
 *  <p>
 *  All primitive types are assumed to be represented using their 
 *  standard Java representations, in big-endian (most significant
 *  byte first) order.
 *  <p>
 *  The client should not intermix calls to { @code  BinaryStdIn} with calls
 *  to { @code  StdIn} or { @code  System.in};
 *  otherwise unexpected behavior will result.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   BinaryStdIn   {
     private   static   final   int  EOF  =   - 1 ;        // end of file

     private   static   BufferedInputStream  in ;    // input stream
     private   static   int  buffer ;                // one character buffer
     private   static   int  n ;                     // number of bits left in buffer
     private   static   boolean  isInitialized ;     // has BinaryStdIn been called for first time?

     // don't instantiate
     private   BinaryStdIn ()   {   }

     // fill buffer
     private   static   void  initialize ()   {
        in  =   new   BufferedInputStream ( System . in );
        buffer  =   0 ;
        n  =   0 ;
        fillBuffer ();
        isInitialized  =   true ;
     }

     private   static   void  fillBuffer ()   {
         try   {
            buffer  =  in . read ();
            n  =   8 ;
         }
         catch   ( IOException  e )   {
             System . out . println ( "EOF" );
            buffer  =  EOF ;
            n  =   - 1 ;
         }
     }

    /**
     * Close this input stream and release any associated system resources.
     */
     public   static   void  close ()   {
         if   ( ! isInitialized )  initialize ();
         try   {
            in . close ();
            isInitialized  =   false ;
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalStateException ( "Could not close BinaryStdIn" ,  ioe );
         }
     }

    /**
     * Returns true if standard input is empty.
     *  @return  true if and only if standard input is empty
     */
     public   static   boolean  isEmpty ()   {
         if   ( ! isInitialized )  initialize ();
         return  buffer  ==  EOF ;
     }

    /**
     * Reads the next bit of data from standard input and return as a boolean.
     *
     *  @return  the next bit of data from standard input as a { @code  boolean}
     *  @throws  NoSuchElementException if standard input is empty
     */
     public   static   boolean  readBoolean ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );
        n -- ;
         boolean  bit  =   (( buffer  >>  n )   &   1 )   ==   1 ;
         if   ( ==   0 )  fillBuffer ();
         return  bit ;
     }

    /**
     * Reads the next 8 bits from standard input and return as an 8-bit char.
     * Note that { @code  char} is a 16-bit type;
     * to read the next 16 bits as a char, use { @code  readChar(16)}.
     *
     *  @return  the next 8 bits of data from standard input as a { @code  char}
     *  @throws  NoSuchElementException if there are fewer than 8 bits available on standard input
     */
     public   static   char  readChar ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );

         // special case when aligned byte
         if   ( ==   8 )   {
             int  x  =  buffer ;
            fillBuffer ();
             return   ( char )   ( &   0xff );
         }

         // combine last n bits of current buffer with first 8-n bits of new buffer
         int  x  =  buffer ;
        x  <<=   ( 8   -  n );
         int  oldN  =  n ;
        fillBuffer ();
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );
        n  =  oldN ;
        x  |=   ( buffer  >>>  n );
         return   ( char )   ( &   0xff );
         // the above code doesn't quite work for the last character if n = 8
         // because buffer will be -1, so there is a special case for aligned byte
     }

    /**
     * Reads the next r bits from standard input and return as an r-bit character.
     *
     *  @param   r number of bits to read.
     *  @return  the next r bits of data from standard input as a { @code  char}
     *  @throws  NoSuchElementException if there are fewer than { @code  r} bits available on standard input
     *  @throws  IllegalArgumentException unless { @code  1 <= r <= 16}
     */
     public   static   char  readChar ( int  r )   {
         if   ( <   1   ||  r  >   16 )   throw   new   IllegalArgumentException ( "Illegal value of r = "   +  r );

         // optimize r = 8 case
         if   ( ==   8 )   return  readChar ();

         char  x  =   0 ;
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
            x  <<=   1 ;
             boolean  bit  =  readBoolean ();
             if   ( bit )  x  |=   1 ;
         }
         return  x ;
     }

    /**
     * Reads the remaining bytes of data from standard input and return as a string. 
     *
     *  @return  the remaining bytes of data from standard input as a { @code  String}
     *  @throws  NoSuchElementException if standard input is empty or if the number of bits
     *         available on standard input is not a multiple of 8 (byte-aligned)
     */
     public   static   String  readString ()   {
         if   ( isEmpty ())   throw   new   NoSuchElementException ( "Reading from empty input stream" );

         StringBuilder  sb  =   new   StringBuilder ();
         while   ( ! isEmpty ())   {
             char  c  =  readChar ();
            sb . append ( c );
         }
         return  sb . toString ();
     }


    /**
     * Reads the next 16 bits from standard input and return as a 16-bit short.
     *
     *  @return  the next 16 bits of data from standard input as a { @code  short}
     *  @throws  NoSuchElementException if there are fewer than 16 bits available on standard input
     */
     public   static   short  readShort ()   {
         short  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   2 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }

    /**
     * Reads the next 32 bits from standard input and return as a 32-bit int.
     *
     *  @return  the next 32 bits of data from standard input as a { @code  int}
     *  @throws  NoSuchElementException if there are fewer than 32 bits available on standard input
     */
     public   static   int  readInt ()   {
         int  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   4 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }

    /**
     * Reads the next r bits from standard input and return as an r-bit int.
     *
     *  @param   r number of bits to read.
     *  @return  the next r bits of data from standard input as a { @code  int}
     *  @throws  NoSuchElementException if there are fewer than { @code  r} bits available on standard input
     *  @throws  IllegalArgumentException unless { @code  1 <= r <= 32}
     */
     public   static   int  readInt ( int  r )   {
         if   ( <   1   ||  r  >   32 )   throw   new   IllegalArgumentException ( "Illegal value of r = "   +  r );

         // optimize r = 32 case
         if   ( ==   32 )   return  readInt ();

         int  x  =   0 ;
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
            x  <<=   1 ;
             boolean  bit  =  readBoolean ();
             if   ( bit )  x  |=   1 ;
         }
         return  x ;
     }

    /**
     * Reads the next 64 bits from standard input and return as a 64-bit long.
     *
     *  @return  the next 64 bits of data from standard input as a { @code  long}
     *  @throws  NoSuchElementException if there are fewer than 64 bits available on standard input
     */
     public   static   long  readLong ()   {
         long  x  =   0 ;
         for   ( int  i  =   0 ;  i  <   8 ;  i ++ )   {
             char  c  =  readChar ();
            x  <<=   8 ;
            x  |=  c ;
         }
         return  x ;
     }


    /**
     * Reads the next 64 bits from standard input and return as a 64-bit double.
     *
     *  @return  the next 64 bits of data from standard input as a { @code  double}
     *  @throws  NoSuchElementException if there are fewer than 64 bits available on standard input
     */
     public   static   double  readDouble ()   {
         return   Double . longBitsToDouble ( readLong ());
     }

    /**
     * Reads the next 32 bits from standard input and return as a 32-bit float.
     *
     *  @return  the next 32 bits of data from standard input as a { @code  float}
     *  @throws  NoSuchElementException if there are fewer than 32 bits available on standard input
     */
     public   static   float  readFloat ()   {
         return   Float . intBitsToFloat ( readInt ());
     }


    /**
     * Reads the next 8 bits from standard input and return as an 8-bit byte.
     *
     *  @return  the next 8 bits of data from standard input as a { @code  byte}
     *  @throws  NoSuchElementException if there are fewer than 8 bits available on standard input
     */
     public   static   byte  readByte ()   {
         char  c  =  readChar ();
         return   ( byte )   ( &   0xff );
     }
    
    /**
     * Test client. Reads in a binary input file from standard input and writes
     * it to standard output.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         // read one 8-bit char at a time
         while   ( ! BinaryStdIn . isEmpty ())   {
             char  c  =   BinaryStdIn . readChar ();
             BinaryStdOut . write ( c );
         }
         BinaryStdOut . flush ();
     }
}

BinaryStdOut.java

BinaryStdOut.java

/******************************************************************************
 *  Compilation:  javac BinaryStdOut.java
 *  Execution:    java BinaryStdOut
 *  Dependencies: none
 *
 *  Write binary data to standard output, either one 1-bit boolean,
 *  one 8-bit char, one 32-bit int, one 64-bit double, one 32-bit float,
 *  or one 64-bit long at a time.
 *
 *  The bytes written are not aligned.
 *
 ******************************************************************************/

import  java . io . BufferedOutputStream ;
import  java . io . IOException ;

/**
 *  <i>Binary standard output</i>. This class provides methods for converting
 *  primtive type variables ({ @code  boolean}, { @code  byte}, { @code  char},
 *  { @code  int}, { @code  long}, { @code  float}, and { @code  double})
 *  to sequences of bits and writing them to standard output.
 *  Uses big-endian (most-significant byte first).
 *  <p>
 *  The client must { @code  flush()} the output stream when finished writing bits.
 *  <p>
 *  The client should not intermix calls to { @code  BinaryStdOut} with calls
 *  to { @code  StdOut} or { @code  System.out}; otherwise unexpected behavior 
 *  will result.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   BinaryStdOut   {
     private   static   BufferedOutputStream  out ;    // output stream (standard output)
     private   static   int  buffer ;                  // 8-bit buffer of bits to write
     private   static   int  n ;                       // number of bits remaining in buffer
     private   static   boolean  isInitialized ;       // has BinaryStdOut been called for first time?

     // don't instantiate
     private   BinaryStdOut ()   {   }

     // initialize BinaryStdOut
     private   static   void  initialize ()   {
        out  =   new   BufferedOutputStream ( System . out );
        buffer  =   0 ;
        n  =   0 ;
        isInitialized  =   true ;
     }

    /**
     * Writes the specified bit to standard output.
     */
     private   static   void  writeBit ( boolean  bit )   {
         if   ( ! isInitialized )  initialize ();

         // add bit to buffer
        buffer  <<=   1 ;
         if   ( bit )  buffer  |=   1 ;

         // if buffer is full (8 bits), write out as a single byte
        n ++ ;
         if   ( ==   8 )  clearBuffer ();
     }  

    /**
     * Writes the 8-bit byte to standard output.
     */
     private   static   void  writeByte ( int  x )   {
         if   ( ! isInitialized )  initialize ();

         assert  x  >=   0   &&  x  <   256 ;

         // optimized if byte-aligned
         if   ( ==   0 )   {
             try   {
                out . write ( x );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
             return ;
         }

         // otherwise write one bit at a time
         for   ( int  i  =   0 ;  i  <   8 ;  i ++ )   {
             boolean  bit  =   (( >>>   ( 8   -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }

     // write out any remaining bits in buffer to standard output, padding with 0s
     private   static   void  clearBuffer ()   {
         if   ( ! isInitialized )  initialize ();

         if   ( ==   0 )   return ;
         if   ( >   0 )  buffer  <<=   ( 8   -  n );
         try   {
            out . write ( buffer );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
        n  =   0 ;
        buffer  =   0 ;
     }

    /**
     * Flushes standard output, padding 0s if number of bits written so far
     * is not a multiple of 8.
     */
     public   static   void  flush ()   {
        clearBuffer ();
         try   {
            out . flush ();
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Flushes and closes standard output. Once standard output is closed, you can no
     * longer write bits to it.
     */
     public   static   void  close ()   {
        flush ();
         try   {
            out . close ();
            isInitialized  =   false ;
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }


    /**
     * Writes the specified bit to standard output.
     *  @param  x the { @code  boolean} to write.
     */
     public   static   void  write ( boolean  x )   {
        writeBit ( x );
     }  

    /**
     * Writes the 8-bit byte to standard output.
     *  @param  x the { @code  byte} to write.
     */
     public   static   void  write ( byte  x )   {
        writeByte ( &   0xff );
     }

    /**
     * Writes the 32-bit int to standard output.
     *  @param  x the { @code  int} to write.
     */
     public   static   void  write ( int  x )   {
        writeByte (( >>>   24 )   &   0xff );
        writeByte (( >>>   16 )   &   0xff );
        writeByte (( >>>    8 )   &   0xff );
        writeByte (( >>>    0 )   &   0xff );
     }

    /**
     * Writes the r-bit int to standard output.
     *  @param  x the { @code  int} to write.
     *  @param  r the number of relevant bits in the char.
     *  @throws  IllegalArgumentException if { @code  r} is not between 1 and 32.
     *  @throws  IllegalArgumentException if { @code  x} is not between 0 and 2<sup>r</sup> - 1.
     */
     public   static   void  write ( int  x ,   int  r )   {
         if   ( ==   32 )   {
            write ( x );
             return ;
         }
         if   ( <   1   ||  r  >   32 )          throw   new   IllegalArgumentException ( "Illegal value for r = "   +  r );
         if   ( <   0   ||  x  >=   ( 1   <<  r ))   throw   new   IllegalArgumentException ( "Illegal "   +  r  +   "-bit char = "   +  x );
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
             boolean  bit  =   (( >>>   ( -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }





    /**
     * Writes the 64-bit double to standard output.
     *  @param  x the { @code  double} to write.
     */
     public   static   void  write ( double  x )   {
        write ( Double . doubleToRawLongBits ( x ));
     }

    /**
     * Writes the 64-bit long to standard output.
     *  @param  x the { @code  long} to write.
     */
     public   static   void  write ( long  x )   {
        writeByte (( int )   (( >>>   56 )   &   0xff ));
        writeByte (( int )   (( >>>   48 )   &   0xff ));
        writeByte (( int )   (( >>>   40 )   &   0xff ));
        writeByte (( int )   (( >>>   32 )   &   0xff ));
        writeByte (( int )   (( >>>   24 )   &   0xff ));
        writeByte (( int )   (( >>>   16 )   &   0xff ));
        writeByte (( int )   (( >>>    8 )   &   0xff ));
        writeByte (( int )   (( >>>    0 )   &   0xff ));
     }

    /**
     * Writes the 32-bit float to standard output.
     *  @param  x the { @code  float} to write.
     */
     public   static   void  write ( float  x )   {
        write ( Float . floatToRawIntBits ( x ));
     }

    /**
     * Writes the 16-bit int to standard output.
     *  @param  x the { @code  short} to write.
     */
     public   static   void  write ( short  x )   {
        writeByte (( >>>    8 )   &   0xff );
        writeByte (( >>>    0 )   &   0xff );
     }

    /**
     * Writes the 8-bit char to standard output.
     *  @param  x the { @code  char} to write.
     *  @throws  IllegalArgumentException if { @code  x} is not betwen 0 and 255.
     */
     public   static   void  write ( char  x )   {
         if   ( <   0   ||  x  >=   256 )   throw   new   IllegalArgumentException ( "Illegal 8-bit char = "   +  x );
        writeByte ( x );
     }

    /**
     * Writes the r-bit char to standard output.
     *  @param  x the { @code  char} to write.
     *  @param  r the number of relevant bits in the char.
     *  @throws  IllegalArgumentException if { @code  r} is not between 1 and 16.
     *  @throws  IllegalArgumentException if { @code  x} is not between 0 and 2<sup>r</sup> - 1.
     */
     public   static   void  write ( char  x ,   int  r )   {
         if   ( ==   8 )   {
            write ( x );
             return ;
         }
         if   ( <   1   ||  r  >   16 )   throw   new   IllegalArgumentException ( "Illegal value for r = "   +  r );
         if   ( >=   ( 1   <<  r ))     throw   new   IllegalArgumentException ( "Illegal "   +  r  +   "-bit char = "   +  x );
         for   ( int  i  =   0 ;  i  <  r ;  i ++ )   {
             boolean  bit  =   (( >>>   ( -  i  -   1 ))   &   1 )   ==   1 ;
            writeBit ( bit );
         }
     }

    /**
     * Writes the string of 8-bit characters to standard output.
     *  @param  s the { @code  String} to write.
     *  @throws  IllegalArgumentException if any character in the string is not
     * between 0 and 255.
     */
     public   static   void  write ( String  s )   {
         for   ( int  i  =   0 ;  i  <  s . length ();  i ++ )
            write ( s . charAt ( i ));
     }

    /**
     * Writes the string of r-bit characters to standard output.
     *  @param  s the { @code  String} to write.
     *  @param  r the number of relevants bits in each character.
     *  @throws  IllegalArgumentException if r is not between 1 and 16.
     *  @throws  IllegalArgumentException if any character in the string is not
     * between 0 and 2<sup>r</sup> - 1.
     */
     public   static   void  write ( String  s ,   int  r )   {
         for   ( int  i  =   0 ;  i  <  s . length ();  i ++ )
            write ( s . charAt ( i ),  r );
     }

    /**
     * Tests the methods in this class.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         int  m  =   Integer . parseInt ( args [ 0 ]);

         // write n integers to binary standard output
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             BinaryStdOut . write ( i );
         }
         BinaryStdOut . flush ();
     }

}

Draw.java

Draw.java

/******************************************************************************
 *  Compilation:  javac Draw.java
 *  Execution:    java Draw
 *  Dependencies: none
 *
 *  Drawing library. This class provides a basic capability for creating
 *  drawings with your programs. It uses a simple graphics model that
 *  allows you to create drawings consisting of points, lines, and curves
 *  in a window on your computer and to save the drawings to a file.
 *  This is the object-oriented version of standard draw; it supports
 *  multiple indepedent drawing windows.
 *
 *  Todo
 *  ----
 *    -  Add support for gradient fill, etc.
 *
 *  Remarks
 *  -------
 *    -  don't use AffineTransform for rescaling since it inverts
 *       images and strings
 *    -  careful using setFont in inner loop within an animation -
 *       it can cause flicker
 *
 ******************************************************************************/

import  java . awt . BasicStroke ;
import  java . awt . Color ;
import  java . awt . Component ;
import  java . awt . FileDialog ;
import  java . awt . Font ;
import  java . awt . FontMetrics ;
import  java . awt . Graphics ;
import  java . awt . Graphics2D ;
import  java . awt . Image ;
import  java . awt . MediaTracker ;
import  java . awt . RenderingHints ;
import  java . awt . Toolkit ;

import  java . awt . event . ActionEvent ;
import  java . awt . event . ActionListener ;
import  java . awt . event . MouseEvent ;
import  java . awt . event . MouseListener ;
import  java . awt . event . MouseMotionListener ;
import  java . awt . event . KeyEvent ;
import  java . awt . event . KeyListener ;

import  java . awt . geom . Arc2D ;
import  java . awt . geom . Ellipse2D ;
import  java . awt . geom . GeneralPath ;
import  java . awt . geom . Line2D ;
import  java . awt . geom . Rectangle2D ;

import  java . awt . image . BufferedImage ;
import  java . awt . image . DirectColorModel ;
import  java . awt . image . WritableRaster ;

import  java . io . File ;
import  java . io . IOException ;

import  java . net . MalformedURLException ;
import  java . net . URL ;

import  java . util . ArrayList ;
import  java . util . LinkedList ;
import  java . util . TreeSet ;

import  javax . imageio . ImageIO ;

import  javax . swing . ImageIcon ;
import  javax . swing . JFrame ;
import  javax . swing . JLabel ;
import  javax . swing . JMenu ;
import  javax . swing . JMenuBar ;
import  javax . swing . JMenuItem ;
import  javax . swing . KeyStroke ;

/**
 *  <i>Draw</i>. This class provides a basic capability for
 *  creating drawings with your programs. It uses a simple graphics model that
 *  allows you to create drawings consisting of points, lines, and curves
 *  in a window on your computer and to save the drawings to a file.
 *  This is the object-oriented version of standard draw; it supports
 *  multiple indepedent drawing windows.
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   Draw   implements   ActionListener ,   MouseListener ,   MouseMotionListener ,   KeyListener   {

     /**
     *  The color black.
     */
     public   static   final   Color  BLACK  =   Color . BLACK ;

     /**
     *  The color blue.
     */
     public   static   final   Color  BLUE  =   Color . BLUE ;

     /**
     *  The color cyan.
     */
     public   static   final   Color  CYAN  =   Color . CYAN ;

     /**
     *  The color dark gray.
     */
     public   static   final   Color  DARK_GRAY  =   Color . DARK_GRAY ;

     /**
     *  The color gray.
     */
     public   static   final   Color  GRAY  =   Color . GRAY ;

     /**
     *  The color green.
     */
     public   static   final   Color  GREEN   =   Color . GREEN ;

     /**
     *  The color light gray.
     */
     public   static   final   Color  LIGHT_GRAY  =   Color . LIGHT_GRAY ;

     /**
     *  The color magenta.
     */
     public   static   final   Color  MAGENTA  =   Color . MAGENTA ;

     /**
     *  The color orange.
     */
     public   static   final   Color  ORANGE  =   Color . ORANGE ;

     /**
     *  The color pink.
     */
     public   static   final   Color  PINK  =   Color . PINK ;

     /**
     *  The color red.
     */
     public   static   final   Color  RED  =   Color . RED ;

     /**
     *  The color white.
     */
     public   static   final   Color  WHITE  =   Color . WHITE ;

     /**
     *  The color yellow.
     */
     public   static   final   Color  YELLOW  =   Color . YELLOW ;

     /**
     * Shade of blue used in Introduction to Programming in Java.
     * It is Pantone 300U. The RGB values are approximately (9, 90, 166).
     */
     public   static   final   Color  BOOK_BLUE  =   new   Color ( 9 ,   90 ,   166 );

     /**
     * Shade of light blue used in Introduction to Programming in Java.
     * The RGB values are approximately (103, 198, 243).
     */
     public   static   final   Color  BOOK_LIGHT_BLUE  =   new   Color ( 103 ,   198 ,   243 );
    
     /**
     * Shade of red used in <em>Algorithms, 4th edition</em>.
     * It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
     */
     public   static   final   Color  BOOK_RED  =   new   Color ( 150 ,   35 ,   31 );

     /**
     * Shade of orange used in Princeton's identity.
     * It is PMS 158. The RGB values are approximately (245, 128, 37).
     */
     public   static   final   Color  PRINCETON_ORANGE  =   new   Color ( 245 ,   128 ,   37 );

     // default colors
     private   static   final   Color  DEFAULT_PEN_COLOR    =  BLACK ;
     private   static   final   Color  DEFAULT_CLEAR_COLOR  =  WHITE ;

     // boundary of drawing canvas, 0% border
     private   static   final   double  BORDER  =   0.0 ;
     private   static   final   double  DEFAULT_XMIN  =   0.0 ;
     private   static   final   double  DEFAULT_XMAX  =   1.0 ;
     private   static   final   double  DEFAULT_YMIN  =   0.0 ;
     private   static   final   double  DEFAULT_YMAX  =   1.0 ;

     // default canvas size is SIZE-by-SIZE
     private   static   final   int  DEFAULT_SIZE  =   512 ;

     // default pen radius
     private   static   final   double  DEFAULT_PEN_RADIUS  =   0.002 ;

     // default font
     private   static   final   Font  DEFAULT_FONT  =   new   Font ( "SansSerif" ,   Font . PLAIN ,   16 );

     // current pen color
     private   Color  penColor ;

     // canvas size
     private   int  width   =  DEFAULT_SIZE ;
     private   int  height  =  DEFAULT_SIZE ;

     // current pen radius
     private   double  penRadius ;

     // show we draw immediately or wait until next show?
     private   boolean  defer  =   false ;

     private   double  xmin ,  ymin ,  xmax ,  ymax ;

     // name of window
     private   String  name  =   "Draw" ;

     // for synchronization
     private   final   Object  mouseLock  =   new   Object ();
     private   final   Object  keyLock  =   new   Object ();

     // current font
     private   Font  font ;

     // the JLabel for drawing
     private   JLabel  draw ;

     // double buffered graphics
     private   BufferedImage  offscreenImage ,  onscreenImage ;
     private   Graphics2D  offscreen ,  onscreen ;

     // the frame for drawing to the screen
     private   JFrame  frame  =   new   JFrame ();

     // mouse state
     private   boolean  isMousePressed  =   false ;
     private   double  mouseX  =   0 ;
     private   double  mouseY  =   0 ;

     // keyboard state
     private   final   LinkedList < Character >  keysTyped  =   new   LinkedList < Character > ();
     private   final   TreeSet < Integer >  keysDown  =   new   TreeSet < Integer > ();

     // event-based listeners
     private   final   ArrayList < DrawListener >  listeners  =   new   ArrayList < DrawListener > ();


     /**
     * Initializes an empty drawing object with the given name.
     *
     *  @param  name the title of the drawing window.
     */
     public   Draw ( String  name )   {
         this . name  =  name ;
        init ();
     }

     /**
     * Initializes an empty drawing object.
     */
     public   Draw ()   {
        init ();
     }

     private   void  init ()   {
         if   ( frame  !=   null )  frame . setVisible ( false );
        frame  =   new   JFrame ();
        offscreenImage  =   new   BufferedImage ( 2 * width ,   2 * height ,   BufferedImage . TYPE_INT_ARGB );
        onscreenImage   =   new   BufferedImage ( 2 * width ,   2 * height ,   BufferedImage . TYPE_INT_ARGB );
        offscreen  =  offscreenImage . createGraphics ();
        onscreen   =  onscreenImage . createGraphics ();
        offscreen . scale ( 2.0 ,   2.0 );    // since we made it 2x as big

        setXscale ();
        setYscale ();
        offscreen . setColor ( DEFAULT_CLEAR_COLOR );
        offscreen . fillRect ( 0 ,   0 ,  width ,  height );
        setPenColor ();
        setPenRadius ();
        setFont ();
        clear ();

         // add antialiasing
         RenderingHints  hints  =   new   RenderingHints ( RenderingHints . KEY_ANTIALIASING ,
                                                   RenderingHints . VALUE_ANTIALIAS_ON );
        hints . put ( RenderingHints . KEY_RENDERING ,   RenderingHints . VALUE_RENDER_QUALITY );
        offscreen . addRenderingHints ( hints );

         // frame stuff
         RetinaImageIcon  icon  =   new   RetinaImageIcon ( onscreenImage );
        draw  =   new   JLabel ( icon );

        draw . addMouseListener ( this );
        draw . addMouseMotionListener ( this );

        frame . setContentPane ( draw );
        frame . addKeyListener ( this );      // JLabel cannot get keyboard focus
        frame . setResizable ( false );
         // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);            // closes all windows
        frame . setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE );        // closes only current window
        frame . setFocusTraversalKeysEnabled ( false );    // to recognize VK_TAB with isKeyPressed()
        frame . setTitle ( name );
        frame . setJMenuBar ( createMenuBar ());
        frame . pack ();
        frame . requestFocusInWindow ();
        frame . setVisible ( true );
     }


     /**
     * Sets the upper-left hand corner of the drawing window to be (x, y), where (0, 0) is upper left.
     *
     *  @param   x the number of pixels from the left
     *  @param   y the number of pixels from the top
     *  @throws  IllegalArgumentException if the width or height is 0 or negative
     */
     public   void  setLocationOnScreen ( int  x ,   int  y )   {
         if   ( <=   0   ||  y  <=   0 )   throw   new   IllegalArgumentException ();
        frame . setLocation ( x ,  y );
     }

     /**
     * Sets the default close operation.
     *
     *  @param   value the value, typically { @code  JFrame.EXIT_ON_CLOSE}
     *         (close all windows) or { @code  JFrame.DISPOSE_ON_CLOSE}
     *         (close current window)
     */
     public   void  setDefaultCloseOperation ( int  value )   {
        frame . setDefaultCloseOperation ( value );
     }
       

     /**
     * Sets the canvas (drawing area) to be <em>width</em>-by-<em>height</em> pixels.
     * This also erases the current drawing and resets the coordinate system, pen radius,
     * pen color, and font back to their default values.
     * Ordinarly, this method is called once, at the very beginning of a program.
     *
     *  @param   canvasWidth the width as a number of pixels
     *  @param   canvasHeight the height as a number of pixels
     *  @throws  IllegalArgumentException unless both { @code  canvasWidth}
     *         and { @code  canvasHeight} are positive
     */
     public   void  setCanvasSize ( int  canvasWidth ,   int  canvasHeight )   {
         if   ( canvasWidth  <   1   ||  canvasHeight  <   1 )   {
             throw   new   IllegalArgumentException ( "width and height must be positive" );
         }
        width  =  canvasWidth ;
        height  =  canvasHeight ;
        init ();
     }


     // create the menu bar (changed to private)
     private   JMenuBar  createMenuBar ()   {
         JMenuBar  menuBar  =   new   JMenuBar ();
         JMenu  menu  =   new   JMenu ( "File" );
        menuBar . add ( menu );
         JMenuItem  menuItem1  =   new   JMenuItem ( " Save...   " );
        menuItem1 . addActionListener ( this );
         // Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
        menuItem1 . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_S ,
                                 Toolkit . getDefaultToolkit (). getMenuShortcutKeyMask ()));
        menu . add ( menuItem1 );
         return  menuBar ;
     }


    /***************************************************************************
    *  User and screen coordinate systems.
    ***************************************************************************/

     // throw an IllegalArgumentException if x is NaN or infinite
     private   static   void  validate ( double  x ,   String  name )   {
         if   ( Double . isNaN ( x ))   throw   new   IllegalArgumentException ( name  +   " is NaN" );
         if   ( Double . isInfinite ( x ))   throw   new   IllegalArgumentException ( name  +   " is infinite" );
     }

     // throw an IllegalArgumentException if s is null
     private   static   void  validateNonnegative ( double  x ,   String  name )   {
         if   ( <   0 )   throw   new   IllegalArgumentException ( name  +   " negative" );
     }

     // throw an IllegalArgumentException if s is null
     private   static   void  validateNotNull ( Object  x ,   String  name )   {
         if   ( ==   null )   throw   new   IllegalArgumentException ( name  +   " is null" );
     }

     /**
     * Sets the x-scale to be the default (between 0.0 and 1.0).
     */
     public   void  setXscale ()   {
        setXscale ( DEFAULT_XMIN ,  DEFAULT_XMAX );
     }

     /**
     * Sets the y-scale to be the default (between 0.0 and 1.0).
     */
     public   void  setYscale ()   {
        setYscale ( DEFAULT_YMIN ,  DEFAULT_YMAX );
     }

     /**
     * Sets the x-scale.
     *
     *  @param  min the minimum value of the x-scale
     *  @param  max the maximum value of the x-scale
     *  @throws  IllegalArgumentException if { @code  (max == min)}
     *  @throws  IllegalArgumentException if either { @code  min} or { @code  max} is either NaN or infinite
     */
     public   void  setXscale ( double  min ,   double  max )   {
        validate ( min ,   "min" );
        validate ( max ,   "max" );
         double  size  =  max  -  min ;
         if   ( size  ==   0.0 )   throw   new   IllegalArgumentException ( "the min and max are the same" );
        xmin  =  min  -  BORDER  *  size ;
        xmax  =  max  +  BORDER  *  size ;
     }

     /**
     * Sets the y-scale.
     *
     *  @param  min the minimum value of the y-scale
     *  @param  max the maximum value of the y-scale
     *  @throws  IllegalArgumentException if { @code  (max == min)}
     *  @throws  IllegalArgumentException if either { @code  min} or { @code  max} is either NaN or infinite
     */
     public   void  setYscale ( double  min ,   double  max )   {
        validate ( min ,   "min" );
        validate ( max ,   "max" );
         double  size  =  max  -  min ;
         if   ( size  ==   0.0 )   throw   new   IllegalArgumentException ( "the min and max are the same" );
        ymin  =  min  -  BORDER  *  size ;
        ymax  =  max  +  BORDER  *  size ;
     }

     // helper functions that scale from user coordinates to screen coordinates and back
     private   double   scaleX ( double  x )   {   return  width   *   ( -  xmin )   /   ( xmax  -  xmin );   }
     private   double   scaleY ( double  y )   {   return  height  *   ( ymax  -  y )   /   ( ymax  -  ymin );   }
     private   double  factorX ( double  w )   {   return  w  *  width   /   Math . abs ( xmax  -  xmin );    }
     private   double  factorY ( double  h )   {   return  h  *  height  /   Math . abs ( ymax  -  ymin );    }
     private   double    userX ( double  x )   {   return  xmin  +  x  *   ( xmax  -  xmin )   /  width ;      }
     private   double    userY ( double  y )   {   return  ymax  -  y  *   ( ymax  -  ymin )   /  height ;     }


     /**
     * Clears the screen to the default color (white).
     */
     public   void  clear ()   {
        clear ( DEFAULT_CLEAR_COLOR );
     }

     /**
     * Clears the screen to the given color.
     *
     *  @param  color the color to make the background
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   void  clear ( Color  color )   {
        validateNotNull ( color ,   "color" );
        offscreen . setColor ( color );
        offscreen . fillRect ( 0 ,   0 ,  width ,  height );
        offscreen . setColor ( penColor );
        draw ();
     }

     /**
     * Gets the current pen radius.
     *
     *  @return  the current pen radius
     */
     public   double  getPenRadius ()   {
         return  penRadius ;
     }

     /**
     * Sets the pen size to the default (.002).
     */
     public   void  setPenRadius ()   {
        setPenRadius ( DEFAULT_PEN_RADIUS );
     }

     /**
     * Sets the radius of the pen to the given size.
     *
     *  @param   radius the radius of the pen
     *  @throws  IllegalArgumentException if { @code  radius} is negative, NaN, or infinite
     */
     public   void  setPenRadius ( double  radius )   {
        validate ( radius ,   "pen radius" );
        validateNonnegative ( radius ,   "pen radius" );

        penRadius  =  radius  *  DEFAULT_SIZE ;
         BasicStroke  stroke  =   new   BasicStroke (( float )  penRadius ,   BasicStroke . CAP_ROUND ,   BasicStroke . JOIN_ROUND );
         // BasicStroke stroke = new BasicStroke((float) penRadius);
        offscreen . setStroke ( stroke );
     }

     /**
     * Gets the current pen color.
     *
     *  @return  the current pen color
     */
     public   Color  getPenColor ()   {
         return  penColor ;
     }

     /**
     * Sets the pen color to the default color (black).
     */
     public   void  setPenColor ()   {
        setPenColor ( DEFAULT_PEN_COLOR );
     }

     /**
     * Sets the pen color to the given color.
     *
     *  @param  color the color to make the pen
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   void  setPenColor ( Color  color )   {
        validateNotNull ( color ,   "color" );
        penColor  =  color ;
        offscreen . setColor ( penColor );
     }

     /**
     * Sets the pen color to the given RGB color.
     *
     *  @param   red the amount of red (between 0 and 255)
     *  @param   green the amount of green (between 0 and 255)
     *  @param   blue the amount of blue (between 0 and 255)
     *  @throws  IllegalArgumentException if { @code  red}, { @code  green},
     *         or { @code  blue} is outside its prescribed range
     */
     public   void  setPenColor ( int  red ,   int  green ,   int  blue )   {
         if   ( red    <   0   ||  red    >=   256 )   throw   new   IllegalArgumentException ( "red must be between 0 and 255" );
         if   ( green  <   0   ||  green  >=   256 )   throw   new   IllegalArgumentException ( "green must be between 0 and 255" );
         if   ( blue   <   0   ||  blue   >=   256 )   throw   new   IllegalArgumentException ( "blue must be between 0 and 255" );
        setPenColor ( new   Color ( red ,  green ,  blue ));
     }


     /**
     * Turns on xor mode.
     */
     public   void  xorOn ()   {
        offscreen . setXORMode ( DEFAULT_CLEAR_COLOR );
     }

     /**
     * Turns off xor mode.
     */
     public   void  xorOff ()   {
        offscreen . setPaintMode ();
     }

     /**
     * Gets the current { @code  JLabel} for use in some other GUI.
     *
     *  @return  the current { @code  JLabel}
     */
     public   JLabel  getJLabel ()   {
         return  draw ;
     }

     /**
     * Gets the current font.
     *
     *  @return  the current font
     */
     public   Font  getFont ()   {
         return  font ;
     }

     /**
     * Sets the font to the default font (sans serif, 16 point).
     */
     public   void  setFont ()   {
        setFont ( DEFAULT_FONT );
     }

     /**
     * Sets the font to the given value.
     *
     *  @param  font the font
     *  @throws  IllegalArgumentException if { @code  font} is { @code  null}
     */
     public   void  setFont ( Font  font )   {
        validateNotNull ( font ,   "font" );
         this . font  =  font ;
     }


    /***************************************************************************
    *  Drawing geometric shapes.
    ***************************************************************************/

     /**
     * Draws a line from (x0, y0) to (x1, y1).
     *
     *  @param  x0 the x-coordinate of the starting point
     *  @param  y0 the y-coordinate of the starting point
     *  @param  x1 the x-coordinate of the destination point
     *  @param  y1 the y-coordinate of the destination point
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     */
     public   void  line ( double  x0 ,   double  y0 ,   double  x1 ,   double  y1 )   {
        validate ( x0 ,   "x0" );
        validate ( y0 ,   "y0" );
        validate ( x1 ,   "x1" );
        validate ( y1 ,   "y1" );
        offscreen . draw ( new   Line2D . Double ( scaleX ( x0 ),  scaleY ( y0 ),  scaleX ( x1 ),  scaleY ( y1 )));
        draw ();
     }

     /**
     * Draws one pixel at (x, y).
     *
     *  @param  x the x-coordinate of the pixel
     *  @param  y the y-coordinate of the pixel
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     private   void  pixel ( double  x ,   double  y )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        offscreen . fillRect (( int )   Math . round ( scaleX ( x )),   ( int )   Math . round ( scaleY ( y )),   1 ,   1 );
     }

     /**
     * Draws a point at (x, y).
     *
     *  @param  x the x-coordinate of the point
     *  @param  y the y-coordinate of the point
     *  @throws  IllegalArgumentException if either { @code  x} or { @code  y} is either NaN or infinite
     */
     public   void  point ( double  x ,   double  y )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  r  =  penRadius ;
         // double ws = factorX(2*r);
         // double hs = factorY(2*r);
         // if (ws <= 1 && hs <= 1) pixel(x, y);
         if   ( <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  r / 2 ,  ys  -  r / 2 ,  r ,  r ));
        draw ();
     }

     /**
     * Draws a circle of the specified radius, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the x-coordinate of the center of the circle
     *  @param   y the y-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  circle ( double  x ,   double  y ,   double  radius )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "radius" );
        validateNonnegative ( radius ,   "radius" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled circle of the specified radius, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the x-coordinate of the center of the circle
     *  @param   y the y-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  filledCircle ( double  x ,   double  y ,   double  radius )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "radius" );
        validateNonnegative ( radius ,   "radius" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws an ellipse with the specified semimajor and semiminor axes,
     * centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the ellipse
     *  @param   y the <em>y</em>-coordinate of the center of the ellipse
     *  @param   semiMajorAxis is the semimajor axis of the ellipse
     *  @param   semiMinorAxis is the semiminor axis of the ellipse
     *  @throws  IllegalArgumentException if either { @code  semiMajorAxis}
     *         or { @code  semiMinorAxis} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  ellipse ( double  x ,   double  y ,   double  semiMajorAxis ,   double  semiMinorAxis )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( semiMajorAxis ,   "semimajor axis" );
        validate ( semiMinorAxis ,   "semiminor axis" );
        validateNonnegative ( semiMajorAxis ,   "semimajor axis" );
        validateNonnegative ( semiMinorAxis ,   "semiminor axis" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * semiMajorAxis );
         double  hs  =  factorY ( 2 * semiMinorAxis );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled ellipse with the specified semimajor and semiminor axes,
     * centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the ellipse
     *  @param   y the <em>y</em>-coordinate of the center of the ellipse
     *  @param   semiMajorAxis is the semimajor axis of the ellipse
     *  @param   semiMinorAxis is the semiminor axis of the ellipse
     *  @throws  IllegalArgumentException if either { @code  semiMajorAxis}
     *         or { @code  semiMinorAxis} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  filledEllipse ( double  x ,   double  y ,   double  semiMajorAxis ,   double  semiMinorAxis )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( semiMajorAxis ,   "semimajor axis" );
        validate ( semiMinorAxis ,   "semiminor axis" );
        validateNonnegative ( semiMajorAxis ,   "semimajor axis" );
        validateNonnegative ( semiMinorAxis ,   "semiminor axis" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * semiMajorAxis );
         double  hs  =  factorY ( 2 * semiMinorAxis );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a circular arc of the specified radius,
     * centered at (<em>x</em>, <em>y</em>), from angle1 to angle2 (in degrees).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the circle
     *  @param   y the <em>y</em>-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @param   angle1 the starting angle. 0 would mean an arc beginning at 3 o'clock.
     *  @param   angle2 the angle at the end of the arc. For example, if
     *         you want a 90 degree arc, then angle2 should be angle1 + 90.
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  arc ( double  x ,   double  y ,   double  radius ,   double  angle1 ,   double  angle2 )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "arc radius" );
        validate ( angle1 ,   "angle1" );
        validate ( angle2 ,   "angle2" );
        validateNonnegative ( radius ,   "arc radius" );

         while   ( angle2  <  angle1 )  angle2  +=   360 ;
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Arc2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ,  angle1 ,  angle2  -  angle1 ,   Arc2D . OPEN ));
        draw ();
     }

     /**
     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the square
     *  @param   y the <em>y</em>-coordinate of the center of the square
     *  @param   halfLength one half the length of any side of the square
     *  @throws  IllegalArgumentException if { @code  halfLength} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  square ( double  x ,   double  y ,   double  halfLength )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfLength ,   "halfLength" );
        validateNonnegative ( halfLength ,   "half length" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfLength );
         double  hs  =  factorY ( 2 * halfLength );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the square
     *  @param   y the <em>y</em>-coordinate of the center of the square
     *  @param   halfLength one half the length of any side of the square
     *  @throws  IllegalArgumentException if { @code  halfLength} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  filledSquare ( double  x ,   double  y ,   double  halfLength )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfLength ,   "halfLength" );
        validateNonnegative ( halfLength ,   "half length" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfLength );
         double  hs  =  factorY ( 2 * halfLength );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws a rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the rectangle
     *  @param   y the <em>y</em>-coordinate of the center of the rectangle
     *  @param   halfWidth one half the width of the rectangle
     *  @param   halfHeight one half the height of the rectangle
     *  @throws  IllegalArgumentException if either { @code  halfWidth} or { @code  halfHeight} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  rectangle ( double  x ,   double  y ,   double  halfWidth ,   double  halfHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfWidth ,   "halfWidth" );
        validate ( halfHeight ,   "halfHeight" );
        validateNonnegative ( halfWidth ,   "half width" );
        validateNonnegative ( halfHeight ,   "half height" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfWidth );
         double  hs  =  factorY ( 2 * halfHeight );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the rectangle
     *  @param   y the <em>y</em>-coordinate of the center of the rectangle
     *  @param   halfWidth one half the width of the rectangle
     *  @param   halfHeight one half the height of the rectangle
     *  @throws  IllegalArgumentException if either { @code  halfWidth} or { @code  halfHeight} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   void  filledRectangle ( double  x ,   double  y ,   double  halfWidth ,   double  halfHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfWidth ,   "halfWidth" );
        validate ( halfHeight ,   "halfHeight" );
        validateNonnegative ( halfWidth ,   "half width" );
        validateNonnegative ( halfHeight ,   "half height" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfWidth );
         double  hs  =  factorY ( 2 * halfHeight );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a polygon with the vertices 
     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),
     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,
     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).
     *
     *  @param   x an array of all the <em>x</em>-coordinates of the polygon
     *  @param   y an array of all the <em>y</em>-coordinates of the polygon
     *  @throws  IllegalArgumentException unless { @code  x[]} and { @code  y[]}
     *         are of the same length
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     *  @throws  IllegalArgumentException if either { @code  x[]} or { @code  y[]} is { @code  null}
     */
     public   void  polygon ( double []  x ,   double []  y )   {
        validateNotNull ( x ,   "x-coordinate array" );
        validateNotNull ( y ,   "y-coordinate array" );
         for   ( int  i  =   0 ;  i  <  x . length ;  i ++ )  validate ( x [ i ],   "x["   +  i  +   "]" );
         for   ( int  i  =   0 ;  i  <  y . length ;  i ++ )  validate ( y [ i ],   "y["   +  i  +   "]" );

         int  n1  =  x . length ;
         int  n2  =  y . length ;
         if   ( n1  !=  n2 )   throw   new   IllegalArgumentException ( "arrays must be of the same length" );
         int  n  =  n1 ;
         if   ( ==   0 )   return ;

         GeneralPath  path  =   new   GeneralPath ();
        path . moveTo (( float )  scaleX ( x [ 0 ]),   ( float )  scaleY ( y [ 0 ]));
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )
            path . lineTo (( float )  scaleX ( x [ i ]),   ( float )  scaleY ( y [ i ]));
        path . closePath ();
        offscreen . draw ( path );
        draw ();
     }

     /**
     * Draws a filled polygon with the vertices 
     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),
     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,
     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).
     *
     *  @param   x an array of all the <em>x</em>-coordinates of the polygon
     *  @param   y an array of all the <em>y</em>-coordinates of the polygon
     *  @throws  IllegalArgumentException unless { @code  x[]} and { @code  y[]}
     *         are of the same length
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     *  @throws  IllegalArgumentException if either { @code  x[]} or { @code  y[]} is { @code  null}
     */
     public   void  filledPolygon ( double []  x ,   double []  y )   {
        validateNotNull ( x ,   "x-coordinate array" );
        validateNotNull ( y ,   "y-coordinate array" );
         for   ( int  i  =   0 ;  i  <  x . length ;  i ++ )  validate ( x [ i ],   "x["   +  i  +   "]" );
         for   ( int  i  =   0 ;  i  <  y . length ;  i ++ )  validate ( y [ i ],   "y["   +  i  +   "]" );

         int  n1  =  x . length ;
         int  n2  =  y . length ;
         if   ( n1  !=  n2 )   throw   new   IllegalArgumentException ( "arrays must be of the same length" );
         int  n  =  n1 ;
         if   ( ==   0 )   return ;

         GeneralPath  path  =   new   GeneralPath ();
        path . moveTo (( float )  scaleX ( x [ 0 ]),   ( float )  scaleY ( y [ 0 ]));
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )
            path . lineTo (( float )  scaleX ( x [ i ]),   ( float )  scaleY ( y [ i ]));
        path . closePath ();
        offscreen . fill ( path );
        draw ();
     }



    /***************************************************************************
    *  Drawing images.
    ***************************************************************************/

     // get an image from the given filename
     private   static   Image  getImage ( String  filename )   {
         if   ( filename  ==   null )   throw   new   IllegalArgumentException ();

         // to read from file
         ImageIcon  icon  =   new   ImageIcon ( filename );

         // try to read from URL
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
             try   {
                URL url  =   new  URL ( filename );
                icon  =   new   ImageIcon ( url );
             }
             catch   ( MalformedURLException  e )   {
                 /* not a url */
             }
         }

         // in case file is inside a .jar (classpath relative to StdDraw)
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
            URL url  =   StdDraw . class . getResource ( filename );
             if   ( url  !=   null )
                icon  =   new   ImageIcon ( url );
         }

         // in case file is inside a .jar (classpath relative to root of jar)
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
            URL url  =   Draw . class . getResource ( "/"   +  filename );
             if   ( url  ==   null )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " not found" );
            icon  =   new   ImageIcon ( url );
         }

         return  icon . getImage ();
     }

     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>).
     * The supported image formats are JPEG, PNG, and GIF.
     * As an optimization, the picture is cached, so there is no performance
     * penalty for redrawing the same image multiple times (e.g., in an animation).
     * However, if you change the picture file after drawing it, subsequent
     * calls will draw the original picture.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if either { @code  x} or { @code  y} is either NaN or infinite
     */
     public   void  picture ( double  x ,   double  y ,   String  filename )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( filename ,   "filename" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  image . getWidth ( null );
         int  hs  =  image . getHeight ( null );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );

        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),   ( int )   Math . round ( ys  -  hs / 2.0 ),   null );
        draw ();
     }

     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>),
     * rotated given number of degrees.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if { @code  x}, { @code  y}, { @code  degrees} is NaN or infinite
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   void  picture ( double  x ,   double  y ,   String  filename ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( filename ,   "filename" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  image . getWidth ( null );
         int  hs  =  image . getHeight ( null );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );

        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),   ( int )   Math . round ( ys  -  hs / 2.0 ),   null );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );

        draw ();
     }

     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>),
     * rescaled to the specified bounding box.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   scaledWidth the width of the scaled image (in screen coordinates)
     *  @param   scaledHeight the height of the scaled image (in screen coordinates)
     *  @throws  IllegalArgumentException if either { @code  scaledWidth}
     *         or { @code  scaledHeight} is negative
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   void  picture ( double  x ,   double  y ,   String  filename ,   double  scaledWidth ,   double  scaledHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( scaledWidth ,   "scaled width" );
        validate ( scaledHeight ,   "scaled height" );
        validateNotNull ( filename ,   "filename" );
        validateNonnegative ( scaledWidth ,   "scaled width" );
        validateNonnegative ( scaledHeight ,   "scaled height" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( scaledWidth );
         double  hs  =  factorY ( scaledHeight );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else   {
            offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),
                                        ( int )   Math . round ( ys  -  hs / 2.0 ),
                                        ( int )   Math . round ( ws ),
                                        ( int )   Math . round ( hs ),   null );
         }
        draw ();
     }


     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>), rotated
     * given number of degrees, and rescaled to the specified bounding box.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   scaledWidth the width of the scaled image (in screen coordinates)
     *  @param   scaledHeight the height of the scaled image (in screen coordinates)
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if either { @code  scaledWidth}
     *         or { @code  scaledHeight} is negative
     *  @throws  IllegalArgumentException if the image filename is invalid
     */
     public   void  picture ( double  x ,   double  y ,   String  filename ,   double  scaledWidth ,   double  scaledHeight ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( scaledWidth ,   "scaled width" );
        validate ( scaledHeight ,   "scaled height" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( filename ,   "filename" );
        validateNonnegative ( scaledWidth ,   "scaled width" );
        validateNonnegative ( scaledHeight ,   "scaled height" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( scaledWidth );
         double  hs  =  factorY ( scaledHeight );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );

        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),
                                    ( int )   Math . round ( ys  -  hs / 2.0 ),
                                    ( int )   Math . round ( ws ),
                                    ( int )   Math . round ( hs ),   null );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );

        draw ();
     }


    /***************************************************************************
    *  Drawing text.
    ***************************************************************************/

     /**
     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the center <em>x</em>-coordinate of the text
     *  @param   y the center <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   void  text ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  metrics . stringWidth ( text );
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )   ( xs  -  ws / 2.0 ),   ( float )   ( ys  +  hs ));
        draw ();
     }

     /**
     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>) and
     * rotated by the specified number of degrees.
     *  @param   x the center <em>x</em>-coordinate of the text
     *  @param   y the center <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x}, { @code  y}, or { @code  degrees} is either NaN or infinite
     */
     public   void  text ( double  x ,   double  y ,   String  text ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( text ,   "text" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        text ( x ,  y ,  text );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );
     }

     /**
     * Writes the given text string in the current font, left-aligned at (<em>x</em>, <em>y</em>).
     *  @param   x the <em>x</em>-coordinate of the text
     *  @param   y the <em>y</em>-coordinate of the text
     *  @param   text the text
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   void  textLeft ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         // int ws = metrics.stringWidth(text);
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )  xs ,   ( float )   ( ys  +  hs ));
        draw ();
     }

     /**
     * Writes the given text string in the current font, right-aligned at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the text
     *  @param   y the <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   void  textRight ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  metrics . stringWidth ( text );
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )   ( xs  -  ws ),   ( float )   ( ys  +  hs ));
        draw ();
     }

     /**
     * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds
     * and enables double buffering.
     *  @param  t number of milliseconds
     *  @deprecated  replaced by { @link  #enableDoubleBuffering()}, { @link  #show()}, and { @link  #pause(int t)}
     */
    @ Deprecated
     public   void  show ( int  t )   {
        show ();
        pause ( t );
        enableDoubleBuffering ();
     }

     /**
     * Pause for t milliseconds. This method is intended to support computer animations.
     *  @param  t number of milliseconds
     */
     public   void  pause ( int  t )   {
         try   {
             Thread . sleep ( t );
         }
         catch   ( InterruptedException  e )   {
             System . out . println ( "Error sleeping" );
         }
     }

     /**
     * Copies offscreen buffer to onscreen buffer. There is no reason to call
     * this method unless double buffering is enabled.
     */
     public   void  show ()   {
        onscreen . drawImage ( offscreenImage ,   0 ,   0 ,   null );
        frame . repaint ();
     }

     // draw onscreen if defer is false
     private   void  draw ()   {
         if   ( ! defer )  show ();
     }

     /**
     * Enable double buffering. All subsequent calls to 
     * drawing methods such as { @code  line()}, { @code  circle()},
     * and { @code  square()} will be deferred until the next call
     * to show(). Useful for animations.
     */
     public   void  enableDoubleBuffering ()   {
        defer  =   true ;
     }

     /**
     * Disable double buffering. All subsequent calls to 
     * drawing methods such as { @code  line()}, { @code  circle()},
     * and { @code  square()} will be displayed on screen when called.
     * This is the default.
     */
     public   void  disableDoubleBuffering ()   {
        defer  =   false ;
     }

     /**
     * Saves the drawing to using the specified filename.
     * The supported image formats are JPEG and PNG;
     * the filename suffix must be { @code  .jpg} or { @code  .png}.
     *
     *  @param   filename the name of the file with one of the required suffixes
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   void  save ( String  filename )   {
        validateNotNull ( filename ,   "filename" );
         File  file  =   new   File ( filename );
         String  suffix  =  filename . substring ( filename . lastIndexOf ( '.' )   +   1 );

         // png files
         if   ( "png" . equalsIgnoreCase ( suffix ))   {
             try   {
                 ImageIO . write ( offscreenImage ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }

         // need to change from ARGB to RGB for jpeg
         // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727
         else   if   ( "jpg" . equalsIgnoreCase ( suffix ))   {
             WritableRaster  raster  =  offscreenImage . getRaster ();
             WritableRaster  newRaster ;
            newRaster  =  raster . createWritableChild ( 0 ,   0 ,  width ,  height ,   0 ,   0 ,   new   int []   { 0 ,   1 ,   2 });
             DirectColorModel  cm  =   ( DirectColorModel )  offscreenImage . getColorModel ();
             DirectColorModel  newCM  =   new   DirectColorModel ( cm . getPixelSize (),
                                                          cm . getRedMask (),
                                                          cm . getGreenMask (),
                                                          cm . getBlueMask ());
             BufferedImage  rgbBuffer  =   new   BufferedImage ( newCM ,  newRaster ,   false ,    null );
             try   {
                 ImageIO . write ( rgbBuffer ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }

         else   {
             System . out . println ( "Invalid image file type: "   +  suffix );
         }
     }


     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  actionPerformed ( ActionEvent  e )   {
         FileDialog  chooser  =   new   FileDialog ( frame ,   "Use a .png or .jpg extension" ,   FileDialog . SAVE );
        chooser . setVisible ( true );
         String  filename  =  chooser . getFile ();
         if   ( filename  !=   null )   {
            save ( chooser . getDirectory ()   +   File . separator  +  chooser . getFile ());
         }
     }



    /***************************************************************************
    *  Event-based interactions.
    ***************************************************************************/

     /**
     * Adds a { @link  DrawListener} to listen to keyboard and mouse events.
     *
     *  @param  listener the {\tt DrawListener} argument
     */
     public   void  addListener ( DrawListener  listener )   {
         // ensure there is a window for listenting to events
        show ();
        listeners . add ( listener );
        frame . addKeyListener ( this );
        frame . addMouseListener ( this );
        frame . addMouseMotionListener ( this );
        frame . setFocusable ( true );  
     }




    /***************************************************************************
    *  Mouse interactions.
    ***************************************************************************/

     /**
     * Returns true if the mouse is being pressed.
     *
     *  @return  { @code  true} if the mouse is being pressed;
     *         { @code  false} otherwise
     */
     public   boolean  isMousePressed ()   {
         synchronized   ( mouseLock )   {
             return  isMousePressed ;
         }
     }

     /**
     * Returns true if the mouse is being pressed.
     *
     *  @return  { @code  true} if the mouse is being pressed;
     *         { @code  false} otherwise
     *  @deprecated  replaced by { @link  #isMousePressed()}
     */
    @ Deprecated
     public   boolean  mousePressed ()   {
         synchronized   ( mouseLock )   {
             return  isMousePressed ;
         }
     }

     /**
     * Returns the x-coordinate of the mouse.
     *  @return  the x-coordinate of the mouse
     */
     public   double  mouseX ()   {
         synchronized   ( mouseLock )   {
             return  mouseX ;
         }
     }

     /**
     * Returns the y-coordinate of the mouse.
     *
     *  @return  the y-coordinate of the mouse
     */
     public   double  mouseY ()   {
         synchronized   ( mouseLock )   {
             return  mouseY ;
         }
     }



     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseEntered ( MouseEvent  e )   {
         // this body is intentionally left empty
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseExited ( MouseEvent  e )   {
         // this body is intentionally left empty
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mousePressed ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            mouseX  =  userX ( e . getX ());
            mouseY  =  userY ( e . getY ());
            isMousePressed  =   true ;
         }
         if   ( e . getButton ()   ==   MouseEvent . BUTTON1 )   {
             for   ( DrawListener  listener  :  listeners )
                listener . mousePressed ( userX ( e . getX ()),  userY ( e . getY ()));
         }

     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseReleased ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            isMousePressed  =   false ;
         }
         if   ( e . getButton ()   ==   MouseEvent . BUTTON1 )   {
             for   ( DrawListener  listener  :  listeners )
                listener . mouseReleased ( userX ( e . getX ()),  userY ( e . getY ()));
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseClicked ( MouseEvent  e )   {
         if   ( e . getButton ()   ==   MouseEvent . BUTTON1 )   {
             for   ( DrawListener  listener  :  listeners )
                listener . mouseClicked ( userX ( e . getX ()),  userY ( e . getY ()));
         }
     }


     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseDragged ( MouseEvent  e )    {
         synchronized   ( mouseLock )   {
            mouseX  =  userX ( e . getX ());
            mouseY  =  userY ( e . getY ());
         }
         // doesn't seem to work if a button is specified
         for   ( DrawListener  listener  :  listeners )
            listener . mouseDragged ( userX ( e . getX ()),  userY ( e . getY ()));
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseMoved ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            mouseX  =  userX ( e . getX ());
            mouseY  =  userY ( e . getY ());
         }
     }


    /***************************************************************************
    *  Keyboard interactions.
    ***************************************************************************/

     /**
     * Returns true if the user has typed a key.
     *
     *  @return  { @code  true} if the user has typed a key; { @code  false} otherwise
     */
     public   boolean  hasNextKeyTyped ()   {
         synchronized   ( keyLock )   {
             return   ! keysTyped . isEmpty ();
         }
     }

     /**
     * The next key typed by the user.
     *
     *  @return  the next key typed by the user
     */
     public   char  nextKeyTyped ()   {
         synchronized   ( keyLock )   {
             return  keysTyped . removeLast ();
         }
     }

    /**
     * Returns true if the keycode is being pressed.
     * <p>
     * This method takes as an argument the keycode (corresponding to a physical key).
     * It can handle action keys (such as F1 and arrow keys) and modifier keys
     * (such as shift and control).
     * See { @link  KeyEvent} for a description of key codes.
     *
     *  @param   keycode the keycode to check
     *  @return  { @code  true} if { @code  keycode} is currently being pressed;
     *         { @code  false} otherwise
     */
     public   boolean  isKeyPressed ( int  keycode )   {
         synchronized   ( keyLock )   {
             return  keysDown . contains ( keycode );
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyTyped ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysTyped . addFirst ( e . getKeyChar ());
         }

         // notify all listeners
         for   ( DrawListener  listener  :  listeners )
            listener . keyTyped ( e . getKeyChar ());
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyPressed ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysDown . add ( e . getKeyCode ());
         }

         // notify all listeners
         for   ( DrawListener  listener  :  listeners )
            listener . keyPressed ( e . getKeyCode ());
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyReleased ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysDown . remove ( e . getKeyCode ());
         }

         // notify all listeners
         for   ( DrawListener  listener  :  listeners )
            listener . keyPressed ( e . getKeyCode ());
     }


    /***************************************************************************
    *  For improved resolution on Mac Retina displays.
    ***************************************************************************/

     private   static   class   RetinaImageIcon   extends   ImageIcon   {
    
         public   RetinaImageIcon ( Image  image )   {
             super ( image );
         }

         public   int  getIconWidth ()   {
             return   super . getIconWidth ()   /   2 ;
         }

         /**
         * Gets the height of the icon.
         *
         *  @return  the height in pixels of this icon
         */
         public   int  getIconHeight ()   {
             return   super . getIconHeight ()   /   2 ;
         }

         public   synchronized   void  paintIcon ( Component  c ,   Graphics  g ,   int  x ,   int  y )   {
             Graphics2D  g2  =   ( Graphics2D )  g . create ();
            g2 . setRenderingHint ( RenderingHints . KEY_INTERPOLATION , RenderingHints . VALUE_INTERPOLATION_BICUBIC );
            g2 . setRenderingHint ( RenderingHints . KEY_RENDERING , RenderingHints . VALUE_RENDER_QUALITY );
            g2 . setRenderingHint ( RenderingHints . KEY_ANTIALIASING , RenderingHints . VALUE_ANTIALIAS_ON );
            g2 . scale ( 0.5 ,   0.5 );
             super . paintIcon ( c ,  g2 ,  x  *   2 ,  y  *   2 );
            g2 . dispose ();
         }
     }

     /**
     * Test client.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         // create one drawing window
         Draw  draw1  =   new   Draw ( "Test client 1" );
        draw1 . square ( 0.2 ,   0.8 ,   0.1 );
        draw1 . filledSquare ( 0.8 ,   0.8 ,   0.2 );
        draw1 . circle ( 0.8 ,   0.2 ,   0.2 );
        draw1 . setPenColor ( Draw . MAGENTA );
        draw1 . setPenRadius ( 0.02 );
        draw1 . arc ( 0.8 ,   0.2 ,   0.1 ,   200 ,   45 );


         // create another one
         Draw  draw2  =   new   Draw ( "Test client 2" );
        draw2 . setCanvasSize ( 900 ,   200 );
         // draw a blue diamond
        draw2 . setPenRadius ();
        draw2 . setPenColor ( Draw . BLUE );
         double []  x  =   {   0.1 ,   0.2 ,   0.3 ,   0.2   };
         double []  y  =   {   0.2 ,   0.3 ,   0.2 ,   0.1   };
        draw2 . filledPolygon ( x ,  y );

         // text
        draw2 . setPenColor ( Draw . BLACK );
        draw2 . text ( 0.2 ,   0.5 ,   "bdfdfdfdlack text" );
        draw2 . setPenColor ( Draw . WHITE );
        draw2 . text ( 0.8 ,   0.8 ,   "white text" );
     }

}

DrawListener.java

DrawListener.java

/******************************************************************************
 *  Compilation:  javac DrawListener.java
 *  Execution:    none
 *  Dependencies: none
 *
 *  Interface that accompanies Draw.java.
 ******************************************************************************/

/**
 *  <i>DrawListener</i>. This interface provides a basic capability for
 *  responding to keyboard in mouse events from { @link  Draw} via callbacks.
 *  You can see some examples in
 *  <a href="https://introcs.cs.princeton.edu/java/36inheritance">Section 3.6</a>.
 *
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */

public   interface   DrawListener   {

     /**
     * Invoked when the mouse has been pressed.
     *
     *  @param  x the x-coordinate of the mouse
     *  @param  y the y-coordinate of the mouse
     */
     void  mousePressed ( double  x ,   double  y );

     /**
     * Invoked when the mouse has been dragged.
     *
     *  @param  x the x-coordinate of the mouse
     *  @param  y the y-coordinate of the mouse
     */
     void  mouseDragged ( double  x ,   double  y );

     /**
     * Invoked when the mouse has been released.
     *
     *  @param  x the x-coordinate of the mouse
     *  @param  y the y-coordinate of the mouse
     */
     void  mouseReleased ( double  x ,   double  y );

     /**
     * Invoked when the mouse has been clicked (pressed and released).
     *
     *  @param  x the x-coordinate of the mouse
     *  @param  y the y-coordinate of the mouse
     */
     void  mouseClicked ( double  x ,   double  y );

     /**
     * Invoked when a key has been typed.
     *
     *  @param  c the character typed
     */
     void  keyTyped ( char  c );

     /**
     * Invoked when a key has been pressed.
     *
     *  @param  keycode the key combination pressed
     */
     void  keyPressed ( int  keycode );

     /**
     * Invoked when a key has been released.
     *
     *  @param  keycode the key combination released
     */
     void  keyReleased ( int  keycode );
}

GrayscalePicture.java

GrayscalePicture.java

/******************************************************************************
 *  Compilation:  javac GrayscalePicture.java
 *  Execution:    java GrayscalePicture imagename
 *  Dependencies: none
 *
 *  Data type for manipulating individual pixels of a grayscale image. The
 *  original image can be read from a file in JPEG, GIF, or PNG format, or the
 *  user can create a blank image of a given dimension. Includes methods for
 *  displaying the image in a window on the screen or saving to a file.
 *
 *  % java GrayscalePicture mandrill.jpg
 *
 *  Remarks
 *  -------
 *   - pixel (x, y) is column x and row y, where (0, 0) is upper left
 *
 *   - uses BufferedImage.TYPE_INT_RGB because BufferedImage.TYPE_BYTE_GRAY
 *     seems to do some undesirable olor correction when calling getRGB() and
 *     setRGB()
 *
 ******************************************************************************/

import  java . awt . Color ;
import  java . awt . FileDialog ;
import  java . awt . Toolkit ;
import  java . awt . event . ActionEvent ;
import  java . awt . event . ActionListener ;
import  java . awt . event . KeyEvent ;
import  java . awt . image . BufferedImage ;
import  java . io . File ;
import  java . io . IOException ;
import  java . net . URL ;
import  javax . imageio . ImageIO ;
import  javax . swing . ImageIcon ;
import  javax . swing . JFrame ;
import  javax . swing . JLabel ;
import  javax . swing . JMenu ;
import  javax . swing . JMenuBar ;
import  javax . swing . JMenuItem ;
import  javax . swing . JPanel ;
import  javax . swing . KeyStroke ;


/**
 *  This class provides methods for manipulating individual pixels of
 *  a grayscale image.
 *  The original image can be read from a { @code  PNG}, { @code  GIF},
 *  or { @code  JPEG} file or the user can create a blank image of a given dimension.
 *  This class includes methods for displaying the image in a window on
 *  the screen or saving it to a file.
 *  <p>
 *  Pixel (<em>col</em>, <em>row</em>) is column <em>col</em> and row <em>row</em>.
 *  By default, the origin (0, 0) is the pixel in the top-left corner,
 *  which is a common convention in image processing.
 *  The method { @link  #setOriginLowerLeft()} change the origin to the lower left.
 *  <p>
 *  The { @code  get()} and { @code  set()} methods use { @link  Color} objects to get
 *  or set the color of the specified pixel. The { @link  Color} objects are converted
 *  to grayscale if they have different values for the R, G, and B channels.
 *  The { @code  getGrayscale()} and { @code  setGrayscale()} methods use an
 *  8-bit { @code  int} to encode the grayscale value, thereby avoiding the need to
 *  create temporary { @code  Color} objects.
 *  <p>
 *  A <em>W</em>-by-<em>H</em> picture uses ~ 4 <em>W H</em> bytes of memory,
 *  since the color of each pixel is encoded as a 32-bit <code>int</code>
 *  (even though, in principle, only ~ <em>W H</em> bytes are needed).
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *  See { @link  Picture} for a version that supports 32-bit RGB color images.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   GrayscalePicture   implements   ActionListener   {
     private   BufferedImage  image ;                 // the rasterized image
     private   JFrame  frame ;                        // on-screen view
     private   String  filename ;                     // name of file
     private   boolean  isOriginUpperLeft  =   true ;    // location of origin
     private   final   int  width ,  height ;             // width and height

    /**
     * Creates a { @code  width}-by-{ @code  height} picture, with { @code  width} columns
     * and { @code  height} rows, where each pixel is black.
     *
     *  @param  width the width of the picture
     *  @param  height the height of the picture
     *  @throws  IllegalArgumentException if { @code  width} is negative
     *  @throws  IllegalArgumentException if { @code  height} is negative
     */
     public   GrayscalePicture ( int  width ,   int  height )   {
         if   ( width   <   0 )   throw   new   IllegalArgumentException ( "width must be non-negative" );
         if   ( height  <   0 )   throw   new   IllegalArgumentException ( "height must be non-negative" );
         this . width   =  width ;
         this . height  =  height ;
        image  =   new   BufferedImage ( width ,  height ,   BufferedImage . TYPE_INT_RGB );
     }

    /**
     * Creates a new grayscale picture that is a deep copy of the argument picture.
     *
     *  @param   picture the picture to copy
     *  @throws  IllegalArgumentException if { @code  picture} is { @code  null}
     */
     public   GrayscalePicture ( GrayscalePicture  picture )   {
         if   ( picture  ==   null )   throw   new   IllegalArgumentException ( "constructor argument is null" );

        width   =  picture . width ();
        height  =  picture . height ();
        image  =   new   BufferedImage ( width ,  height ,   BufferedImage . TYPE_INT_RGB );
        filename  =  picture . filename ;
        isOriginUpperLeft  =  picture . isOriginUpperLeft ;
         for   ( int  col  =   0 ;  col  <  width ();  col ++ )
             for   ( int  row  =   0 ;  row  <  height ();  row ++ )
                image . setRGB ( col ,  row ,  picture . image . getRGB ( col ,  row ));
     }

    /**
     * Creates a grayscale picture by reading an image from a file or URL.
     *
     *  @param   name the name of the file (.png, .gif, or .jpg) or URL.
     *  @throws  IllegalArgumentException if cannot read image
     *  @throws  IllegalArgumentException if { @code  name} is { @code  null}
     */
     public   GrayscalePicture ( String  name )   {
         if   ( name  ==   null )   throw   new   IllegalArgumentException ( "constructor argument is null" );
         this . filename  =  name ;
         try   {
             // try to read from file in working directory
             File  file  =   new   File ( name );
             if   ( file . isFile ())   {
                image  =   ImageIO . read ( file );
             }

             else   {

                 // resource relative to .class file
                URL url  =  getClass (). getResource ( name );

                 // resource relative to classloader root
                 if   ( url  ==   null )   {
                    url  =  getClass (). getClassLoader (). getResource ( name );
                 }
     
                 // or URL from web
                 if   ( url  ==   null )   {
                    url  =   new  URL ( name );
                 }
        
                image  =   ImageIO . read ( url );
             }

             if   ( image  ==   null )   {
                 throw   new   IllegalArgumentException ( "could not read image: "   +  name );
             }

            width   =  image . getWidth ( null );
            height  =  image . getHeight ( null );

             // convert to grayscale inplace
             for   ( int  col  =   0 ;  col  <  width ;  col ++ )   {
                 for   ( int  row  =   0 ;  row  <  height ;  row ++ )   {
                     Color  color  =   new   Color ( image . getRGB ( col ,  row ));
                     Color  gray  =  toGray ( color );
                    image . setRGB ( col ,  row ,  gray . getRGB ());
                 }
             }
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "could not open image: "   +  name ,  ioe );
         }
     }

      // Returns a grayscale version of the given color as a Color object.
     private   static   Color  toGray ( Color  color )   {
         int  r  =  color . getRed ();
         int  g  =  color . getGreen ();
         int  b  =  color . getBlue ();
         int  y  =   ( int )   ( Math . round ( 0.299 * +   0.587 * +   0.114 * b ));
         return   new   Color ( y ,  y ,  y );
     }

    /**
     * Returns a { @link  JLabel} containing this picture, for embedding in a { @link  JPanel},
     * { @link  JFrame} or other GUI widget.
     *
     *  @return  the { @code  JLabel}
     */
     public   JLabel  getJLabel ()   {
         if   ( image  ==   null )   return   null ;           // no image available
         ImageIcon  icon  =   new   ImageIcon ( image );
         return   new   JLabel ( icon );
     }

    /**
     * Sets the origin to be the upper left pixel. This is the default.
     */
     public   void  setOriginUpperLeft ()   {
        isOriginUpperLeft  =   true ;
     }

    /**
     * Sets the origin to be the lower left pixel.
     */
     public   void  setOriginLowerLeft ()   {
        isOriginUpperLeft  =   false ;
     }

    /**
     * Displays the picture in a window on the screen.
     */
     public   void  show ()   {

         // create the GUI for viewing the image if needed
         if   ( frame  ==   null )   {
            frame  =   new   JFrame ();

             JMenuBar  menuBar  =   new   JMenuBar ();
             JMenu  menu  =   new   JMenu ( "File" );
            menuBar . add ( menu );
             JMenuItem  menuItem1  =   new   JMenuItem ( " Save...   " );
            menuItem1 . addActionListener ( this );
             // use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)
            menuItem1 . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_S ,
                                      Toolkit . getDefaultToolkit (). getMenuShortcutKeyMask ()));
            menu . add ( menuItem1 );
            frame . setJMenuBar ( menuBar );



            frame . setContentPane ( getJLabel ());
             // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame . setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE );
             if   ( filename  ==   null )  frame . setTitle ( width  +   "-by-"   +  height );
             else                   frame . setTitle ( filename );
            frame . setResizable ( false );
            frame . pack ();
            frame . setVisible ( true );
         }

         // draw
        frame . repaint ();
     }

    /**
     * Returns the height of the picture.
     *
     *  @return  the height of the picture (in pixels)
     */
     public   int  height ()   {
         return  height ;
     }

    /**
     * Returns the width of the picture.
     *
     *  @return  the width of the picture (in pixels)
     */
     public   int  width ()   {
         return  width ;
     }

     private   void  validateRowIndex ( int  row )   {
         if   ( row  <   0   ||  row  >=  height ())
             throw   new   IllegalArgumentException ( "row index must be between 0 and "   +   ( height ()   -   1 )   +   ": "   +  row );
     }

     private   void  validateColumnIndex ( int  col )   {
         if   ( col  <   0   ||  col  >=  width ())
             throw   new   IllegalArgumentException ( "column index must be between 0 and "   +   ( width ()   -   1 )   +   ": "   +  col );
     }

     private   void  validateGrayscaleValue ( int  gray )   {
         if   ( gray  <   0   ||  gray  >=   256 )
             throw   new   IllegalArgumentException ( "grayscale value must be between 0 and 255" );
     }

    /**
     * Returns the grayscale value of pixel ({ @code  col}, { @code  row}) as a { @link  java.awt.Color}.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @return  the grayscale value of pixel ({ @code  col}, { @code  row})
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   Color  get ( int  col ,   int  row )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         Color  color  =   new   Color ( image . getRGB ( col ,  row ));
         return  toGray ( color );
     }

    /**
     * Returns the grayscale value of pixel ({ @code  col}, { @code  row}) as an { @code  int}
     * between 0 and 255.
     * Using this method can be more efficient than { @link  #get(int, int)} because
     * it does not create a { @code  Color} object.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @return  the 8-bit integer representation of the grayscale value of pixel ({ @code  col}, { @code  row})
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   int  getGrayscale ( int  col ,   int  row )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         if   ( isOriginUpperLeft )   return  image . getRGB ( col ,  row )   &   0xFF ;
         else                     return  image . getRGB ( col ,  height  -  row  -   1 )   &   0xFF ;
     }

    /**
     * Sets the color of pixel ({ @code  col}, { @code  row}) to the given grayscale value.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @param  color the color (converts to grayscale if color is not a shade of gray)
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   void  set ( int  col ,   int  row ,   Color  color )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         if   ( color  ==   null )   throw   new   IllegalArgumentException ( "color argument is null" );
         Color  gray  =  toGray ( color );
        image . setRGB ( col ,  row ,  gray . getRGB ());
     }

    /**
     * Sets the color of pixel ({ @code  col}, { @code  row}) to the given grayscale value
     * between 0 and 255.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @param  gray the 8-bit integer representation of the grayscale value
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   void  setGrayscale ( int  col ,   int  row ,   int  gray )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
        validateGrayscaleValue ( gray );
         int  rgb  =  gray  |   ( gray  <<   8 )   |   ( gray  <<   16 );
         if   ( isOriginUpperLeft )  image . setRGB ( col ,  row ,  rgb );
         else                    image . setRGB ( col ,  height  -  row  -   1 ,  rgb );
     }

    /**
     * Returns true if this picture is equal to the argument picture.
     *
     *  @param  other the other picture
     *  @return  { @code  true} if this picture is the same dimension as { @code  other}
     *         and if all pixels have the same color; { @code  false} otherwise
     */
     public   boolean  equals ( Object  other )   {
         if   ( other  ==   this )   return   true ;
         if   ( other  ==   null )   return   false ;
         if   ( other . getClass ()   !=   this . getClass ())   return   false ;
         GrayscalePicture  that  =   ( GrayscalePicture )  other ;
         if   ( this . width ()    !=  that . width ())    return   false ;
         if   ( this . height ()   !=  that . height ())   return   false ;
         for   ( int  col  =   0 ;  col  <  width ();  col ++ )
             for   ( int  row  =   0 ;  row  <  height ();  row ++ )
                 if   ( this . getGrayscale ( col ,  row )   !=  that . getGrayscale ( col ,  row ))   return   false ;
         return   true ;
     }

    /**
     * Returns a string representation of this picture.
     * The result is a <code>width</code>-by-<code>height</code> matrix of pixels,
     * where the grayscale value of a pixel is an integer between 0 and 255.
     *
     *  @return  a string representation of this picture
     */
     public   String  toString ()   {
         StringBuilder  sb  =   new   StringBuilder ();
        sb . append ( width  + "-by-"   +  height  +   " grayscale picture (grayscale values given in hex)\n" );
         for   ( int  row  =   0 ;  row  <  height ;  row ++ )   {
             for   ( int  col  =   0 ;  col  <  width ;  col ++ )   {
                 int  gray  =   0 ;
                 if   ( isOriginUpperLeft )  gray  =   0xFF   &  image . getRGB ( col ,  row );
                 else                    gray  =   0xFF   &  image . getRGB ( col ,  height  -  row  -   1 );
                sb . append ( String . format ( "%3d " ,  gray ));
             }
            sb . append ( "\n" );
         }
         return  sb . toString (). trim ();
     }

     /**
     * This operation is not supported because pictures are mutable.
     *
     *  @return  does not return a value
     *  @throws  UnsupportedOperationException if called
     */
     public   int  hashCode ()   {
         throw   new   UnsupportedOperationException ( "hashCode() is not supported because pictures are mutable" );
     }

    /**
     * Saves the picture to a file in either PNG or JPEG format.
     * The filetype extension must be either .png or .jpg.
     *
     *  @param  name the name of the file
     *  @throws  IllegalArgumentException if { @code  name} is { @code  null}
     */
     public   void  save ( String  name )   {
         if   ( name  ==   null )   throw   new   IllegalArgumentException ( "argument to save() is null" );
        save ( new   File ( name ));
        filename  =  name ;
     }

    /**
     * Saves the picture to a file in a PNG or JPEG image format.
     *
     *  @param   file the file
     *  @throws  IllegalArgumentException if { @code  file} is { @code  null}
     */
     public   void  save ( File  file )   {
         if   ( file  ==   null )   throw   new   IllegalArgumentException ( "argument to save() is null" );
        filename  =  file . getName ();
         if   ( frame  !=   null )  frame . setTitle ( filename );
         String  suffix  =  filename . substring ( filename . lastIndexOf ( '.' )   +   1 );
         if   ( "jpg" . equalsIgnoreCase ( suffix )   ||   "png" . equalsIgnoreCase ( suffix ))   {
             try   {
                 ImageIO . write ( image ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }
         else   {
             System . out . println ( "Error: filename must end in .jpg or .png" );
         }
     }

    /**
     * Opens a save dialog box when the user selects "Save As" from the menu.
     */
    @ Override
     public   void  actionPerformed ( ActionEvent  e )   {
         FileDialog  chooser  =   new   FileDialog ( frame ,
                              "Use a .png or .jpg extension" ,   FileDialog . SAVE );
        chooser . setVisible ( true );
         if   ( chooser . getFile ()   !=   null )   {
            save ( chooser . getDirectory ()   +   File . separator  +  chooser . getFile ());
         }
     }

    /**
     * Unit tests this { @code  Picture} data type.
     * Reads a picture specified by the command-line argument,
     * and shows it in a window on the screen.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         GrayscalePicture  picture  =   new   GrayscalePicture ( args [ 0 ]);
         StdOut . printf ( "%d-by-%d\n" ,  picture . width (),  picture . height ());
         GrayscalePicture  copy  =   new   GrayscalePicture ( picture );
        picture . show ();
        copy . show ();
         while   ( ! StdIn . isEmpty ())   {
             int  row  =   StdIn . readInt ();
             int  col  =   StdIn . readInt ();
             int  gray  =   StdIn . readInt ();
            picture . setGrayscale ( row ,  col ,  gray );
             StdOut . println ( picture . get ( row ,  col ));
             StdOut . println ( picture . getGrayscale ( row ,  col ));
         }
     }

}

In.java

In.java

/******************************************************************************
 *  Compilation:  javac In.java
 *  Execution:    java In   (basic test --- see source for required files)
 *  Dependencies: none
 *
 *  Reads in data of various types from standard input, files, and URLs.
 *
 ******************************************************************************/

import  java . io . BufferedInputStream ;
import  java . io . File ;
import  java . io . FileInputStream ;
import  java . io . IOException ;
import  java . io . InputStream ;
import  java . net . URL ;
import  java . net . Socket ;
// import java.net.HttpURLConnection;
import  java . net . URLConnection ;
import  java . util . ArrayList ;
import  java . util . InputMismatchException ;
import  java . util . Locale ;
import  java . util . NoSuchElementException ;
import  java . util . Scanner ;
import  java . util . regex . Pattern ;

/**
 *  <i>Input</i>. This class provides methods for reading strings
 *  and numbers from standard input, file input, URLs, and sockets. 
 *  <p>
 *  The Locale used is: language = English, country = US. This is consistent
 *  with the formatting conventions with Java floating-point literals,
 *  command-line arguments (via { @link  Double#parseDouble(String)})
 *  and standard output. 
 *  <p>
 *  For additional documentation, see 
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i> 
 *  by Robert Sedgewick and Kevin Wayne.
 *  <p>
 *  Like { @link  Scanner}, reading a token also consumes preceding Java
 *  whitespace, reading a full line consumes
 *  the following end-of-line delimeter, while reading a character consumes
 *  nothing extra. 
 *  <p>
 *  Whitespace is defined in { @link  Character#isWhitespace(char)}. Newlines
 *  consist of \n, \r, \r\n, and Unicode hex code points 0x2028, 0x2029, 0x0085;
 *  see <a href="http://www.docjar.com/html/api/java/util/Scanner.java.html">
 *  Scanner.java</a> (NB: Java 6u23 and earlier uses only \r, \r, \r\n).
 *
 *   @author  David Pritchard
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   In   {
    
     ///// begin: section (1 of 2) of code duplicated from In to StdIn.
    
     // assume Unicode UTF-8 encoding
     private   static   final   String  CHARSET_NAME  =   "UTF-8" ;

     // assume language = English, country = US for consistency with System.out.
     private   static   final   Locale  LOCALE  =   Locale . US ;

     // the default token separator; we maintain the invariant that this value 
     // is held by the scanner's delimiter between calls
     private   static   final   Pattern  WHITESPACE_PATTERN  =   Pattern . compile ( "\\p{javaWhitespace}+" );

     // makes whitespace characters significant 
     private   static   final   Pattern  EMPTY_PATTERN  =   Pattern . compile ( "" );

     // used to read the entire input. source:
     // http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner_1.html
     private   static   final   Pattern  EVERYTHING_PATTERN  =   Pattern . compile ( "\\A" );

     //// end: section (1 of 2) of code duplicated from In to StdIn.

     private   Scanner  scanner ;

    /**
     * Initializes an input stream from standard input.
     */
     public   In ()   {
        scanner  =   new   Scanner ( new   BufferedInputStream ( System . in ),  CHARSET_NAME );
        scanner . useLocale ( LOCALE );
     }

    /**
     * Initializes an input stream from a socket.
     *
     *  @param   socket the socket
     *  @throws  IllegalArgumentException if cannot open { @code  socket}
     *  @throws  IllegalArgumentException if { @code  socket} is { @code  null}
     */
     public   In ( Socket  socket )   {
         if   ( socket  ==   null )   throw   new   IllegalArgumentException ( "socket argument is null" );
         try   {
             InputStream  is  =  socket . getInputStream ();
            scanner  =   new   Scanner ( new   BufferedInputStream ( is ),  CHARSET_NAME );
            scanner . useLocale ( LOCALE );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "Could not open "   +  socket ,  ioe );
         }
     }

    /**
     * Initializes an input stream from a URL.
     *
     *  @param   url the URL
     *  @throws  IllegalArgumentException if cannot open { @code  url}
     *  @throws  IllegalArgumentException if { @code  url} is { @code  null}
     */
     public   In ( URL url )   {
         if   ( url  ==   null )   throw   new   IllegalArgumentException ( "url argument is null" );
         try   {
             URLConnection  site  =  url . openConnection ();
             InputStream  is      =  site . getInputStream ();
            scanner             =   new   Scanner ( new   BufferedInputStream ( is ),  CHARSET_NAME );
            scanner . useLocale ( LOCALE );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "Could not open "   +  url ,  ioe );
         }
     }

    /**
     * Initializes an input stream from a file.
     *
     *  @param   file the file
     *  @throws  IllegalArgumentException if cannot open { @code  file}
     *  @throws  IllegalArgumentException if { @code  file} is { @code  null}
     */
     public   In ( File  file )   {
         if   ( file  ==   null )   throw   new   IllegalArgumentException ( "file argument is null" );
         try   {
             // for consistency with StdIn, wrap with BufferedInputStream instead of use
             // file as argument to Scanner
             FileInputStream  fis  =   new   FileInputStream ( file );
            scanner  =   new   Scanner ( new   BufferedInputStream ( fis ),  CHARSET_NAME );
            scanner . useLocale ( LOCALE );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "Could not open "   +  file ,  ioe );
         }
     }


    /**
     * Initializes an input stream from a filename or web page name.
     *
     *  @param   name the filename or web page name
     *  @throws  IllegalArgumentException if cannot open { @code  name} as
     *         a file or URL
     *  @throws  IllegalArgumentException if { @code  name} is { @code  null}
     */
     public   In ( String  name )   {
         if   ( name  ==   null )   throw   new   IllegalArgumentException ( "argument is null" );
         try   {
             // first try to read file from local file system
             File  file  =   new   File ( name );
             if   ( file . exists ())   {
                 // for consistency with StdIn, wrap with BufferedInputStream instead of use
                 // file as argument to Scanner
                 FileInputStream  fis  =   new   FileInputStream ( file );
                scanner  =   new   Scanner ( new   BufferedInputStream ( fis ),  CHARSET_NAME );
                scanner . useLocale ( LOCALE );
                 return ;
             }

             // resource relative to .class file
            URL url  =  getClass (). getResource ( name );

             // resource relative to classloader root
             if   ( url  ==   null )   {
                url  =  getClass (). getClassLoader (). getResource ( name );
             }

             // or URL from web
             if   ( url  ==   null )   {
                url  =   new  URL ( name );
             }

             URLConnection  site  =  url . openConnection ();

             // in order to set User-Agent, replace above line with these two
             // HttpURLConnection site = (HttpURLConnection) url.openConnection();
             // site.addRequestProperty("User-Agent", "Mozilla/4.76");

             InputStream  is      =  site . getInputStream ();
            scanner             =   new   Scanner ( new   BufferedInputStream ( is ),  CHARSET_NAME );
            scanner . useLocale ( LOCALE );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "Could not open "   +  name ,  ioe );
         }
     }

     /**
     * Initializes an input stream from a given { @link  Scanner} source; use with 
     * { @code  new Scanner(String)} to read from a string.
     * <p>
     * Note that this does not create a defensive copy, so the
     * scanner will be mutated as you read on. 
     *
     *  @param   scanner the scanner
     *  @throws  IllegalArgumentException if { @code  scanner} is { @code  null}
     */
     public   In ( Scanner  scanner )   {
         if   ( scanner  ==   null )   throw   new   IllegalArgumentException ( "scanner argument is null" );
         this . scanner  =  scanner ;
     }

     /**
     * Returns true if this input stream exists.
     *
     *  @return  { @code  true} if this input stream exists; { @code  false} otherwise
     */
     public   boolean  exists ()    {
         return  scanner  !=   null ;
     }
    
     ////  begin: section (2 of 2) of code duplicated from In to StdIn,
     ////  with all methods changed from "public" to "public static".

    /**
     * Returns true if input stream is empty (except possibly whitespace).
     * Use this to know whether the next call to { @link  #readString()}, 
     * { @link  #readDouble()}, etc will succeed.
     *
     *  @return  { @code  true} if this input stream is empty (except possibly whitespace);
     *         { @code  false} otherwise
     */
     public   boolean  isEmpty ()   {
         return   ! scanner . hasNext ();
     }

    /** 
     * Returns true if this input stream has a next line.
     * Use this method to know whether the
     * next call to { @link  #readLine()} will succeed.
     * This method is functionally equivalent to { @link  #hasNextChar()}.
     *
     *  @return  { @code  true} if this input stream has more input (including whitespace);
     *         { @code  false} otherwise
     */
     public   boolean  hasNextLine ()   {
         return  scanner . hasNextLine ();
     }

     /**
     * Returns true if this input stream has more input (including whitespace).
     * Use this method to know whether the next call to { @link  #readChar()} will succeed.
     * This method is functionally equivalent to { @link  #hasNextLine()}.
     * 
     *  @return  { @code  true} if this input stream has more input (including whitespace);
     *         { @code  false} otherwise   
     */
     public   boolean  hasNextChar ()   {
        scanner . useDelimiter ( EMPTY_PATTERN );
         boolean  result  =  scanner . hasNext ();
        scanner . useDelimiter ( WHITESPACE_PATTERN );
         return  result ;
     }


    /**
     * Reads and returns the next line in this input stream.
     *
     *  @return  the next line in this input stream; { @code  null} if no such line
     */
     public   String  readLine ()   {
         String  line ;
         try   {
            line  =  scanner . nextLine ();
         }
         catch   ( NoSuchElementException  e )   {
            line  =   null ;
         }
         return  line ;
     }

     /**
     * Reads and returns the next character in this input stream.
     *
     *  @return  the next { @code  char} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     */
     public   char  readChar ()   {
        scanner . useDelimiter ( EMPTY_PATTERN );
         try   {
             String  ch  =  scanner . next ();
             assert  ch . length ()   ==   1   :   "Internal (Std)In.readChar() error!"
                 +   " Please contact the authors." ;
            scanner . useDelimiter ( WHITESPACE_PATTERN );
             return  ch . charAt ( 0 );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'char' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }   


    /**
     * Reads and returns the remainder of this input stream, as a string.
     *
     *  @return  the remainder of this input stream, as a string
     */
     public   String  readAll ()   {
         if   ( ! scanner . hasNextLine ())
             return   "" ;

         String  result  =  scanner . useDelimiter ( EVERYTHING_PATTERN ). next ();
         // not that important to reset delimeter, since now scanner is empty
        scanner . useDelimiter ( WHITESPACE_PATTERN );   // but let's do it anyway
         return  result ;
     }


    /**
     * Reads the next token from this input stream and returns it as a { @code  String}.
     *
     *  @return  the next { @code  String} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     */
     public   String  readString ()   {
         try   {
             return  scanner . next ();
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'String' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  int},
     * and returns the { @code  int}.
     *
     *  @return  the next { @code  int} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as an { @code  int}
     */
     public   int  readInt ()   {
         try   {
             return  scanner . nextInt ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read an 'int' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read an 'int' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  double},
     * and returns the { @code  double}.
     *
     *  @return  the next { @code  double} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  double}
     */
     public   double  readDouble ()   {
         try   {
             return  scanner . nextDouble ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'double' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read a 'double' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  float},
     * and returns the { @code  float}.
     *
     *  @return  the next { @code  float} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  float}
     */
     public   float  readFloat ()   {
         try   {
             return  scanner . nextFloat ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'float' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read a 'float' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  long},
     * and returns the { @code  long}.
     *
     *  @return  the next { @code  long} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  long}
     */
     public   long  readLong ()   {
         try   {
             return  scanner . nextLong ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'long' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read a 'long' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  short},
     * and returns the { @code  short}.
     *
     *  @return  the next { @code  short} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  short}
     */
     public   short  readShort ()   {
         try   {
             return  scanner . nextShort ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'short' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read a 'short' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from this input stream, parses it as a { @code  byte},
     * and returns the { @code  byte}.
     * <p>
     * To read binary data, use { @link  BinaryIn}.
     *
     *  @return  the next { @code  byte} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  byte}
     */
     public   byte  readByte ()   {
         try   {
             return  scanner . nextByte ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'byte' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read a 'byte' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

     /**
     * Reads the next token from this input stream, parses it as a { @code  boolean}
     * (interpreting either { @code  "true"} or { @code  "1"} as { @code  true},
     * and either { @code  "false"} or { @code  "0"} as { @code  false}).
     *
     *  @return  the next { @code  boolean} in this input stream
     *  @throws  NoSuchElementException if the input stream is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  boolean}
     */
     public   boolean  readBoolean ()   {
         try   {
             String  token  =  readString ();
             if   ( "true" . equalsIgnoreCase ( token ))    return   true ;
             if   ( "false" . equalsIgnoreCase ( token ))   return   false ;
             if   ( "1" . equals ( token ))                 return   true ;
             if   ( "0" . equals ( token ))                 return   false ;
             throw   new   InputMismatchException ( "attempts to read a 'boolean' value from the input stream, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'boolean' value from the input stream, "
                                            +   "but no more tokens are available" );
         }
     }

     /**
     * Reads all remaining tokens from this input stream and returns them as
     * an array of strings.
     *
     *  @return  all remaining tokens in this input stream, as an array of strings
     */
     public   String []  readAllStrings ()   {
         // we could use readAll.trim().split(), but that's not consistent
         // since trim() uses characters 0x00..0x20 as whitespace
         String []  tokens  =  WHITESPACE_PATTERN . split ( readAll ());
         if   ( tokens . length  ==   0   ||  tokens [ 0 ]. length ()   >   0 )
             return  tokens ;
         String []  decapitokens  =   new   String [ tokens . length - 1 ];
         for   ( int  i  =   0 ;  i  <  tokens . length - 1 ;  i ++ )
            decapitokens [ i ]   =  tokens [ i + 1 ];
         return  decapitokens ;
     }

     /**
     * Reads all remaining lines from this input stream and returns them as
     * an array of strings.
     *
     *  @return  all remaining lines in this input stream, as an array of strings
     */
     public   String []  readAllLines ()   {
         ArrayList < String >  lines  =   new   ArrayList < String > ();
         while   ( hasNextLine ())   {
            lines . add ( readLine ());
         }
         return  lines . toArray ( new   String [ lines . size ()]);
     }


     /**
     * Reads all remaining tokens from this input stream, parses them as integers,
     * and returns them as an array of integers.
     *
     *  @return  all remaining lines in this input stream, as an array of integers
     */
     public   int []  readAllInts ()   {
         String []  fields  =  readAllStrings ();
         int []  vals  =   new   int [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Integer . parseInt ( fields [ i ]);
         return  vals ;
     }

     /**
     * Reads all remaining tokens from this input stream, parses them as longs,
     * and returns them as an array of longs.
     *
     *  @return  all remaining lines in this input stream, as an array of longs
     */
     public   long []  readAllLongs ()   {
         String []  fields  =  readAllStrings ();
         long []  vals  =   new   long [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Long . parseLong ( fields [ i ]);
         return  vals ;
     }

     /**
     * Reads all remaining tokens from this input stream, parses them as doubles,
     * and returns them as an array of doubles.
     *
     *  @return  all remaining lines in this input stream, as an array of doubles
     */
     public   double []  readAllDoubles ()   {
         String []  fields  =  readAllStrings ();
         double []  vals  =   new   double [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Double . parseDouble ( fields [ i ]);
         return  vals ;
     }
    
     ///// end: section (2 of 2) of code duplicated from In to StdIn */

    /**
     * Closes this input stream.
     */
     public   void  close ()   {
        scanner . close ();   
     }

     /**
     * Reads all integers from a file and returns them as
     * an array of integers.
     *
     *  @param       filename the name of the file
     *  @return      the integers in the file
     *  @deprecated  Replaced by { @code  new In(filename)}.{ @link  #readAllInts()}.
     */
    @ Deprecated
     public   static   int []  readInts ( String  filename )   {
         return   new   In ( filename ). readAllInts ();
     }

    /**
     * Reads all doubles from a file and returns them as
     * an array of doubles.
     *
     *  @param       filename the name of the file
     *  @return      the doubles in the file
     *  @deprecated  Replaced by { @code  new In(filename)}.{ @link  #readAllDoubles()}.
     */
    @ Deprecated
     public   static   double []  readDoubles ( String  filename )   {
         return   new   In ( filename ). readAllDoubles ();
     }

    /**
     * Reads all strings from a file and returns them as
     * an array of strings.
     *
     *  @param       filename the name of the file
     *  @return      the strings in the file
     *  @deprecated  Replaced by { @code  new In(filename)}.{ @link  #readAllStrings()}.
     */
    @ Deprecated
     public   static   String []  readStrings ( String  filename )   {
         return   new   In ( filename ). readAllStrings ();
     }

     /**
     * Reads all integers from standard input and returns them
     * an array of integers.
     *
     *  @return      the integers on standard input
     *  @deprecated  Replaced by { @link  StdIn#readAllInts()}.
     */
    @ Deprecated
     public   static   int []  readInts ()   {
         return   new   In (). readAllInts ();
     }

    /**
     * Reads all doubles from standard input and returns them as
     * an array of doubles.
     *
     *  @return      the doubles on standard input
     *  @deprecated  Replaced by { @link  StdIn#readAllDoubles()}.
     */
    @ Deprecated
     public   static   double []  readDoubles ()   {
         return   new   In (). readAllDoubles ();
     }

    /**
     * Reads all strings from standard input and returns them as
     *  an array of strings.
     *
     *  @return      the strings on standard input
     *  @deprecated  Replaced by { @link  StdIn#readAllStrings()}.
     */
    @ Deprecated
     public   static   String []  readStrings ()   {
         return   new   In (). readAllStrings ();
     }
    
    /**
     * Unit tests the { @code  In} data type.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         In  in ;
         String  urlName  =   "https://introcs.cs.princeton.edu/java/stdlib/InTest.txt" ;

         // read from a URL
         System . out . println ( "readAll() from URL "   +  urlName );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( urlName );
             System . out . println ( in . readAll ());
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();

         // read one line at a time from URL
         System . out . println ( "readLine() from URL "   +  urlName );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( urlName );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readLine ();
                 System . out . println ( s );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();

         // read one string at a time from URL
         System . out . println ( "readString() from URL "   +  urlName );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( urlName );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readString ();
                 System . out . println ( s );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();


         // read one line at a time from file in current directory
         System . out . println ( "readLine() from current directory" );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( "./InTest.txt" );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readLine ();
                 System . out . println ( s );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();


         // read one line at a time from file using relative path
         System . out . println ( "readLine() from relative path" );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( "../stdlib/InTest.txt" );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readLine ();
                 System . out . println ( s );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();

         // read one char at a time
         System . out . println ( "readChar() from file" );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( "InTest.txt" );
             while   ( ! in . isEmpty ())   {
                 char  c  =  in . readChar ();
                 System . out . print ( c );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();
         System . out . println ();

         // read one line at a time from absolute OS X / Linux path
         System . out . println ( "readLine() from absolute OS X / Linux path" );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( "/n/fs/introcs/www/java/stdlib/InTest.txt" );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readLine ();
                 System . out . println ( s );
             }
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();


         // read one line at a time from absolute Windows path
         System . out . println ( "readLine() from absolute Windows path" );
         System . out . println ( "---------------------------------------------------------------------------" );
         try   {
            in  =   new   In ( "G:\\www\\introcs\\stdlib\\InTest.txt" );
             while   ( ! in . isEmpty ())   {
                 String  s  =  in . readLine ();
                 System . out . println ( s );
             }
             System . out . println ();
         }
         catch   ( IllegalArgumentException  e )   {
             System . out . println ( e );
         }
         System . out . println ();

     }

}

Out.java

Out.java

/******************************************************************************
 *  Compilation:  javac Out.java
 *  Execution:    java Out
 *  Dependencies: none
 *
 *  Writes data of various types to: stdout, file, or socket.
 *
 ******************************************************************************/


import  java . io . FileOutputStream ;
import  java . io . IOException ;
import  java . io . OutputStream ;
import  java . io . OutputStreamWriter ;
import  java . io . PrintWriter ;
import  java . net . Socket ;
import  java . util . Locale ;

/**
 *  This class provides methods for writing strings and numbers to
 *  various output streams, including standard output, file, and sockets.
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   class   Out   {

     // force Unicode UTF-8 encoding; otherwise it's system dependent
     private   static   final   String  CHARSET_NAME  =   "UTF-8" ;

     // assume language = English, country = US for consistency with In
     private   static   final   Locale  LOCALE  =   Locale . US ;

     private   PrintWriter  out ;

    /**
     * Initializes an output stream from a { @link  OutputStream}.
     *
     *  @param   os the { @code  OutputStream}
     */
     public   Out ( OutputStream  os )   {
         try   {
             OutputStreamWriter  osw  =   new   OutputStreamWriter ( os ,  CHARSET_NAME );
            out  =   new   PrintWriter ( osw ,   true );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Initializes an output stream from standard output.
     */
     public   Out ()   {
         this ( System . out );
     }

    /**
     * Initializes an output stream from a socket.
     *
     *  @param   socket the socket
     */
     public   Out ( Socket  socket )   {
         try   {
             OutputStream  os  =  socket . getOutputStream ();
             OutputStreamWriter  osw  =   new   OutputStreamWriter ( os ,  CHARSET_NAME );
            out  =   new   PrintWriter ( osw ,   true );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Initializes an output stream from a file.
     *
     *  @param   filename the name of the file
     */
     public   Out ( String  filename )   {
         try   {
             OutputStream  os  =   new   FileOutputStream ( filename );
             OutputStreamWriter  osw  =   new   OutputStreamWriter ( os ,  CHARSET_NAME );
            out  =   new   PrintWriter ( osw ,   true );
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
     }

    /**
     * Closes the output stream.
     */
     public   void  close ()   {
        out . close ();
     }

    /**
     * Terminates the current line by printing the line-separator string.
     */
     public   void  println ()   {
        out . println ();
     }

    /**
     * Prints an object to this output stream and then terminates the line.
     *
     *  @param  x the object to print
     */
     public   void  println ( Object  x )   {
        out . println ( x );
     }

    /**
     * Prints a boolean to this output stream and then terminates the line.
     *
     *  @param  x the boolean to print
     */
     public   void  println ( boolean  x )   {
        out . println ( x );
     }

    /**
     * Prints a character to this output stream and then terminates the line.
     *
     *  @param  x the character to print
     */
     public   void  println ( char  x )   {
        out . println ( x );
     }

    /**
     * Prints a double to this output stream and then terminates the line.
     *
     *  @param  x the double to print
     */
     public   void  println ( double  x )   {
        out . println ( x );
     }

    /**
     * Prints a float to this output stream and then terminates the line.
     *
     *  @param  x the float to print
     */
     public   void  println ( float  x )   {
        out . println ( x );
     }

    /**
     * Prints an integer to this output stream and then terminates the line.
     *
     *  @param  x the integer to print
     */
     public   void  println ( int  x )   {
        out . println ( x );
     }

    /**
     * Prints a long to this output stream and then terminates the line.
     *
     *  @param  x the long to print
     */
     public   void  println ( long  x )   {
        out . println ( x );
     }

    /**
     * Prints a byte to this output stream and then terminates the line.
     * <p>
     * To write binary data, see { @link  BinaryOut}.
     *
     *  @param  x the byte to print
     */
     public   void  println ( byte  x )   {
        out . println ( x );
     }



    /**
     * Flushes this output stream.
     */
     public   void  print ()   {
        out . flush ();
     }

    /**
     * Prints an object to this output stream and flushes this output stream.
     * 
     *  @param  x the object to print
     */
     public   void  print ( Object  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a boolean to this output stream and flushes this output stream.
     * 
     *  @param  x the boolean to print
     */
     public   void  print ( boolean  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a character to this output stream and flushes this output stream.
     * 
     *  @param  x the character to print
     */
     public   void  print ( char  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a double to this output stream and flushes this output stream.
     * 
     *  @param  x the double to print
     */
     public   void  print ( double  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a float to this output stream and flushes this output stream.
     * 
     *  @param  x the float to print
     */
     public   void  print ( float  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints an integer to this output stream and flushes this output stream.
     * 
     *  @param  x the integer to print
     */
     public   void  print ( int  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a long integer to this output stream and flushes this output stream.
     * 
     *  @param  x the long integer to print
     */
     public   void  print ( long  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a byte to this output stream and flushes this output stream.
     * 
     *  @param  x the byte to print
     */
     public   void  print ( byte  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a formatted string to this output stream, using the specified format
     * string and arguments, and then flushes this output stream.
     *
     *  @param  format the format string
     *  @param  args   the arguments accompanying the format string
     */
     public   void  printf ( String  format ,   Object ...  args )   {
        out . printf ( LOCALE ,  format ,  args );
        out . flush ();
     }

    /**
     * Prints a formatted string to this output stream, using the specified
     * locale, format string, and arguments, and then flushes this output stream.
     *
     *  @param  locale the locale
     *  @param  format the format string
     *  @param  args   the arguments accompanying the format string
     */
     public   void  printf ( Locale  locale ,   String  format ,   Object ...  args )   {
        out . printf ( locale ,  format ,  args );
        out . flush ();
     }


    /**
     * A test client.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         Out  out ;

         // write to stdout
        out  =   new   Out ();
        out . println ( "Test 1" );
        out . close ();

         // write to a file
        out  =   new   Out ( "test.txt" );
        out . println ( "Test 2" );
        out . close ();
     }

}

Picture.java

Picture.java

/******************************************************************************
 *  Compilation:  javac Picture.java
 *  Execution:    java Picture imagename
 *  Dependencies: none
 *
 *  Data type for manipulating individual pixels of an image. The original
 *  image can be read from a file in JPG, GIF, or PNG format, or the
 *  user can create a blank image of a given dimension. Includes methods for
 *  displaying the image in a window on the screen or saving to a file.
 *
 *  % java Picture mandrill.jpg
 *
 *  Remarks
 *  -------
 *   - pixel (x, y) is column x and row y, where (0, 0) is upper left
 *
 ******************************************************************************/

import  java . awt . Color ;
import  java . awt . FileDialog ;
import  java . awt . Toolkit ;
import  java . awt . event . ActionEvent ;
import  java . awt . event . ActionListener ;
import  java . awt . event . KeyEvent ;
import  java . awt . image . BufferedImage ;
import  java . io . File ;
import  java . io . IOException ;
import  java . net . URL ;
import  javax . imageio . ImageIO ;
import  javax . swing . ImageIcon ;
import  javax . swing . JFrame ;
import  javax . swing . JLabel ;
import  javax . swing . JMenu ;
import  javax . swing . JMenuBar ;
import  javax . swing . JMenuItem ;
import  javax . swing . JPanel ;
import  javax . swing . KeyStroke ;


/**
 *  This class provides methods for manipulating individual pixels of
 *  an image using the RGB color format. The alpha component (for transparency)
 *  is not currently supported.
 *  The original image can be read from a { @code  PNG}, { @code  GIF},
 *  or { @code  JPEG} file or the user can create a blank image of a given dimension.
 *  This class includes methods for displaying the image in a window on
 *  the screen or saving it to a file.
 *  <p>
 *  Pixel (<em>col</em>, <em>row</em>) is column <em>col</em> and row <em>row</em>.
 *  By default, the origin (0, 0) is the pixel in the top-left corner,
 *  which is a common convention in image processing.
 *  The method { @link  #setOriginLowerLeft()} change the origin to the lower left.
 *  <p>
 *  The { @code  get()} and { @code  set()} methods use { @link  Color} objects to get
 *  or set the color of the specified pixel.
 *  The { @code  getRGB()} and { @code  setRGB()} methods use a 32-bit { @code  int}
 *  to encode the color, thereby avoiding the need to create temporary
 *  { @code  Color} objects. The red (R), green (G), and blue (B) components 
 *  are encoded using the least significant 24 bits.
 *  Given a 32-bit { @code  int} encoding the color, the following code extracts
 *  the RGB components:
 * <blockquote><pre>
 *  int r = (rgb &gt;&gt; 16) &amp; 0xFF;
 *  int g = (rgb &gt;&gt;  8) &amp; 0xFF;
 *  int b = (rgb &gt;&gt;  0) &amp; 0xFF;
 *  </pre></blockquote> 
 *  Given the RGB components (8-bits each) of a color,
 *  the following statement packs it into a 32-bit { @code  int}:
 * <blockquote><pre>
 *  int rgb = (r &lt;&lt; 16) + (g &lt;&lt; 8) + (b &lt;&lt; 0);
 * </pre></blockquote> 
 *  <p>
 *  A <em>W</em>-by-<em>H</em> picture uses ~ 4 <em>W H</em> bytes of memory,
 *  since the color of each pixel is encoded as a 32-bit <code>int</code>.
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/31datatype">Section 3.1</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *  See { @link  GrayscalePicture} for a version that supports grayscale images.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   Picture   implements   ActionListener   {
     private   BufferedImage  image ;                 // the rasterized image
     private   JFrame  frame ;                        // on-screen view
     private   String  filename ;                     // name of file
     private   boolean  isOriginUpperLeft  =   true ;    // location of origin
     private   final   int  width ,  height ;             // width and height

    /**
     * Creates a { @code  width}-by-{ @code  height} picture, with { @code  width} columns
     * and { @code  height} rows, where each pixel is black.
     *
     *  @param  width the width of the picture
     *  @param  height the height of the picture
     *  @throws  IllegalArgumentException if { @code  width} is negative or zero
     *  @throws  IllegalArgumentException if { @code  height} is negative or zero
     */
     public   Picture ( int  width ,   int  height )   {
         if   ( width   <=   0 )   throw   new   IllegalArgumentException ( "width must be positive" );
         if   ( height  <=   0 )   throw   new   IllegalArgumentException ( "height must be positive" );
         this . width   =  width ;
         this . height  =  height ;
        image  =   new   BufferedImage ( width ,  height ,   BufferedImage . TYPE_INT_RGB );
         // set to TYPE_INT_ARGB here and in next constructor to support transparency
     }

    /**
     * Creates a new picture that is a deep copy of the argument picture.
     *
     *  @param   picture the picture to copy
     *  @throws  IllegalArgumentException if { @code  picture} is { @code  null}
     */
     public   Picture ( Picture  picture )   {
         if   ( picture  ==   null )   throw   new   IllegalArgumentException ( "constructor argument is null" );

        width   =  picture . width ();
        height  =  picture . height ();
        image  =   new   BufferedImage ( width ,  height ,   BufferedImage . TYPE_INT_RGB );
        filename  =  picture . filename ;
        isOriginUpperLeft  =  picture . isOriginUpperLeft ;
         for   ( int  col  =   0 ;  col  <  width ();  col ++ )
             for   ( int  row  =   0 ;  row  <  height ();  row ++ )
                image . setRGB ( col ,  row ,  picture . image . getRGB ( col ,  row ));
     }

    /**
     * Creates a picture by reading an image from a file or URL.
     *
     *  @param   name the name of the file (.png, .gif, or .jpg) or URL.
     *  @throws  IllegalArgumentException if cannot read image
     *  @throws  IllegalArgumentException if { @code  name} is { @code  null}
     */
     public   Picture ( String  name )   {
         if   ( name  ==   null )   throw   new   IllegalArgumentException ( "constructor argument is null" );

         this . filename  =  name ;
         try   {
             // try to read from file in working directory
             File  file  =   new   File ( name );
             if   ( file . isFile ())   {
                image  =   ImageIO . read ( file );
             }

             else   {

                 // resource relative to .class file
                URL url  =  getClass (). getResource ( filename );

                 // resource relative to classloader root
                 if   ( url  ==   null )   {
                    url  =  getClass (). getClassLoader (). getResource ( name );
                 }

                 // or URL from web
                 if   ( url  ==   null )   {
                    url  =   new  URL ( name );
                 }

                image  =   ImageIO . read ( url );
             }

             if   ( image  ==   null )   {
                 throw   new   IllegalArgumentException ( "could not read image: "   +  name );
             }

            width   =  image . getWidth ( null );
            height  =  image . getHeight ( null );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "could not open image: "   +  name ,  ioe );
         }
     }

    /**
     * Creates a picture by reading the image from a PNG, GIF, or JPEG file.
     *
     *  @param  file the file
     *  @throws  IllegalArgumentException if cannot read image
     *  @throws  IllegalArgumentException if { @code  file} is { @code  null}
     */
     public   Picture ( File  file )   {
         if   ( file  ==   null )   throw   new   IllegalArgumentException ( "constructor argument is null" );

         try   {
            image  =   ImageIO . read ( file );
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "could not open file: "   +  file ,  ioe );
         }
         if   ( image  ==   null )   {
             throw   new   IllegalArgumentException ( "could not read file: "   +  file );
         }
        width   =  image . getWidth ( null );
        height  =  image . getHeight ( null );
        filename  =  file . getName ();
     }

    /**
     * Returns a { @link  JLabel} containing this picture, for embedding in a { @link  JPanel},
     * { @link  JFrame} or other GUI widget.
     *
     *  @return  the { @code  JLabel}
     */
     public   JLabel  getJLabel ()   {
         if   ( image  ==   null )   return   null ;           // no image available
         ImageIcon  icon  =   new   ImageIcon ( image );
         return   new   JLabel ( icon );
     }

    /**
     * Sets the origin to be the upper left pixel. This is the default.
     */
     public   void  setOriginUpperLeft ()   {
        isOriginUpperLeft  =   true ;
     }

    /**
     * Sets the origin to be the lower left pixel.
     */
     public   void  setOriginLowerLeft ()   {
        isOriginUpperLeft  =   false ;
     }

    /**
     * Displays the picture in a window on the screen.
     */
     public   void  show ()   {

         // create the GUI for viewing the image if needed
         if   ( frame  ==   null )   {
            frame  =   new   JFrame ();

             JMenuBar  menuBar  =   new   JMenuBar ();
             JMenu  menu  =   new   JMenu ( "File" );
            menuBar . add ( menu );
             JMenuItem  menuItem1  =   new   JMenuItem ( " Save...   " );
            menuItem1 . addActionListener ( this );
             // use getMenuShortcutKeyMaskEx() in Java 10 (getMenuShortcutKeyMask() deprecated)           
            menuItem1 . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_S ,
                                      Toolkit . getDefaultToolkit (). getMenuShortcutKeyMask ()));
            menu . add ( menuItem1 );
            frame . setJMenuBar ( menuBar );



            frame . setContentPane ( getJLabel ());
             // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame . setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE );
             if   ( filename  ==   null )  frame . setTitle ( width  +   "-by-"   +  height );
             else                   frame . setTitle ( filename );
            frame . setResizable ( false );
            frame . pack ();
            frame . setVisible ( true );
         }

         // draw
        frame . repaint ();
     }

    /**
     * Returns the height of the picture.
     *
     *  @return  the height of the picture (in pixels)
     */
     public   int  height ()   {
         return  height ;
     }

    /**
     * Returns the width of the picture.
     *
     *  @return  the width of the picture (in pixels)
     */
     public   int  width ()   {
         return  width ;
     }

     private   void  validateRowIndex ( int  row )   {
         if   ( row  <   0   ||  row  >=  height ())
             throw   new   IllegalArgumentException ( "row index must be between 0 and "   +   ( height ()   -   1 )   +   ": "   +  row );
     }

     private   void  validateColumnIndex ( int  col )   {
         if   ( col  <   0   ||  col  >=  width ())
             throw   new   IllegalArgumentException ( "column index must be between 0 and "   +   ( width ()   -   1 )   +   ": "   +  col );
     }

    /**
     * Returns the color of pixel ({ @code  col}, { @code  row}) as a { @link  java.awt.Color}.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @return  the color of pixel ({ @code  col}, { @code  row})
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   Color  get ( int  col ,   int  row )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         int  rgb  =  getRGB ( col ,  row );
         return   new   Color ( rgb );
     }

    /**
     * Returns the color of pixel ({ @code  col}, { @code  row}) as an { @code  int}.
     * Using this method can be more efficient than { @link  #get(int, int)} because
     * it does not create a { @code  Color} object.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @return  the integer representation of the color of pixel ({ @code  col}, { @code  row})
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   int  getRGB ( int  col ,   int  row )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         if   ( isOriginUpperLeft )   return  image . getRGB ( col ,  row );
         else                     return  image . getRGB ( col ,  height  -  row  -   1 );
     }

    /**
     * Sets the color of pixel ({ @code  col}, { @code  row}) to given color.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @param  color the color
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   void  set ( int  col ,   int  row ,   Color  color )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         if   ( color  ==   null )   throw   new   IllegalArgumentException ( "color argument is null" );
         int  rgb  =  color . getRGB ();
        setRGB ( col ,  row ,  rgb );
     }

    /**
     * Sets the color of pixel ({ @code  col}, { @code  row}) to given color.
     *
     *  @param  col the column index
     *  @param  row the row index
     *  @param  rgb the integer representation of the color
     *  @throws  IllegalArgumentException unless both { @code  0 <= col < width} and { @code  0 <= row < height}
     */
     public   void  setRGB ( int  col ,   int  row ,   int  rgb )   {
        validateColumnIndex ( col );
        validateRowIndex ( row );
         if   ( isOriginUpperLeft )  image . setRGB ( col ,  row ,  rgb );
         else                    image . setRGB ( col ,  height  -  row  -   1 ,  rgb );
     }

    /**
     * Returns true if this picture is equal to the argument picture.
     *
     *  @param  other the other picture
     *  @return  { @code  true} if this picture is the same dimension as { @code  other}
     *         and if all pixels have the same color; { @code  false} otherwise
     */
     public   boolean  equals ( Object  other )   {
         if   ( other  ==   this )   return   true ;
         if   ( other  ==   null )   return   false ;
         if   ( other . getClass ()   !=   this . getClass ())   return   false ;
         Picture  that  =   ( Picture )  other ;
         if   ( this . width ()    !=  that . width ())    return   false ;
         if   ( this . height ()   !=  that . height ())   return   false ;
         for   ( int  col  =   0 ;  col  <  width ();  col ++ )
             for   ( int  row  =   0 ;  row  <  height ();  row ++ )
                 if   ( this . getRGB ( col ,  row )   !=  that . getRGB ( col ,  row ))   return   false ;
         return   true ;
     }

    /**
     * Returns a string representation of this picture.
     * The result is a <code>width</code>-by-<code>height</code> matrix of pixels,
     * where the color of a pixel is represented using 6 hex digits to encode
     * the red, green, and blue components.
     *
     *  @return  a string representation of this picture
     */
     public   String  toString ()   {
         StringBuilder  sb  =   new   StringBuilder ();
        sb . append ( width  + "-by-"   +  height  +   " picture (RGB values given in hex)\n" );
         for   ( int  row  =   0 ;  row  <  height ;  row ++ )   {
             for   ( int  col  =   0 ;  col  <  width ;  col ++ )   {
                 int  rgb  =   0 ;
                 if   ( isOriginUpperLeft )  rgb  =  image . getRGB ( col ,  row );
                 else                    rgb  =  image . getRGB ( col ,  height  -  row  -   1 );
                sb . append ( String . format ( "#%06X " ,  rgb  &   0xFFFFFF ));
             }
            sb . append ( "\n" );
         }
         return  sb . toString (). trim ();
     }

     /**
     * This operation is not supported because pictures are mutable.
     *
     *  @return  does not return a value
     *  @throws  UnsupportedOperationException if called
     */
     public   int  hashCode ()   {
         throw   new   UnsupportedOperationException ( "hashCode() is not supported because pictures are mutable" );
     }

    /**
     * Saves the picture to a file in either PNG or JPEG format.
     * The filetype extension must be either .png or .jpg.
     *
     *  @param  name the name of the file
     *  @throws  IllegalArgumentException if { @code  name} is { @code  null}
     */
     public   void  save ( String  name )   {
         if   ( name  ==   null )   throw   new   IllegalArgumentException ( "argument to save() is null" );
        save ( new   File ( name ));
        filename  =  name ;
     }

    /**
     * Saves the picture to a file in a PNG or JPEG image format.
     *
     *  @param   file the file
     *  @throws  IllegalArgumentException if { @code  file} is { @code  null}
     */
     public   void  save ( File  file )   {
         if   ( file  ==   null )   throw   new   IllegalArgumentException ( "argument to save() is null" );
        filename  =  file . getName ();
         if   ( frame  !=   null )  frame . setTitle ( filename );
         String  suffix  =  filename . substring ( filename . lastIndexOf ( '.' )   +   1 );
         if   ( "jpg" . equalsIgnoreCase ( suffix )   ||   "png" . equalsIgnoreCase ( suffix ))   {
             try   {
                 ImageIO . write ( image ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }
         else   {
             System . out . println ( "Error: filename must end in .jpg or .png" );
         }
     }

    /**
     * Opens a save dialog box when the user selects "Save As" from the menu.
     */
    @ Override
     public   void  actionPerformed ( ActionEvent  e )   {
         FileDialog  chooser  =   new   FileDialog ( frame ,
                              "Use a .png or .jpg extension" ,   FileDialog . SAVE );
        chooser . setVisible ( true );
         if   ( chooser . getFile ()   !=   null )   {
            save ( chooser . getDirectory ()   +   File . separator  +  chooser . getFile ());
         }
     }

    /**
     * Unit tests this { @code  Picture} data type.
     * Reads a picture specified by the command-line argument,
     * and shows it in a window on the screen.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         Picture  picture  =   new   Picture ( args [ 0 ]);
         System . out . printf ( "%d-by-%d\n" ,  picture . width (),  picture . height ());
        picture . show ();
     }

}

PlayMusic.java

PlayMusic.java

import  java . io . InputStream ;
import  java . io . IOException ;

import  java . applet . * ;
import  java . net . * ;
import  java . io . * ;

import  javax . sound . sampled . AudioFormat ;
import  javax . sound . sampled . AudioInputStream ;
import  javax . sound . sampled . AudioSystem ;
import  javax . sound . sampled . DataLine ;
import  javax . sound . sampled . LineUnavailableException ;
import  javax . sound . sampled . SourceDataLine ;
import  javax . sound . sampled . UnsupportedAudioFileException ;


public   class   PlayMusic   {

     // play sound file using Applet.newAudioClip();
     private   static   void  playApplet ( String  filename )   {
        URL url  =   null ;
         try   {
             File  file  =   new   File ( filename );
             if   ( file . canRead ())  url  =  file . toURI (). toURL ();
         }
         catch   ( MalformedURLException  e )   {  e . printStackTrace ();   }
         // URL url = StdAudio.class.getResource(filename);
         if   ( url  ==   null )   throw   new   RuntimeException ( "audio "   +  filename  +   " not found" );
         AudioClip  clip  =   Applet . newAudioClip ( url );
        clip . play ();
     }


     public   static   synchronized   void  play ( final   String  filename )   {

         // code adapted from: http://stackoverflow.com/questions/26305/how-can-i-play-sound-in-java
         try   {
             System . out . println ( "trying AudioSystem.getClip()" );

             // check if file format is supported
             // (if not, will throw an UnsupportedAudioFileException)
             InputStream  is  =   PlayMusic . class . getResourceAsStream ( filename );
             AudioInputStream  ais  =   AudioSystem . getAudioInputStream ( is );

             new   Thread ( new   Runnable ()   {
                @ Override
                 public   void  run ()   {
                    stream ( filename );
                 }
             }). start ();
         }

         // let's try Applet.newAudioClip() instead
         catch   ( UnsupportedAudioFileException  e )   {
             System . out . println ( "trying Applet.newAudioClip()" );
            playApplet ( filename );
             System . out . println ( "done 2" );
             return ;
         }

         // something else went wrong
         catch   ( Exception  e )   {
             System . out . println ( e );
             System . out . println ( "Could not play "   +  filename );
         }

     }


     // https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html
     // play a wav or aif file
     // javax.sound.sampled.Clip fails for long clips (on some systems)
     private   static   void  stream ( String  filename )   {
         SourceDataLine  line  =   null ;
//        int BUFFER_SIZE = 65526; // 64K buffer
         int  BUFFER_SIZE  =   4096 ;   // 4K buffer

         try   {
             InputStream  is  =   PlayMusic . class . getResourceAsStream ( filename );
             AudioInputStream  ais  =   AudioSystem . getAudioInputStream ( is );
             AudioFormat  audioFormat  =  ais . getFormat ();
             DataLine . Info  info  =   new   DataLine . Info ( SourceDataLine . class ,  audioFormat );
            line  =   ( SourceDataLine )   AudioSystem . getLine ( info );
            line . open ( audioFormat );
            line . start ();
             byte []  samples  =   new   byte [ BUFFER_SIZE ];
             int  count  =   0 ;
             while   (( count  =  ais . read ( samples ,   0 ,  BUFFER_SIZE ))   !=   - 1 )   {
                line . write ( samples ,   0 ,  count );
             }
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
         catch   ( UnsupportedAudioFileException  e )   {
            e . printStackTrace ();
         }
         catch   ( LineUnavailableException  e )   {
            e . printStackTrace ();
         }
         finally   {
             if   ( line  !=   null )   {
                line . drain ();
                line . close ();
             }
         }
     }

     public   static   void  main ( String []  args )   {
         String  filename  =  args [ 0 ];
        play ( filename );
         System . out . println ( "done" );
     }
}

StdArrayIO.java

StdArrayIO.java

/******************************************************************************
 *  Compilation:  javac StdArrayIO.java
 *  Execution:    java StdArrayIO < input.txt
 *  Dependencies: StdOut.java
 *  Data files:    https://introcs.cs.princeton.edu/java/22library/tinyDouble1D.txt
 *                 https://introcs.cs.princeton.edu/java/22library/tinyDouble2D.txt
 *                 https://introcs.cs.princeton.edu/java/22library/tinyBoolean2D.txt
 *
 *  A library for reading in 1D and 2D arrays of integers, doubles,
 *  and booleans from standard input and printing them out to
 *  standard output.
 *
 *  % more tinyDouble1D.txt 
 *  4
 *    .000  .246  .222  -.032
 *
 *  % more tinyDouble2D.txt 
 *  4 3 
 *    .000  .270  .000 
 *    .246  .224 -.036 
 *    .222  .176  .0893 
 *   -.032  .739  .270 
 *
 *  % more tinyBoolean2D.txt 
 *  4 3 
 *    1 1 0
 *    0 0 0
 *    0 1 1
 *    1 1 1
 *
 *  % cat tinyDouble1D.txt tinyDouble2D.txt tinyBoolean2D.txt | java StdArrayIO
 *  4
 *    0.00000   0.24600   0.22200  -0.03200 
 *  
 *  4 3
 *    0.00000   0.27000   0.00000 
 *    0.24600   0.22400  -0.03600 
 *    0.22200   0.17600   0.08930 
 *    0.03200   0.73900   0.27000 
 *
 *  4 3
 *  1 1 0 
 *  0 0 0 
 *  0 1 1 
 *  1 1 1 
 *
 ******************************************************************************/


/**
 *  <i>Standard array IO</i>. This class provides methods for reading
 *  in 1D and 2D arrays from standard input and printing out to 
 *  standard output.
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/22libary">Section 2.2</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   class   StdArrayIO   {

     // it doesn't make sense to instantiate this class
     private   StdArrayIO ()   {   }

     /**
     * Reads a 1D array of doubles from standard input and returns it.
     *
     *  @return  the 1D array of doubles
     */
     public   static   double []  readDouble1D ()   {
         int  n  =   StdIn . readInt ();
         double []  a  =   new   double [ n ];
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
            a [ i ]   =   StdIn . readDouble ();
         }
         return  a ;
     }

     /**
     * Prints an array of doubles to standard output.
     *
     *  @param  a the 1D array of doubles
     */
     public   static   void  print ( double []  a )   {
         int  n  =  a . length ;
         StdOut . println ( n );
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             StdOut . printf ( "%9.5f " ,  a [ i ]);
         }
         StdOut . println ();
     }

        
     /**
     * Reads a 2D array of doubles from standard input and returns it.
     *
     *  @return  the 2D array of doubles
     */
     public   static   double [][]  readDouble2D ()   {
         int  m  =   StdIn . readInt ();
         int  n  =   StdIn . readInt ();
         double [][]  a  =   new   double [ m ][ n ];
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                a [ i ][ j ]   =   StdIn . readDouble ();
             }
         }
         return  a ;
     }

     /**
     * Prints the 2D array of doubles to standard output.
     *
     *  @param  a the 2D array of doubles
     */
     public   static   void  print ( double [][]  a )   {
         int  m  =  a . length ;
         int  n  =  a [ 0 ]. length ;
         StdOut . println ( +   " "   +  n );
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                 StdOut . printf ( "%9.5f " ,  a [ i ][ j ]);
             }
             StdOut . println ();
         }
     }


     /**
     * Reads a 1D array of integers from standard input and returns it.
     *
     *  @return  the 1D array of integers
     */
     public   static   int []  readInt1D ()   {
         int  n  =   StdIn . readInt ();
         int []  a  =   new   int [ n ];
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
            a [ i ]   =   StdIn . readInt ();
         }
         return  a ;
     }

     /**
     * Prints an array of integers to standard output.
     *
     *  @param  a the 1D array of integers
     */
     public   static   void  print ( int []  a )   {
         int  n  =  a . length ;
         StdOut . println ( n );
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             StdOut . printf ( "%9d " ,  a [ i ]);
         }
         StdOut . println ();
     }

        
     /**
     * Reads a 2D array of integers from standard input and returns it.
     *
     *  @return  the 2D array of integers
     */
     public   static   int [][]  readInt2D ()   {
         int  m  =   StdIn . readInt ();
         int  n  =   StdIn . readInt ();
         int [][]  a  =   new   int [ m ][ n ];
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                a [ i ][ j ]   =   StdIn . readInt ();
             }
         }
         return  a ;
     }

     /**
     * Print a 2D array of integers to standard output.
     *
     *  @param  a the 2D array of integers
     */
     public   static   void  print ( int [][]  a )   {
         int  m  =  a . length ;
         int  n  =  a [ 0 ]. length ;
         StdOut . println ( +   " "   +  n );
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                 StdOut . printf ( "%9d " ,  a [ i ][ j ]);
             }
             StdOut . println ();
         }
     }


     /**
     * Reads a 1D array of booleans from standard input and returns it.
     *
     *  @return  the 1D array of booleans
     */
     public   static   boolean []  readBoolean1D ()   {
         int  n  =   StdIn . readInt ();
         boolean []  a  =   new   boolean [ n ];
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
            a [ i ]   =   StdIn . readBoolean ();
         }
         return  a ;
     }

     /**
     * Prints a 1D array of booleans to standard output.
     *
     *  @param  a the 1D array of booleans
     */
     public   static   void  print ( boolean []  a )   {
         int  n  =  a . length ;
         StdOut . println ( n );
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             if   ( a [ i ])   StdOut . print ( "1 " );
             else        StdOut . print ( "0 " );
         }
         StdOut . println ();
     }

     /**
     * Reads a 2D array of booleans from standard input and returns it.
     *
     *  @return  the 2D array of booleans
     */
     public   static   boolean [][]  readBoolean2D ()   {
         int  m  =   StdIn . readInt ();
         int  n  =   StdIn . readInt ();
         boolean [][]  a  =   new   boolean [ m ][ n ];
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                a [ i ][ j ]   =   StdIn . readBoolean ();
             }
         }
         return  a ;
     }

    /**
     * Prints a 2D array of booleans to standard output.
     *
     *  @param  a the 2D array of booleans
     */
     public   static   void  print ( boolean [][]  a )   {
         int  m  =  a . length ;
         int  n  =  a [ 0 ]. length ;
         StdOut . println ( +   " "   +  n );
         for   ( int  i  =   0 ;  i  <  m ;  i ++ )   {
             for   ( int  j  =   0 ;  j  <  n ;  j ++ )   {
                 if   ( a [ i ][ j ])   StdOut . print ( "1 " );
                 else           StdOut . print ( "0 " );
             }
             StdOut . println ();
         }
     }


    /**
     * Unit tests { @code  StdArrayIO}.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         // read and print an array of doubles
         double []  a  =   StdArrayIO . readDouble1D ();
         StdArrayIO . print ( a );
         StdOut . println ();

         // read and print a matrix of doubles
         double [][]  b  =   StdArrayIO . readDouble2D ();
         StdArrayIO . print ( b );
         StdOut . println ();

         // read and print a matrix of doubles
         boolean [][]  d  =   StdArrayIO . readBoolean2D ();
         StdArrayIO . print ( d );
         StdOut . println ();
     }

}

StdAudio.java

StdAudio.java

/******************************************************************************
 *  Compilation:  javac StdAudio.java
 *  Execution:    java StdAudio
 *  Dependencies: none
 *  
 *  Simple library for reading, writing, and manipulating .wav files.
 *
 *
 *  Limitations
 *  -----------
 *    - Assumes the audio is monaural, little endian, with sampling rate
 *      of 44,100
 *    - check when reading .wav files from a .jar file ?
 *
 ******************************************************************************/

import  javax . sound . sampled . Clip ;

import  java . io . File ;
import  java . io . ByteArrayInputStream ;
import  java . io . InputStream ;
import  java . io . IOException ;

import  java . net . URL ;

import  javax . sound . sampled . AudioFileFormat ;
import  javax . sound . sampled . AudioFormat ;
import  javax . sound . sampled . AudioInputStream ;
import  javax . sound . sampled . AudioSystem ;
import  javax . sound . sampled . DataLine ;
import  javax . sound . sampled . LineUnavailableException ;
import  javax . sound . sampled . SourceDataLine ;
import  javax . sound . sampled . UnsupportedAudioFileException ;

import  javax . sound . sampled . LineListener ;
import  javax . sound . sampled . LineEvent ;

/**
 *  <i>Standard audio</i>. This class provides a basic capability for
 *  creating, reading, and saving audio. 
 *  <p>
 *  The audio format uses a sampling rate of 44,100 Hz, 16-bit, monaural.
 *
 *  <p>
 *  For additional documentation, see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i> by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   StdAudio   {

     /**
     *  The sample rate: 44,100 Hz for CD quality audio.
     */
     public   static   final   int  SAMPLE_RATE  =   44100 ;

     private   static   final   int  BYTES_PER_SAMPLE  =   2 ;         // 16-bit audio
     private   static   final   int  BITS_PER_SAMPLE  =   16 ;         // 16-bit audio
     private   static   final   double  MAX_16_BIT  =   32768 ;
     private   static   final   int  SAMPLE_BUFFER_SIZE  =   4096 ;

     private   static   final   int  MONO    =   1 ;
     private   static   final   int  STEREO  =   2 ;
     private   static   final   boolean  LITTLE_ENDIAN  =   false ;
     private   static   final   boolean  BIG_ENDIAN     =   true ;
     private   static   final   boolean  SIGNED         =   true ;
     private   static   final   boolean  UNSIGNED       =   false ;


     private   static   SourceDataLine  line ;     // to play the sound
     private   static   byte []  buffer ;           // our internal buffer
     private   static   int  bufferSize  =   0 ;      // number of samples currently in internal buffer

     private   StdAudio ()   {
         // can not instantiate
     }
   
     // static initializer
     static   {
        init ();
     }

     // open up an audio stream
     private   static   void  init ()   {
         try   {
             // 44,100 Hz, 16-bit audio, mono, signed PCM, little endian
             AudioFormat  format  =   new   AudioFormat (( float )  SAMPLE_RATE ,  BITS_PER_SAMPLE ,  MONO ,  SIGNED ,  LITTLE_ENDIAN );
             DataLine . Info  info  =   new   DataLine . Info ( SourceDataLine . class ,  format );

            line  =   ( SourceDataLine )   AudioSystem . getLine ( info );
            line . open ( format ,  SAMPLE_BUFFER_SIZE  *  BYTES_PER_SAMPLE );
            
             // the internal buffer is a fraction of the actual buffer size, this choice is arbitrary
             // it gets divided because we can't expect the buffered data to line up exactly with when
             // the sound card decides to push out its samples.
            buffer  =   new   byte [ SAMPLE_BUFFER_SIZE  *  BYTES_PER_SAMPLE / 3 ];
         }
         catch   ( LineUnavailableException  e )   {
             System . out . println ( e . getMessage ());
         }

         // no sound gets made before this call
        line . start ();
     }

     // get an AudioInputStream object from a file
     private   static   AudioInputStream  getAudioInputStreamFromFile ( String  filename )   {
         if   ( filename  ==   null )   {
             throw   new   IllegalArgumentException ( "filename is null" );
         }

         try   {
             // first try to read file from local file system
             File  file  =   new   File ( filename );
             if   ( file . exists ())   {
                 return   AudioSystem . getAudioInputStream ( file );
             }

             // resource relative to .class file
             InputStream  is1  =   StdAudio . class . getResourceAsStream ( filename );
             if   ( is1  !=   null )   {
                 return   AudioSystem . getAudioInputStream ( is1 );
             }

             // resource relative to classloader root
             InputStream  is2  =   StdAudio . class . getClassLoader (). getResourceAsStream ( filename );
             if   ( is2  !=   null )   {
                 return   AudioSystem . getAudioInputStream ( is2 );
             }

             // give up
             else   {
                 throw   new   IllegalArgumentException ( "could not read '"   +  filename  +   "'" );
             }
         }
         catch   ( IOException  e )   {
             throw   new   IllegalArgumentException ( "could not read '"   +  filename  +   "'" ,  e );
         }
         catch   ( UnsupportedAudioFileException  e )   {
             throw   new   IllegalArgumentException ( "file of unsupported audio format: '"   +  filename  +   "'" ,  e );
         }
     }

     /**
     * Closes standard audio.
     */
     public   static   void  close ()   {
        line . drain ();
        line . stop ();
     }
    
     /**
     * Writes one sample (between -1.0 and +1.0) to standard audio.
     * If the sample is outside the range, it will be clipped.
     *
     *  @param   sample the sample to play
     *  @throws  IllegalArgumentException if the sample is { @code  Double.NaN}
     */
     public   static   void  play ( double  sample )   {
         if   ( Double . isNaN ( sample ))   throw   new   IllegalArgumentException ( "sample is NaN" );

         // clip if outside [-1, +1]
         if   ( sample  <   - 1.0 )  sample  =   - 1.0 ;
         if   ( sample  >   + 1.0 )  sample  =   + 1.0 ;

         // convert to bytes
         short  s  =   ( short )   ( MAX_16_BIT  *  sample );
         if   ( sample  ==   1.0 )  s  =   Short . MAX_VALUE ;     // special case since 32768 not a short
        buffer [ bufferSize ++ ]   =   ( byte )  s ;
        buffer [ bufferSize ++ ]   =   ( byte )   ( >>   8 );     // little endian

         // send to sound card if buffer is full        
         if   ( bufferSize  >=  buffer . length )   {
            line . write ( buffer ,   0 ,  buffer . length );
            bufferSize  =   0 ;
         }
     }

     /**
     * Writes the array of samples (between -1.0 and +1.0) to standard audio.
     * If a sample is outside the range, it will be clipped.
     *
     *  @param   samples the array of samples to play
     *  @throws  IllegalArgumentException if any sample is { @code  Double.NaN}
     *  @throws  IllegalArgumentException if { @code  samples} is { @code  null}
     */
     public   static   void  play ( double []  samples )   {
         if   ( samples  ==   null )   throw   new   IllegalArgumentException ( "argument to play() is null" );
         for   ( int  i  =   0 ;  i  <  samples . length ;  i ++ )   {
            play ( samples [ i ]);
         }
     }

     /**
     * Reads audio samples from a file (in .wav or .au format) and returns
     * them as a double array with values between -1.0 and +1.0.
     * The audio file must be 16-bit with a sampling rate of 44,100.
     * It can be mono or stereo.
     *
     *  @param   filename the name of the audio file
     *  @return  the array of samples
     */
     public   static   double []  read ( String  filename )   {

         // make sure that AudioFormat is 16-bit, 44,100 Hz, little endian
         final   AudioInputStream  ais  =  getAudioInputStreamFromFile ( filename );
         AudioFormat  audioFormat  =  ais . getFormat ();

         // require sampling rate = 44,100 Hz
         if   ( audioFormat . getSampleRate ()   !=  SAMPLE_RATE )   {
             throw   new   IllegalArgumentException ( "StdAudio.read() currently supports only a sample rate of "   +  SAMPLE_RATE  +   " Hz\n"
                                              +   "audio format: "   +  audioFormat );
         }

         // require 16-bit audio
         if   ( audioFormat . getSampleSizeInBits ()   !=  BITS_PER_SAMPLE )   {
             throw   new   IllegalArgumentException ( "StdAudio.read() currently supports only "   +  BITS_PER_SAMPLE  +   "-bit audio\n"
                                              +   "audio format: "   +  audioFormat );
         }

         // require little endian
         if   ( audioFormat . isBigEndian ())   {
             throw   new   IllegalArgumentException ( "StdAudio.read() currently supports only audio stored using little endian\n"
                                              +   "audio format: "   +  audioFormat );
         }

         byte []  bytes  =   null ;
         try   {
             int  bytesToRead  =  ais . available ();
            bytes  =   new   byte [ bytesToRead ];
             int  bytesRead  =  ais . read ( bytes );
             if   ( bytesToRead  !=  bytesRead )   {
                 throw   new   IllegalStateException ( "read only "   +  bytesRead  +   " of "   +  bytesToRead  +   " bytes" );  
             }
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "could not read '"   +  filename  +   "'" ,  ioe );
         }

         int  n  =  bytes . length ;

         // little endian, mono
         if   ( audioFormat . getChannels ()   ==  MONO )   {
             double []  data  =   new   double [ n / 2 ];
             for   ( int  i  =   0 ;  i  <  n / 2 ;  i ++ )   {
                 // little endian, mono
                data [ i ]   =   (( short )   ((( bytes [ 2 * i + 1 ]   &   0xFF )   <<   8 )   |   ( bytes [ 2 * i ]   &   0xFF )))   /   (( double )  MAX_16_BIT );
             }
             return  data ;
         }

         // little endian, stereo
         else   if   ( audioFormat . getChannels ()   ==  STEREO )   {
             double []  data  =   new   double [ n / 4 ];
             for   ( int  i  =   0 ;  i  <  n / 4 ;  i ++ )   {
                 double  left   =   (( short )   ((( bytes [ 4 * i + 1 ]   &   0xFF )   <<   8 )   |   ( bytes [ 4 * +   0 ]   &   0xFF )))   /   (( double )  MAX_16_BIT );
                 double  right  =   (( short )   ((( bytes [ 4 * i + 3 ]   &   0xFF )   <<   8 )   |   ( bytes [ 4 * +   2 ]   &   0xFF )))   /   (( double )  MAX_16_BIT );
                data [ i ]   =   ( left  +  right )   /   2.0 ;
             }
             return  data ;
         }

         // TODO: handle big endian (or other formats)
         else   throw   new   IllegalStateException ( "audio format is neither mono or stereo" );
     }

     /**
     * Saves the double array as an audio file (using .wav or .au format).
     *
     *  @param   filename the name of the audio file
     *  @param   samples the array of samples
     *  @throws  IllegalArgumentException if unable to save { @code  filename}
     *  @throws  IllegalArgumentException if { @code  samples} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  filename} extension is not { @code  .wav}
     *         or { @code  .au}
     */
     public   static   void  save ( String  filename ,   double []  samples )   {
         if   ( filename  ==   null )   {
             throw   new   IllegalArgumentException ( "filenameis null" );
         }
         if   ( samples  ==   null )   {
             throw   new   IllegalArgumentException ( "samples[] is null" );
         }

         // assumes 16-bit samples with sample rate = 44,100 Hz
         // use 16-bit audio, mono, signed PCM, little Endian
         AudioFormat  format  =   new   AudioFormat ( SAMPLE_RATE ,   16 ,  MONO ,  SIGNED ,  LITTLE_ENDIAN );
         byte []  data  =   new   byte [ 2   *  samples . length ];
         for   ( int  i  =   0 ;  i  <  samples . length ;  i ++ )   {
             int  temp  =   ( short )   ( samples [ i ]   *  MAX_16_BIT );
             if   ( samples [ i ]   ==   1.0 )  temp  =   Short . MAX_VALUE ;     // special case since 32768 not a short
            data [ 2 * +   0 ]   =   ( byte )  temp ;
            data [ 2 * +   1 ]   =   ( byte )   ( temp  >>   8 );     // little endian
         }

         // now save the file
         try   {
             ByteArrayInputStream  bais  =   new   ByteArrayInputStream ( data );
             AudioInputStream  ais  =   new   AudioInputStream ( bais ,  format ,  samples . length );
             if   ( filename . endsWith ( ".wav" )   ||  filename . endsWith ( ".WAV" ))   {
                 AudioSystem . write ( ais ,   AudioFileFormat . Type . WAVE ,   new   File ( filename ));
             }
             else   if   ( filename . endsWith ( ".au" )   ||  filename . endsWith ( ".AU" ))   {
                 AudioSystem . write ( ais ,   AudioFileFormat . Type . AU ,   new   File ( filename ));
             }
             else   {
                 throw   new   IllegalArgumentException ( "file type for saving must be .wav or .au" );
             }
         }
         catch   ( IOException  ioe )   {
             throw   new   IllegalArgumentException ( "unable to save file '"   +  filename  +   "'" ,  ioe );
         }
     }



     /**
     * Plays an audio file (in .wav, .mid, or .au format) in a background thread.
     *
     *  @param  filename the name of the audio file
     *  @throws  IllegalArgumentException if unable to play { @code  filename}
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   static   synchronized   void  play ( final   String  filename )   {
         new   Thread ( new   Runnable ()   {
             public   void  run ()   {
                 AudioInputStream  ais  =  getAudioInputStreamFromFile ( filename );
                stream ( ais );
             }
         }). start ();
     }


     // https://www3.ntu.edu.sg/home/ehchua/programming/java/J8c_PlayingSound.html
     // play a wav or aif file
     // javax.sound.sampled.Clip fails for long clips (on some systems), perhaps because
     // JVM closes (see remedy in loop)
     private   static   void  stream ( AudioInputStream  ais )   {
         SourceDataLine  line  =   null ;
         int  BUFFER_SIZE  =   4096 ;   // 4K buffer

         try   {
             AudioFormat  audioFormat  =  ais . getFormat ();
             DataLine . Info  info  =   new   DataLine . Info ( SourceDataLine . class ,  audioFormat );
            line  =   ( SourceDataLine )   AudioSystem . getLine ( info );
            line . open ( audioFormat );
            line . start ();
             byte []  samples  =   new   byte [ BUFFER_SIZE ];
             int  count  =   0 ;
             while   (( count  =  ais . read ( samples ,   0 ,  BUFFER_SIZE ))   !=   - 1 )   {
                line . write ( samples ,   0 ,  count );
             }
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }
         catch   ( LineUnavailableException  e )   {
            e . printStackTrace ();
         }
         finally   {
             if   ( line  !=   null )   {
                line . drain ();
                line . close ();
             }
         }
     }

     /**
     * Loops an audio file (in .wav, .mid, or .au format) in a background thread.
     *
     *  @param  filename the name of the audio file
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   static   synchronized   void  loop ( String  filename )   {
         if   ( filename  ==   null )   throw   new   IllegalArgumentException ();

         final   AudioInputStream  ais  =  getAudioInputStreamFromFile ( filename );

         try   {
             Clip  clip  =   AudioSystem . getClip ();
             // Clip clip = (Clip) AudioSystem.getLine(new Line.Info(Clip.class));
            clip . open ( ais );
            clip . loop ( Clip . LOOP_CONTINUOUSLY );
         }
         catch   ( LineUnavailableException  e )   {
            e . printStackTrace ();
         }
         catch   ( IOException  e )   {
            e . printStackTrace ();
         }

         // keep JVM open
         new   Thread ( new   Runnable ()   {
             public   void  run ()   {
                 while   ( true )   {
                     try   {
                        Thread . sleep ( 1000 );
                     }
                     catch   ( InterruptedException  e )   {
                        e . printStackTrace ();
                     }
                 }
             }
         }). start ();
     }


    /***************************************************************************
    * Unit tests { @code  StdAudio}.
    ***************************************************************************/

     // create a note (sine wave) of the given frequency (Hz), for the given
     // duration (seconds) scaled to the given volume (amplitude)
     private   static   double []  note ( double  hz ,   double  duration ,   double  amplitude )   {
         int  n  =   ( int )   ( StdAudio . SAMPLE_RATE  *  duration );
         double []  a  =   new   double [ n + 1 ];
         for   ( int  i  =   0 ;  i  <=  n ;  i ++ )
            a [ i ]   =  amplitude  *   Math . sin ( 2   *   Math . PI  *  i  *  hz  /   StdAudio . SAMPLE_RATE );
         return  a ;
     }

     /**
     * Test client - play an A major scale to standard audio.
     *
     *  @param  args the command-line arguments
     */
     /**
     * Test client - play an A major scale to standard audio.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
        
         // 440 Hz for 1 sec
         double  freq  =   440.0 ;
         for   ( int  i  =   0 ;  i  <=   StdAudio . SAMPLE_RATE ;  i ++ )   {
             StdAudio . play ( 0.5   *   Math . sin ( 2 * Math . PI  *  freq  *  i  /   StdAudio . SAMPLE_RATE ));
         }
        
         // scale increments
         int []  steps  =   {   0 ,   2 ,   4 ,   5 ,   7 ,   9 ,   11 ,   12   };
         for   ( int  i  =   0 ;  i  <  steps . length ;  i ++ )   {
             double  hz  =   440.0   *   Math . pow ( 2 ,  steps [ i ]   /   12.0 );
             StdAudio . play ( note ( hz ,   1.0 ,   0.5 ));
         }


         // need to call this in non-interactive stuff so the program doesn't terminate
         // until all the sound leaves the speaker.
         StdAudio . close ();  
     }
}

StdDraw.java

StdDraw.java

/******************************************************************************
 *  Compilation:  javac StdDraw.java
 *  Execution:    java StdDraw
 *  Dependencies: none
 *
 *  Standard drawing library. This class provides a basic capability for
 *  creating drawings with your programs. It uses a simple graphics model that
 *  allows you to create drawings consisting of points, lines, and curves
 *  in a window on your computer and to save the drawings to a file.
 *
 *  Todo
 *  ----
 *    -  Add support for gradient fill, etc.
 *    -  Fix setCanvasSize() so that it can only be called once.
 *    -  On some systems, drawing a line (or other shape) that extends way
 *       beyond canvas (e.g., to infinity) dimensions does not get drawn.
 *
 *  Remarks
 *  -------
 *    -  don't use AffineTransform for rescaling since it inverts
 *       images and strings
 *
 ******************************************************************************/

import  java . awt . BasicStroke ;
import  java . awt . Color ;
import  java . awt . Component ;
import  java . awt . FileDialog ;
import  java . awt . Font ;
import  java . awt . FontMetrics ;
import  java . awt . Graphics ;
import  java . awt . Graphics2D ;
import  java . awt . Image ;
import  java . awt . MediaTracker ;
import  java . awt . RenderingHints ;
import  java . awt . Toolkit ;

import  java . awt . event . ActionEvent ;
import  java . awt . event . ActionListener ;
import  java . awt . event . MouseEvent ;
import  java . awt . event . MouseListener ;
import  java . awt . event . MouseMotionListener ;
import  java . awt . event . KeyEvent ;
import  java . awt . event . KeyListener ;

import  java . awt . geom . Arc2D ;
import  java . awt . geom . Ellipse2D ;
import  java . awt . geom . GeneralPath ;
import  java . awt . geom . Line2D ;
import  java . awt . geom . Rectangle2D ;

import  java . awt . image . BufferedImage ;
import  java . awt . image . DirectColorModel ;
import  java . awt . image . WritableRaster ;

import  java . io . File ;
import  java . io . IOException ;

import  java . net . MalformedURLException ;
import  java . net . URL ;

import  java . util . LinkedList ;
import  java . util . TreeSet ;
import  java . util . NoSuchElementException ;
import  javax . imageio . ImageIO ;

import  javax . swing . ImageIcon ;
import  javax . swing . JFrame ;
import  javax . swing . JLabel ;
import  javax . swing . JMenu ;
import  javax . swing . JMenuBar ;
import  javax . swing . JMenuItem ;
import  javax . swing . KeyStroke ;

/**
 *  The { @code  StdDraw} class provides a basic capability for
 *  creating drawings with your programs. It uses a simple graphics model that
 *  allows you to create drawings consisting of points, lines, squares, 
 *  circles, and other geometric shapes in a window on your computer and
 *  to save the drawings to a file. Standard drawing also includes
 *  facilities for text, color, pictures, and animation, along with
 *  user interaction via the keyboard and mouse.
 *  <p>
 *  <b>Getting started.</b>
 *  To use this class, you must have { @code  StdDraw.class} in your
 *  Java classpath. If you used our autoinstaller, you should be all set.
 *  Otherwise, either download
 *  <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
 *  and add to your Java classpath or download
 *  <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdDraw.java">StdDraw.java</a>
 *  and put a copy in your working directory.
 *  <p>
 *  Now, type the following short program into your editor:
 *  <pre>
 *   public class TestStdDraw {
 *       public static void main(String[] args) {
 *           StdDraw.setPenRadius(0.05);
 *           StdDraw.setPenColor(StdDraw.BLUE);
 *           StdDraw.point(0.5, 0.5);
 *           StdDraw.setPenColor(StdDraw.MAGENTA);
 *           StdDraw.line(0.2, 0.2, 0.8, 0.2);
 *       }
 *   }
 *  </pre>
 *  If you compile and execute the program, you should see a window
 *  appear with a thick magenta line and a blue point.
 *  This program illustrates the two main types of methods in standard
 *  drawing—methods that draw geometric shapes and methods that
 *  control drawing parameters.
 *  The methods { @code  StdDraw.line()} and { @code  StdDraw.point()}
 *  draw lines and points; the methods { @code  StdDraw.setPenRadius()}
 *  and { @code  StdDraw.setPenColor()} control the line thickness and color.
 *  <p>
 *  <b>Points and lines.</b>
 *  You can draw points and line segments with the following methods:
 *  <ul>
 *  <li> { @link  #point(double x, double y)}
 *  <li> { @link  #line(double x1, double y1, double x2, double y2)}
 *  </ul>
 *  <p>
 *  The <em>x</em>- and <em>y</em>-coordinates must be in the drawing area
 *  (between 0 and 1 and by default) or the points and lines will not be visible.
 *  <p>
 *  <b>Squares, circles, rectangles, and ellipses.</b>
 *  You can draw squares, circles, rectangles, and ellipses using
 *  the following methods:
 *  <ul>
 *  <li> { @link  #circle(double x, double y, double radius)}
 *  <li> { @link  #ellipse(double x, double y, double semiMajorAxis, double semiMinorAxis)}
 *  <li> { @link  #square(double x, double y, double halfLength)}
 *  <li> { @link  #rectangle(double x, double y, double halfWidth, double halfHeight)}
 *  </ul>
 *  <p>
 *  All of these methods take as arguments the location and size of the shape.
 *  The location is always specified by the <em>x</em>- and <em>y</em>-coordinates
 *  of its <em>center</em>.
 *  The size of a circle is specified by its radius and the size of an ellipse is
 *  specified by the lengths of its semi-major and semi-minor axes.
 *  The size of a square or rectangle is specified by its half-width or half-height.
 *  The convention for drawing squares and rectangles is parallel to those for
 *  drawing circles and ellipses, but may be unexpected to the uninitiated.
 *  <p>
 *  The methods above trace outlines of the given shapes. The following methods
 *  draw filled versions:
 *  <ul>
 *  <li> { @link  #filledCircle(double x, double y, double radius)}
 *  <li> { @link  #filledEllipse(double x, double y, double semiMajorAxis, double semiMinorAxis)}
 *  <li> { @link  #filledSquare(double x, double y, double radius)}
 *  <li> { @link  #filledRectangle(double x, double y, double halfWidth, double halfHeight)}
 *  </ul>
 *  <p>
 *  <b>Circular arcs.</b>
 *  You can draw circular arcs with the following method:
 *  <ul>
 *  <li> { @link  #arc(double x, double y, double radius, double angle1, double angle2)}
 *  </ul>
 *  <p>
 *  The arc is from the circle centered at (<em>x</em>, <em>y</em>) of the specified radius.
 *  The arc extends from angle1 to angle2. By convention, the angles are
 *  <em>polar</em> (counterclockwise angle from the <em>x</em>-axis)
 *  and represented in degrees. For example, { @code  StdDraw.arc(0.0, 0.0, 1.0, 0, 90)}
 *  draws the arc of the unit circle from 3 o'clock (0 degrees) to 12 o'clock (90 degrees).
 *  <p>
 *  <b>Polygons.</b>
 *  You can draw polygons with the following methods:
 *  <ul>
 *  <li> { @link  #polygon(double[] x, double[] y)}
 *  <li> { @link  #filledPolygon(double[] x, double[] y)}
 *  </ul>
 *  <p>
 *  The points in the polygon are ({ @code  x[i]}, { @code  y[i]}).
 *  For example, the following code fragment draws a filled diamond
 *  with vertices (0.1, 0.2), (0.2, 0.3), (0.3, 0.2), and (0.2, 0.1):
 *  <pre>
 *   double[] x = { 0.1, 0.2, 0.3, 0.2 };
 *   double[] y = { 0.2, 0.3, 0.2, 0.1 };
 *   StdDraw.filledPolygon(x, y);
 *  </pre>
 *  <p>
 *  <b>Pen size.</b>
 *  The pen is circular, so that when you set the pen radius to <em>r</em>
 *  and draw a point, you get a circle of radius <em>r</em>. Also, lines are
 *  of thickness 2<em>r</em> and have rounded ends. The default pen radius
 *  is 0.005 and is not affected by coordinate scaling. This default pen
 *  radius is about 1/200 the width of the default canvas, so that if
 *  you draw 100 points equally spaced along a horizontal or vertical line,
 *  you will be able to see individual circles, but if you draw 200 such
 *  points, the result will look like a line.
 *  <ul>
 *  <li> { @link  #setPenRadius(double radius)}
 *  </ul>
 *  <p>
 *  For example, { @code  StdDraw.setPenRadius(0.025)} makes
 *  the thickness of the lines and the size of the points to be five times
 *  the 0.005 default.
 *  To draw points with the minimum possible radius (one pixel on typical
 *  displays), set the pen radius to 0.0.
 *  <p>
 *  <b>Pen color.</b>
 *  All geometric shapes (such as points, lines, and circles) are drawn using
 *  the current pen color. By default, it is black.
 *  You can change the pen color with the following methods:
 *  <ul>
 *  <li> { @link  #setPenColor(int red, int green, int blue)}
 *  <li> { @link  #setPenColor(Color color)}
 *  </ul>
 *  <p>
 *  The first method allows you to specify colors using the RGB color system.
 *  This <a href = "http://johndyer.name/lab/colorpicker/">color picker</a>
 *  is a convenient way to find a desired color.
 *  The second method allows you to specify colors using the
 *  { @link  Color} data type that is discussed in Chapter 3. Until then,
 *  you can use this method with one of these predefined colors in standard drawing:
 *  { @link  #BLACK}, { @link  #BLUE}, { @link  #CYAN}, { @link  #DARK_GRAY}, { @link  #GRAY},
 *  { @link  #GREEN}, { @link  #LIGHT_GRAY}, { @link  #MAGENTA}, { @link  #ORANGE},
 *  { @link  #PINK}, { @link  #RED}, { @link  #WHITE}, { @link  #YELLOW},
 *  { @link  #BOOK_BLUE}, { @link  #BOOK_LIGHT_BLUE}, { @link  #BOOK_RED}, and
 *  { @link  #PRINCETON_ORANGE}.
 *  For example, { @code  StdDraw.setPenColor(StdDraw.MAGENTA)} sets the
 *  pen color to magenta.
 *  <p>
 *  <b>Canvas size.</b>
 *  By default, all drawing takes places in a 512-by-512 canvas.
 *  The canvas does not include the window title or window border.
 *  You can change the size of the canvas with the following method:
 *  <ul>
 *  <li> { @link  #setCanvasSize(int width, int height)}
 *  </ul>
 *  <p>
 *  This sets the canvas size to be <em>width</em>-by-<em>height</em> pixels.
 *  It also erases the current drawing and resets the coordinate system,
 *  pen radius, pen color, and font back to their default values.
 *  Ordinarly, this method is called once, at the very beginning of a program.
 *  For example, { @code  StdDraw.setCanvasSize(800, 800)}
 *  sets the canvas size to be 800-by-800 pixels.
 *  <p>
 *  <b>Canvas scale and coordinate system.</b>
 *  By default, all drawing takes places in the unit square, with (0, 0) at
 *  lower left and (1, 1) at upper right. You can change the default
 *  coordinate system with the following methods:
 *  <ul>
 *  <li> { @link  #setXscale(double xmin, double xmax)}
 *  <li> { @link  #setYscale(double ymin, double ymax)}
 *  <li> { @link  #setScale(double min, double max)}
 *  </ul>
 *  <p>
 *  The arguments are the coordinates of the minimum and maximum 
 *  <em>x</em>- or <em>y</em>-coordinates that will appear in the canvas.
 *  For example, if you  wish to use the default coordinate system but
 *  leave a small margin, you can call { @code  StdDraw.setScale(-.05, 1.05)}.
 *  <p>
 *  These methods change the coordinate system for subsequent drawing
 *  commands; they do not affect previous drawings.
 *  These methods do not change the canvas size; so, if the <em>x</em>-
 *  and <em>y</em>-scales are different, squares will become rectangles
 *  and circles will become ellipses.
 *  <p>
 *  <b>Text.</b>
 *  You can use the following methods to annotate your drawings with text:
 *  <ul>
 *  <li> { @link  #text(double x, double y, String text)}
 *  <li> { @link  #text(double x, double y, String text, double degrees)}
 *  <li> { @link  #textLeft(double x, double y, String text)}
 *  <li> { @link  #textRight(double x, double y, String text)}
 *  </ul>
 *  <p>
 *  The first two methods write the specified text in the current font,
 *  centered at (<em>x</em>, <em>y</em>).
 *  The second method allows you to rotate the text.
 *  The last two methods either left- or right-align the text at (<em>x</em>, <em>y</em>).
 *  <p>
 *  The default font is a Sans Serif font with point size 16.
 *  You can use the following method to change the font:
 *  <ul>
 *  <li> { @link  #setFont(Font font)}
 *  </ul>
 *  <p>
 *  You use the { @link  Font} data type to specify the font. This allows you to
 *  choose the face, size, and style of the font. For example, the following
 *  code fragment sets the font to Arial Bold, 60 point.
 *  <pre>
 *   Font font = new Font("Arial", Font.BOLD, 60);
 *   StdDraw.setFont(font);
 *   StdDraw.text(0.5, 0.5, "Hello, World");
 *  </pre>
 *  <p>
 *  <b>Images.</b>
 *  You can use the following methods to add images to your drawings:
 *  <ul>
 *  <li> { @link  #picture(double x, double y, String filename)}
 *  <li> { @link  #picture(double x, double y, String filename, double degrees)}
 *  <li> { @link  #picture(double x, double y, String filename, double scaledWidth, double scaledHeight)}
 *  <li> { @link  #picture(double x, double y, String filename, double scaledWidth, double scaledHeight, double degrees)}
 *  </ul>
 *  <p>
 *  These methods draw the specified image, centered at (<em>x</em>, <em>y</em>).
 *  The supported image formats are JPEG, PNG, and GIF.
 *  The image will display at its native size, independent of the coordinate system.
 *  Optionally, you can rotate the image a specified number of degrees counterclockwise
 *  or rescale it to fit snugly inside a width-by-height bounding box.
 *  <p>
 *  <b>Saving to a file.</b>
 *  You save your image to a file using the <em>File → Save</em> menu option.
 *  You can also save a file programatically using the following method:
 *  <ul>
 *  <li> { @link  #save(String filename)}
 *  </ul>
 *  <p>
 *  The supported image formats are JPEG and PNG. The filename must have either the
 *  extension .jpg or .png.
 *  We recommend using PNG for drawing that consist solely of geometric shapes and JPEG 
 *  for drawings that contains pictures.
 *  <p>
 *  <b>Clearing the canvas.</b>
 *  To clear the entire drawing canvas, you can use the following methods:
 *  <ul>
 *  <li> { @link  #clear()}
 *  <li> { @link  #clear(Color color)}
 *  </ul>
 *  <p>
 *  The first method clears the canvas to white; the second method
 *  allows you to specify a color of your choice. For example,
 *  { @code  StdDraw.clear(StdDraw.LIGHT_GRAY)} clears the canvas to a shade
 *  of gray.
 *  <p>
 *  <b>Computer animations and double buffering.</b>
 *  Double buffering is one of the most powerful features of standard drawing,
 *  enabling computer animations.
 *  The following methods control the way in which objects are drawn:
 *  <ul>
 *  <li> { @link  #enableDoubleBuffering()}
 *  <li> { @link  #disableDoubleBuffering()}
 *  <li> { @link  #show()}
 *  <li> { @link  #pause(int t)}
 *  </ul>
 *  <p>
 *  By default, double buffering is disabled, which means that as soon as you
 *  call a drawing
 *  method—such as { @code  point()} or { @code  line()}—the
 *  results appear on the screen.
 *  <p>
 *  When double buffering is enabled by calling { @link  #enableDoubleBuffering()},
 *  all drawing takes place on the <em>offscreen canvas</em>. The offscreen canvas
 *  is not displayed. Only when you call
 *  { @link  #show()} does your drawing get copied from the offscreen canvas to
 *  the onscreen canvas, where it is displayed in the standard drawing window. You 
 *  can think of double buffering as collecting all of the lines, points, shapes,
 *  and text that you tell it to draw, and then drawing them all
 *  <em>simultaneously</em>, upon request.
 *  <p>
 *  The most important use of double buffering is to produce computer
 *  animations, creating the illusion of motion by rapidly
 *  displaying static drawings. To produce an animation, repeat
 *  the following four steps:
 *  <ul>
 *  <li> Clear the offscreen canvas.
 *  <li> Draw objects on the offscreen canvas.
 *  <li> Copy the offscreen canvas to the onscreen canvas.
 *  <li> Wait for a short while.
 *  </ul>
 *  <p>
 *  The { @link  #clear()}, { @link  #show()}, and { @link  #pause(int t)} methods
 *  support the first, third, and fourth of these steps, respectively.
 *  <p>
 *  For example, this code fragment animates two balls moving in a circle.
 *  <pre>
 *   StdDraw.setScale(-2, +2);
 *   StdDraw.enableDoubleBuffering();
 *
 *   for (double t = 0.0; true; t += 0.02) {
 *       double x = Math.sin(t);
 *       double y = Math.cos(t);
 *       StdDraw.clear();
 *       StdDraw.filledCircle(x, y, 0.05);
 *       StdDraw.filledCircle(-x, -y, 0.05);
 *       StdDraw.show();
 *       StdDraw.pause(20);
 *   }
 *  </pre>
 *  <p>
 *  <b>Keyboard and mouse inputs.</b>
 *  Standard drawing has very basic support for keyboard and mouse input.
 *  It is much less powerful than most user interface libraries provide, but also much simpler.
 *  You can use the following methods to intercept mouse events:
 *  <ul>
 *  <li> { @link  #isMousePressed()}
 *  <li> { @link  #mouseX()}
 *  <li> { @link  #mouseY()}
 *  </ul>
 *  <p>
 *  The first method tells you whether a mouse button is currently being pressed.
 *  The last two methods tells you the <em>x</em>- and <em>y</em>-coordinates of the mouse's
 *  current position, using the same coordinate system as the canvas (the unit square, by default).
 *  You should use these methods in an animation loop that waits a short while before trying
 *  to poll the mouse for its current state.
 *  You can use the following methods to intercept keyboard events:
 *  <ul>
 *  <li> { @link  #hasNextKeyTyped()}
 *  <li> { @link  #nextKeyTyped()}
 *  <li> { @link  #isKeyPressed(int keycode)}
 *  </ul>
 *  <p>
 *  If the user types lots of keys, they will be saved in a list until you process them.
 *  The first method tells you whether the user has typed a key (that your program has
 *  not yet processed).
 *  The second method returns the next key that the user typed (that your program has
 *  not yet processed) and removes it from the list of saved keystrokes.
 *  The third method tells you whether a key is currently being pressed.
 *  <p>
 *  <b>Accessing control parameters.</b>
 *  You can use the following methods to access the current pen color, pen radius,
 *  and font:
 *  <ul>
 *  <li> { @link  #getPenColor()}
 *  <li> { @link  #getPenRadius()}
 *  <li> { @link  #getFont()}
 *  </ul>
 *  <p>
 *  These methods are useful when you want to temporarily change a
 *  control parameter and reset it back to its original value.
 *  <p>
 *  <b>Corner cases.</b>
 *  Here are some corner cases.
 *  <ul>
 *  <li> Drawing an object outside (or partly outside) the canvas is permitted.
 *       However, only the part of the object that appears inside the canvas
 *       will be visible.
 *  <li> Any method that is passed a { @code  null} argument will throw an
 *       { @link  IllegalArgumentException}.
 *  <li> Any method that is passed a { @link  Double#NaN},
 *       { @link  Double#POSITIVE_INFINITY}, or { @link  Double#NEGATIVE_INFINITY}
 *       argument will throw an { @link  IllegalArgumentException}.
 *  <li> Due to floating-point issues, an object drawn with an <em>x</em>- or
 *       <em>y</em>-coordinate that is way outside the canvas (such as the line segment
 *       from (0.5, –10^308) to (0.5, 10^308) may not be visible even in the
 *       part of the canvas where it should be.
 *  </ul>
 *  <p>
 *  <b>Performance tricks.</b>
 *  Standard drawing is capable of drawing large amounts of data.
 *  Here are a few tricks and tips:
 *  <ul>
 *  <li> Use <em>double buffering</em> for static drawing with a large
 *       number of objects.
 *       That is, call { @link  #enableDoubleBuffering()} before
 *       the sequence of drawing commands and call { @link  #show()} afterwards.
 *       Incrementally displaying a complex drawing while it is being
 *       created can be intolerably inefficient on many computer systems.
 *  <li> When drawing computer animations, call { @code  show()}
 *       only once per frame, not after drawing each individual object.
 *  <li> If you call { @code  picture()} multiple times with the same filename,
 *       Java will cache the image, so you do not incur the cost of reading
 *       from a file each time.
 *  </ul>
 *  <p>
 *  <b>Known bugs and issues.</b>
 *  <ul>
 *  <li> The { @code  picture()} methods may not draw the portion of the image that is
 *       inside the canvas if the center point (<em>x</em>, <em>y</em>) is outside the
 *       canvas.
 *       This bug appears only on some systems.
 *  </ul>
 *  <p>
 *  <b>Reference.</b>
 *  For additional documentation,
 *  see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
 *  <em>Computer Science: An Interdisciplinary Approach</em>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   StdDraw   implements   ActionListener ,   MouseListener ,   MouseMotionListener ,   KeyListener   {

     /**
     *  The color black.
     */
     public   static   final   Color  BLACK  =   Color . BLACK ;

     /**
     *  The color blue.
     */
     public   static   final   Color  BLUE  =   Color . BLUE ;

     /**
     *  The color cyan.
     */
     public   static   final   Color  CYAN  =   Color . CYAN ;

     /**
     *  The color dark gray.
     */
     public   static   final   Color  DARK_GRAY  =   Color . DARK_GRAY ;

     /**
     *  The color gray.
     */
     public   static   final   Color  GRAY  =   Color . GRAY ;

     /**
     *  The color green.
     */
     public   static   final   Color  GREEN   =   Color . GREEN ;

     /**
     *  The color light gray.
     */
     public   static   final   Color  LIGHT_GRAY  =   Color . LIGHT_GRAY ;

     /**
     *  The color magenta.
     */
     public   static   final   Color  MAGENTA  =   Color . MAGENTA ;

     /**
     *  The color orange.
     */
     public   static   final   Color  ORANGE  =   Color . ORANGE ;

     /**
     *  The color pink.
     */
     public   static   final   Color  PINK  =   Color . PINK ;

     /**
     *  The color red.
     */
     public   static   final   Color  RED  =   Color . RED ;

     /**
     *  The color white.
     */
     public   static   final   Color  WHITE  =   Color . WHITE ;

     /**
     *  The color yellow.
     */
     public   static   final   Color  YELLOW  =   Color . YELLOW ;

     /**
     * Shade of blue used in <em>Introduction to Programming in Java</em>.
     * It is Pantone 300U. The RGB values are approximately (9, 90, 166).
     */
     public   static   final   Color  BOOK_BLUE  =   new   Color ( 9 ,   90 ,   166 );

     /**
     * Shade of light blue used in <em>Introduction to Programming in Java</em>.
     * The RGB values are approximately (103, 198, 243).
     */
     public   static   final   Color  BOOK_LIGHT_BLUE  =   new   Color ( 103 ,   198 ,   243 );

     /**
     * Shade of red used in <em>Algorithms, 4th edition</em>.
     * It is Pantone 1805U. The RGB values are approximately (150, 35, 31).
     */
     public   static   final   Color  BOOK_RED  =   new   Color ( 150 ,   35 ,   31 );

     /**
     * Shade of orange used in Princeton University's identity.
     * It is PMS 158. The RGB values are approximately (245, 128, 37).
     */
     public   static   final   Color  PRINCETON_ORANGE  =   new   Color ( 245 ,   128 ,   37 );

     // default colors
     private   static   final   Color  DEFAULT_PEN_COLOR    =  BLACK ;
     private   static   final   Color  DEFAULT_CLEAR_COLOR  =  WHITE ;

     // current pen color
     private   static   Color  penColor ;

     // default canvas size is DEFAULT_SIZE-by-DEFAULT_SIZE
     private   static   final   int  DEFAULT_SIZE  =   512 ;
     private   static   int  width   =  DEFAULT_SIZE ;
     private   static   int  height  =  DEFAULT_SIZE ;

     // default pen radius
     private   static   final   double  DEFAULT_PEN_RADIUS  =   0.002 ;

     // current pen radius
     private   static   double  penRadius ;

     // show we draw immediately or wait until next show?
     private   static   boolean  defer  =   false ;

     // boundary of drawing canvas, 0% border
     // private static final double BORDER = 0.05;
     private   static   final   double  BORDER  =   0.00 ;
     private   static   final   double  DEFAULT_XMIN  =   0.0 ;
     private   static   final   double  DEFAULT_XMAX  =   1.0 ;
     private   static   final   double  DEFAULT_YMIN  =   0.0 ;
     private   static   final   double  DEFAULT_YMAX  =   1.0 ;
     private   static   double  xmin ,  ymin ,  xmax ,  ymax ;

     // for synchronization
     private   static   Object  mouseLock  =   new   Object ();
     private   static   Object  keyLock  =   new   Object ();

     // default font
     private   static   final   Font  DEFAULT_FONT  =   new   Font ( "SansSerif" ,   Font . PLAIN ,   16 );

     // current font
     private   static   Font  font ;

     // double buffered graphics
     private   static   BufferedImage  offscreenImage ,  onscreenImage ;
     private   static   Graphics2D  offscreen ,  onscreen ;

     // singleton for callbacks: avoids generation of extra .class files
     private   static   StdDraw  std  =   new   StdDraw ();

     // the frame for drawing to the screen
     private   static   JFrame  frame ;

     // mouse state
     private   static   boolean  isMousePressed  =   false ;
     private   static   double  mouseX  =   0 ;
     private   static   double  mouseY  =   0 ;

     // queue of typed key characters
     private   static   LinkedList < Character >  keysTyped  =   new   LinkedList < Character > ();

     // set of key codes currently pressed down
     private   static   TreeSet < Integer >  keysDown  =   new   TreeSet < Integer > ();

     // singleton pattern: client can't instantiate
     private   StdDraw ()   {   }


     // static initializer
     static   {
        init ();
     }

     /**
     * Sets the canvas (drawing area) to be 512-by-512 pixels.
     * This also erases the current drawing and resets the coordinate system,
     * pen radius, pen color, and font back to their default values.
     * Ordinarly, this method is called once, at the very beginning
     * of a program.
     */
     public   static   void  setCanvasSize ()   {
        setCanvasSize ( DEFAULT_SIZE ,  DEFAULT_SIZE );
     }

     /**
     * Sets the canvas (drawing area) to be <em>width</em>-by-<em>height</em> pixels.
     * This also erases the current drawing and resets the coordinate system,
     * pen radius, pen color, and font back to their default values.
     * Ordinarly, this method is called once, at the very beginning
     * of a program.
     *
     *  @param   canvasWidth the width as a number of pixels
     *  @param   canvasHeight the height as a number of pixels
     *  @throws  IllegalArgumentException unless both { @code  canvasWidth} and
     *         { @code  canvasHeight} are positive
     */
     public   static   void  setCanvasSize ( int  canvasWidth ,   int  canvasHeight )   {
         if   ( canvasWidth  <=   0 )   throw   new   IllegalArgumentException ( "width must be positive" );
         if   ( canvasHeight  <=   0 )   throw   new   IllegalArgumentException ( "height must be positive" );
        width  =  canvasWidth ;
        height  =  canvasHeight ;
        init ();
     }

     // init
     private   static   void  init ()   {
         if   ( frame  !=   null )  frame . setVisible ( false );
        frame  =   new   JFrame ();
        offscreenImage  =   new   BufferedImage ( 2 * width ,   2 * height ,   BufferedImage . TYPE_INT_ARGB );
        onscreenImage   =   new   BufferedImage ( 2 * width ,   2 * height ,   BufferedImage . TYPE_INT_ARGB );
        offscreen  =  offscreenImage . createGraphics ();
        onscreen   =  onscreenImage . createGraphics ();
        offscreen . scale ( 2.0 ,   2.0 );    // since we made it 2x as big

        setXscale ();
        setYscale ();
        offscreen . setColor ( DEFAULT_CLEAR_COLOR );
        offscreen . fillRect ( 0 ,   0 ,  width ,  height );
        setPenColor ();
        setPenRadius ();
        setFont ();
        clear ();

         // add antialiasing
         RenderingHints  hints  =   new   RenderingHints ( RenderingHints . KEY_ANTIALIASING ,
                                                   RenderingHints . VALUE_ANTIALIAS_ON );
        hints . put ( RenderingHints . KEY_RENDERING ,   RenderingHints . VALUE_RENDER_QUALITY );
        offscreen . addRenderingHints ( hints );

         // frame stuff
         RetinaImageIcon  icon  =   new   RetinaImageIcon ( onscreenImage );
         JLabel  draw  =   new   JLabel ( icon );

        draw . addMouseListener ( std );
        draw . addMouseMotionListener ( std );

        frame . setContentPane ( draw );
        frame . addKeyListener ( std );      // JLabel cannot get keyboard focus
        frame . setFocusTraversalKeysEnabled ( false );    // allow VK_TAB with isKeyPressed()
        frame . setResizable ( false );
        frame . setDefaultCloseOperation ( JFrame . EXIT_ON_CLOSE );              // closes all windows
         // frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);      // closes only current window
        frame . setTitle ( "Standard Draw" );
        frame . setJMenuBar ( createMenuBar ());
        frame . pack ();
        frame . requestFocusInWindow ();
        frame . setVisible ( true );
     }

     // create the menu bar (changed to private)
     private   static   JMenuBar  createMenuBar ()   {
         JMenuBar  menuBar  =   new   JMenuBar ();
         JMenu  menu  =   new   JMenu ( "File" );
        menuBar . add ( menu );
         JMenuItem  menuItem1  =   new   JMenuItem ( " Save...   " );
        menuItem1 . addActionListener ( std );
         // Java 10+: replace getMenuShortcutKeyMask() with getMenuShortcutKeyMaskEx()
        menuItem1 . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_S ,
                                 Toolkit . getDefaultToolkit (). getMenuShortcutKeyMask ()));
        menu . add ( menuItem1 );
         return  menuBar ;
     }

    /***************************************************************************
    *  User and screen coordinate systems.
    ***************************************************************************/

     // throw an IllegalArgumentException if x is NaN or infinite
     private   static   void  validate ( double  x ,   String  name )   {
         if   ( Double . isNaN ( x ))   throw   new   IllegalArgumentException ( name  +   " is NaN" );
         if   ( Double . isInfinite ( x ))   throw   new   IllegalArgumentException ( name  +   " is infinite" );
     }

     // throw an IllegalArgumentException if s is null
     private   static   void  validateNonnegative ( double  x ,   String  name )   {
         if   ( <   0 )   throw   new   IllegalArgumentException ( name  +   " negative" );
     }

     // throw an IllegalArgumentException if s is null
     private   static   void  validateNotNull ( Object  x ,   String  name )   {
         if   ( ==   null )   throw   new   IllegalArgumentException ( name  +   " is null" );
     }


     /**
     * Sets the <em>x</em>-scale to be the default (between 0.0 and 1.0).
     */
     public   static   void  setXscale ()   {
        setXscale ( DEFAULT_XMIN ,  DEFAULT_XMAX );
     }

     /**
     * Sets the <em>y</em>-scale to be the default (between 0.0 and 1.0).
     */
     public   static   void  setYscale ()   {
        setYscale ( DEFAULT_YMIN ,  DEFAULT_YMAX );
     }

     /**
     * Sets the <em>x</em>-scale and <em>y</em>-scale to be the default
     * (between 0.0 and 1.0).
     */
     public   static   void  setScale ()   {
        setXscale ();
        setYscale ();
     }

     /**
     * Sets the <em>x</em>-scale to the specified range.
     *
     *  @param   min the minimum value of the <em>x</em>-scale
     *  @param   max the maximum value of the <em>x</em>-scale
     *  @throws  IllegalArgumentException if { @code  (max == min)}
     *  @throws  IllegalArgumentException if either { @code  min} or { @code  max} is either NaN or infinite
     */
     public   static   void  setXscale ( double  min ,   double  max )   {
        validate ( min ,   "min" );
        validate ( max ,   "max" );
         double  size  =  max  -  min ;
         if   ( size  ==   0.0 )   throw   new   IllegalArgumentException ( "the min and max are the same" );
         synchronized   ( mouseLock )   {
            xmin  =  min  -  BORDER  *  size ;
            xmax  =  max  +  BORDER  *  size ;
         }
     }

     /**
     * Sets the <em>y</em>-scale to the specified range.
     *
     *  @param   min the minimum value of the <em>y</em>-scale
     *  @param   max the maximum value of the <em>y</em>-scale
     *  @throws  IllegalArgumentException if { @code  (max == min)}
     *  @throws  IllegalArgumentException if either { @code  min} or { @code  max} is either NaN or infinite
     */
     public   static   void  setYscale ( double  min ,   double  max )   {
        validate ( min ,   "min" );
        validate ( max ,   "max" );
         double  size  =  max  -  min ;
         if   ( size  ==   0.0 )   throw   new   IllegalArgumentException ( "the min and max are the same" );
         synchronized   ( mouseLock )   {
            ymin  =  min  -  BORDER  *  size ;
            ymax  =  max  +  BORDER  *  size ;
         }
     }

     /**
     * Sets both the <em>x</em>-scale and <em>y</em>-scale to the (same) specified range.
     *
     *  @param   min the minimum value of the <em>x</em>- and <em>y</em>-scales
     *  @param   max the maximum value of the <em>x</em>- and <em>y</em>-scales
     *  @throws  IllegalArgumentException if { @code  (max == min)}
     *  @throws  IllegalArgumentException if either { @code  min} or { @code  max} is either NaN or infinite
     */
     public   static   void  setScale ( double  min ,   double  max )   {
        validate ( min ,   "min" );
        validate ( max ,   "max" );
         double  size  =  max  -  min ;
         if   ( size  ==   0.0 )   throw   new   IllegalArgumentException ( "the min and max are the same" );
         synchronized   ( mouseLock )   {
            xmin  =  min  -  BORDER  *  size ;
            xmax  =  max  +  BORDER  *  size ;
            ymin  =  min  -  BORDER  *  size ;
            ymax  =  max  +  BORDER  *  size ;
         }
     }

     // helper functions that scale from user coordinates to screen coordinates and back
     private   static   double   scaleX ( double  x )   {   return  width   *   ( -  xmin )   /   ( xmax  -  xmin );   }
     private   static   double   scaleY ( double  y )   {   return  height  *   ( ymax  -  y )   /   ( ymax  -  ymin );   }
     private   static   double  factorX ( double  w )   {   return  w  *  width   /   Math . abs ( xmax  -  xmin );    }
     private   static   double  factorY ( double  h )   {   return  h  *  height  /   Math . abs ( ymax  -  ymin );    }
     private   static   double    userX ( double  x )   {   return  xmin  +  x  *   ( xmax  -  xmin )   /  width ;      }
     private   static   double    userY ( double  y )   {   return  ymax  -  y  *   ( ymax  -  ymin )   /  height ;     }


     /**
     * Clears the screen to the default color (white).
     */
     public   static   void  clear ()   {
        clear ( DEFAULT_CLEAR_COLOR );
     }

     /**
     * Clears the screen to the specified color.
     *
     *  @param  color the color to make the background
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   static   void  clear ( Color  color )   {
        validateNotNull ( color ,   "color" );
        offscreen . setColor ( color );
        offscreen . fillRect ( 0 ,   0 ,  width ,  height );
        offscreen . setColor ( penColor );
        draw ();
     }

     /**
     * Returns the current pen radius.
     *
     *  @return  the current value of the pen radius
     */
     public   static   double  getPenRadius ()   {
         return  penRadius ;
     }

     /**
     * Sets the pen size to the default size (0.002).
     * The pen is circular, so that lines have rounded ends, and when you set the
     * pen radius and draw a point, you get a circle of the specified radius.
     * The pen radius is not affected by coordinate scaling.
     */
     public   static   void  setPenRadius ()   {
        setPenRadius ( DEFAULT_PEN_RADIUS );
     }

     /**
     * Sets the radius of the pen to the specified size.
     * The pen is circular, so that lines have rounded ends, and when you set the
     * pen radius and draw a point, you get a circle of the specified radius.
     * The pen radius is not affected by coordinate scaling.
     *
     *  @param   radius the radius of the pen
     *  @throws  IllegalArgumentException if { @code  radius} is negative, NaN, or infinite
     */
     public   static   void  setPenRadius ( double  radius )   {
        validate ( radius ,   "pen radius" );
        validateNonnegative ( radius ,   "pen radius" );

        penRadius  =  radius ;
         float  scaledPenRadius  =   ( float )   ( radius  *  DEFAULT_SIZE );
         BasicStroke  stroke  =   new   BasicStroke ( scaledPenRadius ,   BasicStroke . CAP_ROUND ,   BasicStroke . JOIN_ROUND );
         // BasicStroke stroke = new BasicStroke(scaledPenRadius);
        offscreen . setStroke ( stroke );
     }

     /**
     * Returns the current pen color.
     *
     *  @return  the current pen color
     */
     public   static   Color  getPenColor ()   {
         return  penColor ;
     }

     /**
     * Sets the pen color to the default color (black).
     */
     public   static   void  setPenColor ()   {
        setPenColor ( DEFAULT_PEN_COLOR );
     }

     /**
     * Sets the pen color to the specified color.
     * <p>
     * The predefined pen colors are
     * { @code  StdDraw.BLACK}, { @code  StdDraw.BLUE}, { @code  StdDraw.CYAN},
     * { @code  StdDraw.DARK_GRAY}, { @code  StdDraw.GRAY}, { @code  StdDraw.GREEN},
     * { @code  StdDraw.LIGHT_GRAY}, { @code  StdDraw.MAGENTA}, { @code  StdDraw.ORANGE},
     * { @code  StdDraw.PINK}, { @code  StdDraw.RED}, { @code  StdDraw.WHITE}, and
     * { @code  StdDraw.YELLOW}.
     *
     *  @param  color the color to make the pen
     *  @throws  IllegalArgumentException if { @code  color} is { @code  null}
     */
     public   static   void  setPenColor ( Color  color )   {
        validateNotNull ( color ,   "color" );
        penColor  =  color ;
        offscreen . setColor ( penColor );
     }

     /**
     * Sets the pen color to the specified RGB color.
     *
     *  @param   red the amount of red (between 0 and 255)
     *  @param   green the amount of green (between 0 and 255)
     *  @param   blue the amount of blue (between 0 and 255)
     *  @throws  IllegalArgumentException if { @code  red}, { @code  green},
     *         or { @code  blue} is outside its prescribed range
     */
     public   static   void  setPenColor ( int  red ,   int  green ,   int  blue )   {
         if   ( red    <   0   ||  red    >=   256 )   throw   new   IllegalArgumentException ( "red must be between 0 and 255" );
         if   ( green  <   0   ||  green  >=   256 )   throw   new   IllegalArgumentException ( "green must be between 0 and 255" );
         if   ( blue   <   0   ||  blue   >=   256 )   throw   new   IllegalArgumentException ( "blue must be between 0 and 255" );
        setPenColor ( new   Color ( red ,  green ,  blue ));
     }

     /**
     * Returns the current font.
     *
     *  @return  the current font
     */
     public   static   Font  getFont ()   {
         return  font ;
     }

     /**
     * Sets the font to the default font (sans serif, 16 point).
     */
     public   static   void  setFont ()   {
        setFont ( DEFAULT_FONT );
     }

     /**
     * Sets the font to the specified value.
     *
     *  @param  font the font
     *  @throws  IllegalArgumentException if { @code  font} is { @code  null}
     */
     public   static   void  setFont ( Font  font )   {
        validateNotNull ( font ,   "font" );
         StdDraw . font  =  font ;
     }


    /***************************************************************************
    *  Drawing geometric shapes.
    ***************************************************************************/

     /**
     * Draws a line segment between (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>) and
     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>).
     *
     *  @param   x0 the <em>x</em>-coordinate of one endpoint
     *  @param   y0 the <em>y</em>-coordinate of one endpoint
     *  @param   x1 the <em>x</em>-coordinate of the other endpoint
     *  @param   y1 the <em>y</em>-coordinate of the other endpoint
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     */
     public   static   void  line ( double  x0 ,   double  y0 ,   double  x1 ,   double  y1 )   {
        validate ( x0 ,   "x0" );
        validate ( y0 ,   "y0" );
        validate ( x1 ,   "x1" );
        validate ( y1 ,   "y1" );
        offscreen . draw ( new   Line2D . Double ( scaleX ( x0 ),  scaleY ( y0 ),  scaleX ( x1 ),  scaleY ( y1 )));
        draw ();
     }

     /**
     * Draws one pixel at (<em>x</em>, <em>y</em>).
     * This method is private because pixels depend on the display.
     * To achieve the same effect, set the pen radius to 0 and call { @code  point()}.
     *
     *  @param   x the <em>x</em>-coordinate of the pixel
     *  @param   y the <em>y</em>-coordinate of the pixel
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     private   static   void  pixel ( double  x ,   double  y )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        offscreen . fillRect (( int )   Math . round ( scaleX ( x )),   ( int )   Math . round ( scaleY ( y )),   1 ,   1 );
     }

     /**
     * Draws a point centered at (<em>x</em>, <em>y</em>).
     * The point is a filled circle whose radius is equal to the pen radius.
     * To draw a single-pixel point, first set the pen radius to 0.
     *
     *  @param  x the <em>x</em>-coordinate of the point
     *  @param  y the <em>y</em>-coordinate of the point
     *  @throws  IllegalArgumentException if either { @code  x} or { @code  y} is either NaN or infinite
     */
     public   static   void  point ( double  x ,   double  y )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  r  =  penRadius ;
         float  scaledPenRadius  =   ( float )   ( *  DEFAULT_SIZE );

         // double ws = factorX(2*r);
         // double hs = factorY(2*r);
         // if (ws <= 1 && hs <= 1) pixel(x, y);
         if   ( scaledPenRadius  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  scaledPenRadius / 2 ,  ys  -  scaledPenRadius / 2 ,
                                                 scaledPenRadius ,  scaledPenRadius ));
        draw ();
     }

     /**
     * Draws a circle of the specified radius, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the circle
     *  @param   y the <em>y</em>-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  circle ( double  x ,   double  y ,   double  radius )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "radius" );
        validateNonnegative ( radius ,   "radius" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled circle of the specified radius, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the circle
     *  @param   y the <em>y</em>-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  filledCircle ( double  x ,   double  y ,   double  radius )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "radius" );
        validateNonnegative ( radius ,   "radius" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws an ellipse with the specified semimajor and semiminor axes,
     * centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the ellipse
     *  @param   y the <em>y</em>-coordinate of the center of the ellipse
     *  @param   semiMajorAxis is the semimajor axis of the ellipse
     *  @param   semiMinorAxis is the semiminor axis of the ellipse
     *  @throws  IllegalArgumentException if either { @code  semiMajorAxis}
     *         or { @code  semiMinorAxis} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  ellipse ( double  x ,   double  y ,   double  semiMajorAxis ,   double  semiMinorAxis )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( semiMajorAxis ,   "semimajor axis" );
        validate ( semiMinorAxis ,   "semiminor axis" );
        validateNonnegative ( semiMajorAxis ,   "semimajor axis" );
        validateNonnegative ( semiMinorAxis ,   "semiminor axis" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * semiMajorAxis );
         double  hs  =  factorY ( 2 * semiMinorAxis );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled ellipse with the specified semimajor and semiminor axes,
     * centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the ellipse
     *  @param   y the <em>y</em>-coordinate of the center of the ellipse
     *  @param   semiMajorAxis is the semimajor axis of the ellipse
     *  @param   semiMinorAxis is the semiminor axis of the ellipse
     *  @throws  IllegalArgumentException if either { @code  semiMajorAxis}
     *         or { @code  semiMinorAxis} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  filledEllipse ( double  x ,   double  y ,   double  semiMajorAxis ,   double  semiMinorAxis )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( semiMajorAxis ,   "semimajor axis" );
        validate ( semiMinorAxis ,   "semiminor axis" );
        validateNonnegative ( semiMajorAxis ,   "semimajor axis" );
        validateNonnegative ( semiMinorAxis ,   "semiminor axis" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * semiMajorAxis );
         double  hs  =  factorY ( 2 * semiMinorAxis );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Ellipse2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws a circular arc of the specified radius,
     * centered at (<em>x</em>, <em>y</em>), from angle1 to angle2 (in degrees).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the circle
     *  @param   y the <em>y</em>-coordinate of the center of the circle
     *  @param   radius the radius of the circle
     *  @param   angle1 the starting angle. 0 would mean an arc beginning at 3 o'clock.
     *  @param   angle2 the angle at the end of the arc. For example, if
     *         you want a 90 degree arc, then angle2 should be angle1 + 90.
     *  @throws  IllegalArgumentException if { @code  radius} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  arc ( double  x ,   double  y ,   double  radius ,   double  angle1 ,   double  angle2 )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( radius ,   "arc radius" );
        validate ( angle1 ,   "angle1" );
        validate ( angle2 ,   "angle2" );
        validateNonnegative ( radius ,   "arc radius" );

         while   ( angle2  <  angle1 )  angle2  +=   360 ;
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * radius );
         double  hs  =  factorY ( 2 * radius );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Arc2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ,  angle1 ,  angle2  -  angle1 ,   Arc2D . OPEN ));
        draw ();
     }

     /**
     * Draws a square of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the square
     *  @param   y the <em>y</em>-coordinate of the center of the square
     *  @param   halfLength one half the length of any side of the square
     *  @throws  IllegalArgumentException if { @code  halfLength} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  square ( double  x ,   double  y ,   double  halfLength )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfLength ,   "halfLength" );
        validateNonnegative ( halfLength ,   "half length" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfLength );
         double  hs  =  factorY ( 2 * halfLength );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled square of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the square
     *  @param   y the <em>y</em>-coordinate of the center of the square
     *  @param   halfLength one half the length of any side of the square
     *  @throws  IllegalArgumentException if { @code  halfLength} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  filledSquare ( double  x ,   double  y ,   double  halfLength )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfLength ,   "halfLength" );
        validateNonnegative ( halfLength ,   "half length" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfLength );
         double  hs  =  factorY ( 2 * halfLength );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws a rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the rectangle
     *  @param   y the <em>y</em>-coordinate of the center of the rectangle
     *  @param   halfWidth one half the width of the rectangle
     *  @param   halfHeight one half the height of the rectangle
     *  @throws  IllegalArgumentException if either { @code  halfWidth} or { @code  halfHeight} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  rectangle ( double  x ,   double  y ,   double  halfWidth ,   double  halfHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfWidth ,   "halfWidth" );
        validate ( halfHeight ,   "halfHeight" );
        validateNonnegative ( halfWidth ,   "half width" );
        validateNonnegative ( halfHeight ,   "half height" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfWidth );
         double  hs  =  factorY ( 2 * halfHeight );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . draw ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }

     /**
     * Draws a filled rectangle of the specified size, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the center of the rectangle
     *  @param   y the <em>y</em>-coordinate of the center of the rectangle
     *  @param   halfWidth one half the width of the rectangle
     *  @param   halfHeight one half the height of the rectangle
     *  @throws  IllegalArgumentException if either { @code  halfWidth} or { @code  halfHeight} is negative
     *  @throws  IllegalArgumentException if any argument is either NaN or infinite
     */
     public   static   void  filledRectangle ( double  x ,   double  y ,   double  halfWidth ,   double  halfHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( halfWidth ,   "halfWidth" );
        validate ( halfHeight ,   "halfHeight" );
        validateNonnegative ( halfWidth ,   "half width" );
        validateNonnegative ( halfHeight ,   "half height" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( 2 * halfWidth );
         double  hs  =  factorY ( 2 * halfHeight );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else  offscreen . fill ( new   Rectangle2D . Double ( xs  -  ws / 2 ,  ys  -  hs / 2 ,  ws ,  hs ));
        draw ();
     }


     /**
     * Draws a polygon with the vertices 
     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),
     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,
     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).
     *
     *  @param   x an array of all the <em>x</em>-coordinates of the polygon
     *  @param   y an array of all the <em>y</em>-coordinates of the polygon
     *  @throws  IllegalArgumentException unless { @code  x[]} and { @code  y[]}
     *         are of the same length
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     *  @throws  IllegalArgumentException if either { @code  x[]} or { @code  y[]} is { @code  null}
     */
     public   static   void  polygon ( double []  x ,   double []  y )   {
        validateNotNull ( x ,   "x-coordinate array" );
        validateNotNull ( y ,   "y-coordinate array" );
         for   ( int  i  =   0 ;  i  <  x . length ;  i ++ )  validate ( x [ i ],   "x["   +  i  +   "]" );
         for   ( int  i  =   0 ;  i  <  y . length ;  i ++ )  validate ( y [ i ],   "y["   +  i  +   "]" );

         int  n1  =  x . length ;
         int  n2  =  y . length ;
         if   ( n1  !=  n2 )   throw   new   IllegalArgumentException ( "arrays must be of the same length" );
         int  n  =  n1 ;
         if   ( ==   0 )   return ;

         GeneralPath  path  =   new   GeneralPath ();
        path . moveTo (( float )  scaleX ( x [ 0 ]),   ( float )  scaleY ( y [ 0 ]));
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )
            path . lineTo (( float )  scaleX ( x [ i ]),   ( float )  scaleY ( y [ i ]));
        path . closePath ();
        offscreen . draw ( path );
        draw ();
     }

     /**
     * Draws a filled polygon with the vertices 
     * (<em>x</em><sub>0</sub>, <em>y</em><sub>0</sub>),
     * (<em>x</em><sub>1</sub>, <em>y</em><sub>1</sub>), ...,
     * (<em>x</em><sub><em>n</em>–1</sub>, <em>y</em><sub><em>n</em>–1</sub>).
     *
     *  @param   x an array of all the <em>x</em>-coordinates of the polygon
     *  @param   y an array of all the <em>y</em>-coordinates of the polygon
     *  @throws  IllegalArgumentException unless { @code  x[]} and { @code  y[]}
     *         are of the same length
     *  @throws  IllegalArgumentException if any coordinate is either NaN or infinite
     *  @throws  IllegalArgumentException if either { @code  x[]} or { @code  y[]} is { @code  null}
     */
     public   static   void  filledPolygon ( double []  x ,   double []  y )   {
        validateNotNull ( x ,   "x-coordinate array" );
        validateNotNull ( y ,   "y-coordinate array" );
         for   ( int  i  =   0 ;  i  <  x . length ;  i ++ )  validate ( x [ i ],   "x["   +  i  +   "]" );
         for   ( int  i  =   0 ;  i  <  y . length ;  i ++ )  validate ( y [ i ],   "y["   +  i  +   "]" );

         int  n1  =  x . length ;
         int  n2  =  y . length ;
         if   ( n1  !=  n2 )   throw   new   IllegalArgumentException ( "arrays must be of the same length" );
         int  n  =  n1 ;
         if   ( ==   0 )   return ;

         GeneralPath  path  =   new   GeneralPath ();
        path . moveTo (( float )  scaleX ( x [ 0 ]),   ( float )  scaleY ( y [ 0 ]));
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )
            path . lineTo (( float )  scaleX ( x [ i ]),   ( float )  scaleY ( y [ i ]));
        path . closePath ();
        offscreen . fill ( path );
        draw ();
     }


    /***************************************************************************
    *  Drawing images.
    ***************************************************************************/
     // get an image from the given filename
     private   static   Image  getImage ( String  filename )   {
         if   ( filename  ==   null )   throw   new   IllegalArgumentException ();

         // to read from file
         ImageIcon  icon  =   new   ImageIcon ( filename );

         // try to read from URL
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
             try   {
                URL url  =   new  URL ( filename );
                icon  =   new   ImageIcon ( url );
             }
             catch   ( MalformedURLException  e )   {
                 /* not a url */
             }
         }

         // in case file is inside a .jar (classpath relative to StdDraw)
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
            URL url  =   StdDraw . class . getResource ( filename );
             if   ( url  !=   null )
                icon  =   new   ImageIcon ( url );
         }

         // in case file is inside a .jar (classpath relative to root of jar)
         if   (( icon  ==   null )   ||   ( icon . getImageLoadStatus ()   !=   MediaTracker . COMPLETE ))   {
            URL url  =   StdDraw . class . getResource ( "/"   +  filename );
             if   ( url  ==   null )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " not found" );
            icon  =   new   ImageIcon ( url );
         }

         return  icon . getImage ();
     }

    /***************************************************************************
    * [Summer 2016] Should we update to use ImageIO instead of ImageIcon()?
    *               Seems to have some issues loading images on some systems
    *               and slows things down on other systems.
    *               especially if you don't call ImageIO.setUseCache(false)
    *               One advantage is that it returns a BufferedImage.
    ***************************************************************************/
/*
    private static BufferedImage getImage(String filename) {
        if (filename == null) throw new IllegalArgumentException();

        // from a file or URL
        try {
            URL url = new URL(filename);
            BufferedImage image = ImageIO.read(url);
            return image;
        } 
        catch (IOException e) {
            // ignore
        }

        // in case file is inside a .jar (classpath relative to StdDraw)
        try {
            URL url = StdDraw.class.getResource(filename);
            BufferedImage image = ImageIO.read(url);
            return image;
        } 
        catch (IOException e) {
            // ignore
        }

        // in case file is inside a .jar (classpath relative to root of jar)
        try {
            URL url = StdDraw.class.getResource("/" + filename);
            BufferedImage image = ImageIO.read(url);
            return image;
        } 
        catch (IOException e) {
            // ignore
        }
        throw new IllegalArgumentException("image " + filename + " not found");
    }
*/
     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>).
     * The supported image formats are JPEG, PNG, and GIF.
     * As an optimization, the picture is cached, so there is no performance
     * penalty for redrawing the same image multiple times (e.g., in an animation).
     * However, if you change the picture file after drawing it, subsequent
     * calls will draw the original picture.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if either { @code  x} or { @code  y} is either NaN or infinite
     */
     public   static   void  picture ( double  x ,   double  y ,   String  filename )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( filename ,   "filename" );

         // BufferedImage image = getImage(filename);
         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         // int ws = image.getWidth();    // can call only if image is a BufferedImage
         // int hs = image.getHeight();
         int  ws  =  image . getWidth ( null );
         int  hs  =  image . getHeight ( null );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );

        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),   ( int )   Math . round ( ys  -  hs / 2.0 ),   null );
        draw ();
     }

     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>),
     * rotated given number of degrees.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if { @code  x}, { @code  y}, { @code  degrees} is NaN or infinite
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   static   void  picture ( double  x ,   double  y ,   String  filename ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( filename ,   "filename" );

         // BufferedImage image = getImage(filename);
         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         // int ws = image.getWidth();    // can call only if image is a BufferedImage
         // int hs = image.getHeight();
         int  ws  =  image . getWidth ( null );
         int  hs  =  image . getHeight ( null );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );

        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),   ( int )   Math . round ( ys  -  hs / 2.0 ),   null );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );

        draw ();
     }

     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>),
     * rescaled to the specified bounding box.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   scaledWidth the width of the scaled image (in screen coordinates)
     *  @param   scaledHeight the height of the scaled image (in screen coordinates)
     *  @throws  IllegalArgumentException if either { @code  scaledWidth}
     *         or { @code  scaledHeight} is negative
     *  @throws  IllegalArgumentException if the image filename is invalid
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   static   void  picture ( double  x ,   double  y ,   String  filename ,   double  scaledWidth ,   double  scaledHeight )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( scaledWidth ,   "scaled width" );
        validate ( scaledHeight ,   "scaled height" );
        validateNotNull ( filename ,   "filename" );
        validateNonnegative ( scaledWidth ,   "scaled width" );
        validateNonnegative ( scaledHeight ,   "scaled height" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( scaledWidth );
         double  hs  =  factorY ( scaledHeight );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );
         else   {
            offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),
                                        ( int )   Math . round ( ys  -  hs / 2.0 ),
                                        ( int )   Math . round ( ws ),
                                        ( int )   Math . round ( hs ),   null );
         }
        draw ();
     }


     /**
     * Draws the specified image centered at (<em>x</em>, <em>y</em>), rotated
     * given number of degrees, and rescaled to the specified bounding box.
     * The supported image formats are JPEG, PNG, and GIF.
     *
     *  @param   x the center <em>x</em>-coordinate of the image
     *  @param   y the center <em>y</em>-coordinate of the image
     *  @param   filename the name of the image/picture, e.g., "ball.gif"
     *  @param   scaledWidth the width of the scaled image (in screen coordinates)
     *  @param   scaledHeight the height of the scaled image (in screen coordinates)
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if either { @code  scaledWidth}
     *         or { @code  scaledHeight} is negative
     *  @throws  IllegalArgumentException if the image filename is invalid
     */
     public   static   void  picture ( double  x ,   double  y ,   String  filename ,   double  scaledWidth ,   double  scaledHeight ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( scaledWidth ,   "scaled width" );
        validate ( scaledHeight ,   "scaled height" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( filename ,   "filename" );
        validateNonnegative ( scaledWidth ,   "scaled width" );
        validateNonnegative ( scaledHeight ,   "scaled height" );

         Image  image  =  getImage ( filename );
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         double  ws  =  factorX ( scaledWidth );
         double  hs  =  factorY ( scaledHeight );
         if   ( ws  <   0   ||  hs  <   0 )   throw   new   IllegalArgumentException ( "image "   +  filename  +   " is corrupt" );
         if   ( ws  <=   1   &&  hs  <=   1 )  pixel ( x ,  y );

        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        offscreen . drawImage ( image ,   ( int )   Math . round ( xs  -  ws / 2.0 ),
                                    ( int )   Math . round ( ys  -  hs / 2.0 ),
                                    ( int )   Math . round ( ws ),
                                    ( int )   Math . round ( hs ),   null );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );

        draw ();
     }

    /***************************************************************************
    *  Drawing text.
    ***************************************************************************/

     /**
     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the center <em>x</em>-coordinate of the text
     *  @param   y the center <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   static   void  text ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  metrics . stringWidth ( text );
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )   ( xs  -  ws / 2.0 ),   ( float )   ( ys  +  hs ));
        draw ();
     }

     /**
     * Writes the given text string in the current font, centered at (<em>x</em>, <em>y</em>) and
     * rotated by the specified number of degrees.
     *  @param   x the center <em>x</em>-coordinate of the text
     *  @param   y the center <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @param   degrees is the number of degrees to rotate counterclockwise
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x}, { @code  y}, or { @code  degrees} is either NaN or infinite
     */
     public   static   void  text ( double  x ,   double  y ,   String  text ,   double  degrees )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validate ( degrees ,   "degrees" );
        validateNotNull ( text ,   "text" );

         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
        offscreen . rotate ( Math . toRadians ( - degrees ),  xs ,  ys );
        text ( x ,  y ,  text );
        offscreen . rotate ( Math . toRadians ( + degrees ),  xs ,  ys );
     }


     /**
     * Writes the given text string in the current font, left-aligned at (<em>x</em>, <em>y</em>).
     *  @param   x the <em>x</em>-coordinate of the text
     *  @param   y the <em>y</em>-coordinate of the text
     *  @param   text the text
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   static   void  textLeft ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )  xs ,   ( float )   ( ys  +  hs ));
        draw ();
     }

     /**
     * Writes the given text string in the current font, right-aligned at (<em>x</em>, <em>y</em>).
     *
     *  @param   x the <em>x</em>-coordinate of the text
     *  @param   y the <em>y</em>-coordinate of the text
     *  @param   text the text to write
     *  @throws  IllegalArgumentException if { @code  text} is { @code  null}
     *  @throws  IllegalArgumentException if { @code  x} or { @code  y} is either NaN or infinite
     */
     public   static   void  textRight ( double  x ,   double  y ,   String  text )   {
        validate ( x ,   "x" );
        validate ( y ,   "y" );
        validateNotNull ( text ,   "text" );

        offscreen . setFont ( font );
         FontMetrics  metrics  =  offscreen . getFontMetrics ();
         double  xs  =  scaleX ( x );
         double  ys  =  scaleY ( y );
         int  ws  =  metrics . stringWidth ( text );
         int  hs  =  metrics . getDescent ();
        offscreen . drawString ( text ,   ( float )   ( xs  -  ws ),   ( float )   ( ys  +  hs ));
        draw ();
     }


     /**
     * Copies the offscreen buffer to the onscreen buffer, pauses for t milliseconds
     * and enables double buffering.
     *  @param  t number of milliseconds
     *  @deprecated  replaced by { @link  #enableDoubleBuffering()}, { @link  #show()}, and { @link  #pause(int t)}
     */
    @ Deprecated
     public   static   void  show ( int  t )   {
        validateNonnegative ( t ,   "t" );
        show ();
        pause ( t );
        enableDoubleBuffering ();
     }

     /**
     * Pauses for t milliseconds. This method is intended to support computer animations.
     *  @param  t number of milliseconds
     */
     public   static   void  pause ( int  t )   {
        validateNonnegative ( t ,   "t" );
         try   {
             Thread . sleep ( t );
         }
         catch   ( InterruptedException  e )   {
             System . out . println ( "Error sleeping" );
         }
     }

     /**
     * Copies offscreen buffer to onscreen buffer. There is no reason to call
     * this method unless double buffering is enabled.
     */
     public   static   void  show ()   {
        onscreen . drawImage ( offscreenImage ,   0 ,   0 ,   null );
        frame . repaint ();
     }

     // draw onscreen if defer is false
     private   static   void  draw ()   {
         if   ( ! defer )  show ();
     }

     /**
     * Enables double buffering. All subsequent calls to 
     * drawing methods such as { @code  line()}, { @code  circle()},
     * and { @code  square()} will be deferred until the next call
     * to show(). Useful for animations.
     */
     public   static   void  enableDoubleBuffering ()   {
        defer  =   true ;
     }

     /**
     * Disables double buffering. All subsequent calls to 
     * drawing methods such as { @code  line()}, { @code  circle()},
     * and { @code  square()} will be displayed on screen when called.
     * This is the default.
     */
     public   static   void  disableDoubleBuffering ()   {
        defer  =   false ;
     }


    /***************************************************************************
    *  Save drawing to a file.
    ***************************************************************************/

     /**
     * Saves the drawing to using the specified filename.
     * The supported image formats are JPEG and PNG;
     * the filename suffix must be { @code  .jpg} or { @code  .png}.
     *
     *  @param   filename the name of the file with one of the required suffixes
     *  @throws  IllegalArgumentException if { @code  filename} is { @code  null}
     */
     public   static   void  save ( String  filename )   {
        validateNotNull ( filename ,   "filename" );
         File  file  =   new   File ( filename );
         String  suffix  =  filename . substring ( filename . lastIndexOf ( '.' )   +   1 );

         // png files
         if   ( "png" . equalsIgnoreCase ( suffix ))   {
             try   {
                 ImageIO . write ( onscreenImage ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }

         // need to change from ARGB to RGB for JPEG
         // reference: http://archives.java.sun.com/cgi-bin/wa?A2=ind0404&L=java2d-interest&D=0&P=2727
         else   if   ( "jpg" . equalsIgnoreCase ( suffix ))   {
             WritableRaster  raster  =  onscreenImage . getRaster ();
             WritableRaster  newRaster ;
            newRaster  =  raster . createWritableChild ( 0 ,   0 ,  width ,  height ,   0 ,   0 ,   new   int []   { 0 ,   1 ,   2 });
             DirectColorModel  cm  =   ( DirectColorModel )  onscreenImage . getColorModel ();
             DirectColorModel  newCM  =   new   DirectColorModel ( cm . getPixelSize (),
                                                          cm . getRedMask (),
                                                          cm . getGreenMask (),
                                                          cm . getBlueMask ());
             BufferedImage  rgbBuffer  =   new   BufferedImage ( newCM ,  newRaster ,   false ,    null );
             try   {
                 ImageIO . write ( rgbBuffer ,  suffix ,  file );
             }
             catch   ( IOException  e )   {
                e . printStackTrace ();
             }
         }

         else   {
             System . out . println ( "Invalid image file type: "   +  suffix );
         }
     }


     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  actionPerformed ( ActionEvent  e )   {
         FileDialog  chooser  =   new   FileDialog ( StdDraw . frame ,   "Use a .png or .jpg extension" ,   FileDialog . SAVE );
        chooser . setVisible ( true );
         String  filename  =  chooser . getFile ();
         if   ( filename  !=   null )   {
             StdDraw . save ( chooser . getDirectory ()   +   File . separator  +  chooser . getFile ());
         }
     }


    /***************************************************************************
    *  Mouse interactions.
    ***************************************************************************/

     /**
     * Returns true if the mouse is being pressed.
     *
     *  @return  { @code  true} if the mouse is being pressed; { @code  false} otherwise
     */
     public   static   boolean  isMousePressed ()   {
         synchronized   ( mouseLock )   {
             return  isMousePressed ;
         }
     }

     /**
     * Returns true if the mouse is being pressed.
     *
     *  @return  { @code  true} if the mouse is being pressed; { @code  false} otherwise
     *  @deprecated  replaced by { @link  #isMousePressed()}
     */
    @ Deprecated
     public   static   boolean  mousePressed ()   {
         synchronized   ( mouseLock )   {
             return  isMousePressed ;
         }
     }

     /**
     * Returns the <em>x</em>-coordinate of the mouse.
     *
     *  @return  the <em>x</em>-coordinate of the mouse
     */
     public   static   double  mouseX ()   {
         synchronized   ( mouseLock )   {
             return  mouseX ;
         }
     }

     /**
     * Returns the <em>y</em>-coordinate of the mouse.
     *
     *  @return  <em>y</em>-coordinate of the mouse
     */
     public   static   double  mouseY ()   {
         synchronized   ( mouseLock )   {
             return  mouseY ;
         }
     }


     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseClicked ( MouseEvent  e )   {
         // this body is intentionally left empty
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseEntered ( MouseEvent  e )   {
         // this body is intentionally left empty
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseExited ( MouseEvent  e )   {
         // this body is intentionally left empty
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mousePressed ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            mouseX  =   StdDraw . userX ( e . getX ());
            mouseY  =   StdDraw . userY ( e . getY ());
            isMousePressed  =   true ;
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseReleased ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            isMousePressed  =   false ;
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseDragged ( MouseEvent  e )    {
         synchronized   ( mouseLock )   {
            mouseX  =   StdDraw . userX ( e . getX ());
            mouseY  =   StdDraw . userY ( e . getY ());
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  mouseMoved ( MouseEvent  e )   {
         synchronized   ( mouseLock )   {
            mouseX  =   StdDraw . userX ( e . getX ());
            mouseY  =   StdDraw . userY ( e . getY ());
         }
     }


    /***************************************************************************
    *  Keyboard interactions.
    ***************************************************************************/

     /**
     * Returns true if the user has typed a key (that has not yet been processed).
     *
     *  @return  { @code  true} if the user has typed a key (that has not yet been processed
     *         by { @link  #nextKeyTyped()}; { @code  false} otherwise
     */
     public   static   boolean  hasNextKeyTyped ()   {
         synchronized   ( keyLock )   {
             return   ! keysTyped . isEmpty ();
         }
     }

     /**
     * Returns the next key that was typed by the user (that your program has not already processed).
     * This method should be preceded by a call to { @link  #hasNextKeyTyped()} to ensure
     * that there is a next key to process.
     * This method returns a Unicode character corresponding to the key
     * typed (such as { @code  'a'} or { @code  'A'}).
     * It cannot identify action keys (such as F1 and arrow keys)
     * or modifier keys (such as control).
     *
     *  @return  the next key typed by the user (that your program has not already processed).
     *  @throws  NoSuchElementException if there is no remaining key
     */
     public   static   char  nextKeyTyped ()   {
         synchronized   ( keyLock )   {
             if   ( keysTyped . isEmpty ())   {
                 throw   new   NoSuchElementException ( "your program has already processed all keystrokes" );
             }
             return  keysTyped . remove ( keysTyped . size ()   -   1 );
             // return keysTyped.removeLast();
         }
     }

     /**
     * Returns true if the given key is being pressed.
     * <p>
     * This method takes the keycode (corresponding to a physical key)
    *  as an argument. It can handle action keys
     * (such as F1 and arrow keys) and modifier keys (such as shift and control).
     * See { @link  KeyEvent} for a description of key codes.
     *
     *  @param   keycode the key to check if it is being pressed
     *  @return  { @code  true} if { @code  keycode} is currently being pressed;
     *         { @code  false} otherwise
     */
     public   static   boolean  isKeyPressed ( int  keycode )   {
         synchronized   ( keyLock )   {
             return  keysDown . contains ( keycode );
         }
     }


     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyTyped ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysTyped . addFirst ( e . getKeyChar ());
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyPressed ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysDown . add ( e . getKeyCode ());
         }
     }

     /**
     * This method cannot be called directly.
     */
    @ Override
     public   void  keyReleased ( KeyEvent  e )   {
         synchronized   ( keyLock )   {
            keysDown . remove ( e . getKeyCode ());
         }
     }


    /***************************************************************************
    *  For improved resolution on Mac Retina displays.
    ***************************************************************************/

     private   static   class   RetinaImageIcon   extends   ImageIcon   {
    
         public   RetinaImageIcon ( Image  image )   {
             super ( image );
         }

         public   int  getIconWidth ()   {
             return   super . getIconWidth ()   /   2 ;
         }

         /**
         * Gets the height of the icon.
         *
         *  @return  the height in pixels of this icon
         */
         public   int  getIconHeight ()   {
             return   super . getIconHeight ()   /   2 ;
         }

         public   synchronized   void  paintIcon ( Component  c ,   Graphics  g ,   int  x ,   int  y )   {
             Graphics2D  g2  =   ( Graphics2D )  g . create ();
            g2 . setRenderingHint ( RenderingHints . KEY_INTERPOLATION , RenderingHints . VALUE_INTERPOLATION_BICUBIC );
            g2 . setRenderingHint ( RenderingHints . KEY_RENDERING , RenderingHints . VALUE_RENDER_QUALITY );
            g2 . setRenderingHint ( RenderingHints . KEY_ANTIALIASING , RenderingHints . VALUE_ANTIALIAS_ON );
            g2 . scale ( 0.5 ,   0.5 );
             super . paintIcon ( c ,  g2 ,  x  *   2 ,  y  *   2 );
            g2 . dispose ();
         }
     }


     /**
     * Test client.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         StdDraw . square ( 0.2 ,   0.8 ,   0.1 );
         StdDraw . filledSquare ( 0.8 ,   0.8 ,   0.2 );
         StdDraw . circle ( 0.8 ,   0.2 ,   0.2 );

         StdDraw . setPenColor ( StdDraw . BOOK_RED );
         StdDraw . setPenRadius ( 0.02 );
         StdDraw . arc ( 0.8 ,   0.2 ,   0.1 ,   200 ,   45 );

         // draw a blue diamond
         StdDraw . setPenRadius ();
         StdDraw . setPenColor ( StdDraw . BOOK_BLUE );
         double []  x  =   {   0.1 ,   0.2 ,   0.3 ,   0.2   };
         double []  y  =   {   0.2 ,   0.3 ,   0.2 ,   0.1   };
         StdDraw . filledPolygon ( x ,  y );

         // text
         StdDraw . setPenColor ( StdDraw . BLACK );
         StdDraw . text ( 0.2 ,   0.5 ,   "black text" );
         StdDraw . setPenColor ( StdDraw . WHITE );
         StdDraw . text ( 0.8 ,   0.8 ,   "white text" );
     }

}

StdIn.java

StdIn.java

/******************************************************************************
 *  Compilation:  javac StdIn.java
 *  Execution:    java StdIn   (interactive test of basic functionality)
 *  Dependencies: none
 *
 *  Reads in data of various types from standard input.
 *
 ******************************************************************************/

import  java . util . ArrayList ;
import  java . util . InputMismatchException ;
import  java . util . Locale ;
import  java . util . NoSuchElementException ;
import  java . util . Scanner ;
import  java . util . regex . Pattern ;

/**
 *  The { @code  StdIn} class provides static methods for reading strings
 *  and numbers from standard input.
 *  These functions fall into one of four categories:
 *  <ul>
 *  <li>those for reading individual tokens from standard input, one at a time,
 *      and converting each to a number, string, or boolean
 *  <li>those for reading characters from standard input, one at a time
 *  <li>those for reading lines from standard input, one at a time
 *  <li>those for reading a sequence of values of the same type from standard input,
 *      and returning the values in an array
 *  </ul>
 *  <p>
 *  Generally, it is best not to mix functions from the different
 *  categories in the same program.
 *  <p>
 *  <b>Getting started.</b>
 *  To use this class, you must have { @code  StdIn.class} in your
 *  Java classpath. If you used our autoinstaller, you should be all set.
 *  Otherwise, either download
 *  <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
 *  and add to your Java classpath or download
 *  <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdIn.java">StdIn.java</a>
 *  and put a copy in your working directory.
 *  <p>
 *  <b>Reading tokens from standard input and converting to numbers and strings.</b>
 *  You can use the following methods to read numbers, strings, and booleans
 *  from standard input one at a time:
 *  <ul>
 *  <li> { @link  #isEmpty()}
 *  <li> { @link  #readInt()}
 *  <li> { @link  #readDouble()}
 *  <li> { @link  #readString()}
 *  <li> { @link  #readShort()}
 *  <li> { @link  #readLong()}
 *  <li> { @link  #readFloat()}
 *  <li> { @link  #readByte()}
 *  <li> { @link  #readBoolean()}
 *  </ul>
 *  <p>
 *  The first method returns true if standard input has no more tokens.
 *  Each other method skips over any input that is whitespace. Then, it reads
 *  the next token and attempts to convert it into a value of the specified
 *  type. If it succeeds, it returns that value; otherwise, it
 *  throws an { @link  InputMismatchException}.
 *  <p>
 *  <em>Whitespace</em> includes spaces, tabs, and newlines; the full definition
 *  is inherited from { @link  Character#isWhitespace(char)}.
 *  A <em>token</em> is a maximal sequence of non-whitespace characters.
 *  The precise rules for describing which tokens can be converted to
 *  integers and floating-point numbers are inherited from
 *  <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#number-syntax">Scanner</a>,
 *  using the locale { @link  Locale#US}; the rules
 *  for floating-point numbers are slightly different
 *  from those in { @link  Double#valueOf(String)},
 *  but unlikely to be of concern to most programmers.
 *  <p>
 *  As an example, the following code fragment reads integers from standard input,
 *  one at a time, and prints them one per line.
 *  <pre>
 *  while (!StdIn.isEmpty()) {
 *      double value = StdIn.readDouble();
 *      StdOut.println(value);
 *  }
 *  </pre>
 *  <p>
 *  <b>Reading characters from standard input.</b>
 *  You can use the following two methods to read characters from standard input one at a time:
 *  <ul>
 *  <li> { @link  #hasNextChar()}
 *  <li> { @link  #readChar()}
 *  </ul>
 *  <p>
 *  The first method returns true if standard input has more input (including whitespace).
 *  The second method reads and returns the next character of input on standard 
 *  input (possibly a whitespace character).
 *  <p>
 *  As an example, the following code fragment reads characters from standard input,
 *  one character at a time, and prints it to standard output.
 *  <pre>
 *  while (StdIn.hasNextChar()) {
 *      char c = StdIn.readChar();
 *      StdOut.print(c);
 *  }
 *  </pre>
 *  <p>
 *  <b>Reading lines from standard input.</b>
 *  You can use the following two methods to read lines from standard input:
 *  <ul>
 *  <li> { @link  #hasNextLine()}
 *  <li> { @link  #readLine()}
 *  </ul>
 *  <p>
 *  The first method returns true if standard input has more input (including whitespace).
 *  The second method reads and returns the remaining portion of 
 *  the next line of input on standard input (possibly whitespace),
 *  discarding the trailing line separator.
 *  <p>
 *  A <em>line separator</em> is defined to be one of the following strings:
 *  { @code  \n} (Linux), { @code  \r} (old Macintosh),
 *  { @code  \r\n} (Windows),
 *  { @code  \}{ @code  u2028}, { @code  \}{ @code  u2029}, or { @code  \}{ @code  u0085}.
 *  <p>
 *  As an example, the following code fragment reads text from standard input,
 *  one line at a time, and prints it to standard output.
 *  <pre>
 *  while (StdIn.hasNextLine()) {
 *      String line = StdIn.readLine();
 *      StdOut.println(line);
 *  }
 *  </pre>
 *  <p>
 *  <b>Reading a sequence of values of the same type from standard input.</b>
 *  You can use the following methods to read a sequence numbers, strings,
 *  or booleans (all of the same type) from standard input:
 *  <ul>
 *  <li> { @link  #readAllDoubles()}
 *  <li> { @link  #readAllInts()}
 *  <li> { @link  #readAllLongs()}
 *  <li> { @link  #readAllStrings()}
 *  <li> { @link  #readAllLines()}
 *  <li> { @link  #readAll()}
 *  </ul>
 *  <p>
 *  The first three methods read of all of remaining token on standard input
 *  and converts the tokens to values of
 *  the specified type, as in the corresponding
 *  { @code  readDouble}, { @code  readInt}, and { @code  readString()} methods.
 *  The { @code  readAllLines()} method reads all remaining lines on standard
 *  input and returns them as an array of strings.
 *  The { @code  readAll()} method reads all remaining input on standard
 *  input and returns it as a string.
 *  <p>
 *  As an example, the following code fragment reads all of the remaining
 *  tokens from standard input and returns them as an array of strings.
 *  <pre>
 *  String[] words = StdIn.readAllStrings();
 *  </pre>
 *  <p>
 *  <b>Differences with Scanner.</b>
 *  { @code  StdIn} and { @link  Scanner} are both designed to parse 
 *  tokens and convert them to primitive types and strings.
 *  The main differences are summarized below:
 *  <ul>
 *  <li> { @code  StdIn} is a set of static methods and reads 
 *       reads input from only standard input. It is suitable for use before
 *       a programmer knows about objects.
 *       See { @link  In} for an object-oriented version that handles
 *       input from files, URLs,
 *       and sockets.
 *  <li> { @code  StdIn} uses whitespace as the delimiter pattern
 *       that separates tokens.
 *       { @link  Scanner} supports arbitrary delimiter patterns.
 *  <li> { @code  StdIn} coerces the character-set encoding to UTF-8,
 *       which is the most widely used character encoding for Unicode.
 *  <li> { @code  StdIn} coerces the locale to { @link  Locale#US},
 *       for consistency with { @link  StdOut}, { @link  Double#parseDouble(String)},
 *       and floating-point literals.
 *  <li> { @code  StdIn} has convenient methods for reading a single
 *       character; reading in sequences of integers, doubles, or strings;
 *       and reading in all of the remaining input.
 *  </ul>
 *  <p>
 *  Historical note: { @code  StdIn} preceded { @code  Scanner}; when
 *  { @code  Scanner} was introduced, this class was re-implemented to use { @code  Scanner}.
 *  <p>
 *  <b>Using standard input.</b>
 *  Standard input is a fundamental operating system abstraction on Mac OS X,
 *  Windows, and Linux.
 *  The methods in { @code  StdIn} are <em>blocking</em>, which means that they
 *  will wait until you enter input on standard input.
 *  If your program has a loop that repeats until standard input is empty,
 *  you must signal that the input is finished.
 *  To do so, depending on your operating system and IDE, 
 *  use either { @code  <Ctrl-d>} or { @code  <Ctrl-z>}, on its own line.
 *  If you are redirecting standard input from a file, you will not need
 *  to do anything to signal that the input is finished.
 *  <p>
 *  <b>Known bugs.</b>
 *  Java's UTF-8 encoding does not recognize the optional 
 *  <a href = "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058">byte-order mask</a>.
 *  If the input begins with the optional byte-order mask, { @code  StdIn}
 *  will have an extra character { @code  \}{ @code  uFEFF} at the beginning.
 *  <p>
 *  <b>Reference.</b> 
 *  For additional documentation,
 *  see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of   
 *  <em>Computer Science: An Interdisciplinary Approach</em>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 *   @author  David Pritchard
 */
public   final   class   StdIn   {

     /*** begin: section (1 of 2) of code duplicated from In to StdIn. */
    
     // assume Unicode UTF-8 encoding
     private   static   final   String  CHARSET_NAME  =   "UTF-8" ;

     // assume language = English, country = US for consistency with System.out.
     private   static   final   Locale  LOCALE  =   Locale . US ;

     // the default token separator; we maintain the invariant that this value
     // is held by the scanner's delimiter between calls
     private   static   final   Pattern  WHITESPACE_PATTERN  =   Pattern . compile ( "\\p{javaWhitespace}+" );

     // makes whitespace significant
     private   static   final   Pattern  EMPTY_PATTERN  =   Pattern . compile ( "" );

     // used to read the entire input
     private   static   final   Pattern  EVERYTHING_PATTERN  =   Pattern . compile ( "\\A" );

     /*** end: section (1 of 2) of code duplicated from In to StdIn. */

     private   static   Scanner  scanner ;
 
     // it doesn't make sense to instantiate this class
     private   StdIn ()   {   }

     //// begin: section (2 of 2) of code duplicated from In to StdIn,
     //// with all methods changed from "public" to "public static"

    /**
     * Returns true if standard input is empty (except possibly for whitespace).
     * Use this method to know whether the next call to { @link  #readString()}, 
     * { @link  #readDouble()}, etc will succeed.
     *
     *  @return  { @code  true} if standard input is empty (except possibly
     *         for whitespace); { @code  false} otherwise
     */
     public   static   boolean  isEmpty ()   {
         return   ! scanner . hasNext ();
     }

    /**
     * Returns true if standard input has a next line.
     * Use this method to know whether the
     * next call to { @link  #readLine()} will succeed.
     * This method is functionally equivalent to { @link  #hasNextChar()}.
     *
     *  @return  { @code  true} if standard input has more input (including whitespace);
     *         { @code  false} otherwise
     */
     public   static   boolean  hasNextLine ()   {
         return  scanner . hasNextLine ();
     }

     /**
     * Returns true if standard input has more input (including whitespace).
     * Use this method to know whether the next call to { @link  #readChar()} will succeed.
     * This method is functionally equivalent to { @link  #hasNextLine()}.
     *
     *  @return  { @code  true} if standard input has more input (including whitespace);
     *         { @code  false} otherwise
     */
     public   static   boolean  hasNextChar ()   {
        scanner . useDelimiter ( EMPTY_PATTERN );
         boolean  result  =  scanner . hasNext ();
        scanner . useDelimiter ( WHITESPACE_PATTERN );
         return  result ;
     }


    /**
     * Reads and returns the next line, excluding the line separator if present.
     *
     *  @return  the next line, excluding the line separator if present;
     *         { @code  null} if no such line
     */
     public   static   String  readLine ()   {
         String  line ;
         try   {
            line  =  scanner . nextLine ();
         }
         catch   ( NoSuchElementException  e )   {
            line  =   null ;
         }
         return  line ;
     }

     /**
     * Reads and returns the next character.
     *
     *  @return  the next { @code  char}
     *  @throws  NoSuchElementException if standard input is empty
     */
     public   static   char  readChar ()   {
         try   {
            scanner . useDelimiter ( EMPTY_PATTERN );
             String  ch  =  scanner . next ();
             assert  ch . length ()   ==   1   :   "Internal (Std)In.readChar() error!"
                 +   " Please contact the authors." ;
            scanner . useDelimiter ( WHITESPACE_PATTERN );
             return  ch . charAt ( 0 );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'char' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }   


    /**
     * Reads and returns the remainder of the input, as a string.
     *
     *  @return  the remainder of the input, as a string
     *  @throws  NoSuchElementException if standard input is empty
     */
     public   static   String  readAll ()   {
         if   ( ! scanner . hasNextLine ())
             return   "" ;

         String  result  =  scanner . useDelimiter ( EVERYTHING_PATTERN ). next ();
         // not that important to reset delimeter, since now scanner is empty
        scanner . useDelimiter ( WHITESPACE_PATTERN );   // but let's do it anyway
         return  result ;
     }


    /**
     * Reads the next token  and returns the { @code  String}.
     *
     *  @return  the next { @code  String}
     *  @throws  NoSuchElementException if standard input is empty
     */
     public   static   String  readString ()   {
         try   {
             return  scanner . next ();
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'String' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from standard input, parses it as an integer, and returns the integer.
     *
     *  @return  the next integer on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as an { @code  int}
     */
     public   static   int  readInt ()   {
         try   {
             return  scanner . nextInt ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read an 'int' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attemps to read an 'int' value from standard input, "
                                            +   "but no more tokens are available" );
         }

     }

    /**
     * Reads the next token from standard input, parses it as a double, and returns the double.
     *
     *  @return  the next double on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  double}
     */
     public   static   double  readDouble ()   {
         try   {
             return  scanner . nextDouble ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'double' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'double' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from standard input, parses it as a float, and returns the float.
     *
     *  @return  the next float on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  float}
     */
     public   static   float  readFloat ()   {
         try   {
             return  scanner . nextFloat ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'float' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'float' value from standard input, "
                                            +   "but there no more tokens are available" );
         }
     }

    /**
     * Reads the next token from standard input, parses it as a long integer, and returns the long integer.
     *
     *  @return  the next long integer on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  long}
     */
     public   static   long  readLong ()   {
         try   {
             return  scanner . nextLong ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'long' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'long' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from standard input, parses it as a short integer, and returns the short integer.
     *
     *  @return  the next short integer on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  short}
     */
     public   static   short  readShort ()   {
         try   {
             return  scanner . nextShort ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'short' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'short' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }

    /**
     * Reads the next token from standard input, parses it as a byte, and returns the byte.
     *
     *  @return  the next byte on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  byte}
     */
     public   static   byte  readByte ()   {
         try   {
             return  scanner . nextByte ();
         }
         catch   ( InputMismatchException  e )   {
             String  token  =  scanner . next ();
             throw   new   InputMismatchException ( "attempts to read a 'byte' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'byte' value from standard input, "
                                            +   "but no more tokens are available" );
         }
     }

     /**
     * Reads the next token from standard input, parses it as a boolean,
     * and returns the boolean.
     *
     *  @return  the next boolean on standard input
     *  @throws  NoSuchElementException if standard input is empty
     *  @throws  InputMismatchException if the next token cannot be parsed as a { @code  boolean}:
     *    { @code  true} or { @code  1} for true, and { @code  false} or { @code  0} for false,
     *    ignoring case
     */
     public   static   boolean  readBoolean ()   {
         try   {
             String  token  =  readString ();
             if   ( "true" . equalsIgnoreCase ( token ))    return   true ;
             if   ( "false" . equalsIgnoreCase ( token ))   return   false ;
             if   ( "1" . equals ( token ))                 return   true ;
             if   ( "0" . equals ( token ))                 return   false ;
             throw   new   InputMismatchException ( "attempts to read a 'boolean' value from standard input, "
                                            +   "but the next token is \""   +  token  +   "\"" );
         }
         catch   ( NoSuchElementException  e )   {
             throw   new   NoSuchElementException ( "attempts to read a 'boolean' value from standard input, "
                                            +   "but no more tokens are available" );
         }

     }

     /**
     * Reads all remaining tokens from standard input and returns them as an array of strings.
     *
     *  @return  all remaining tokens on standard input, as an array of strings
     */
     public   static   String []  readAllStrings ()   {
         // we could use readAll.trim().split(), but that's not consistent
         // because trim() uses characters 0x00..0x20 as whitespace
         String []  tokens  =  WHITESPACE_PATTERN . split ( readAll ());
         if   ( tokens . length  ==   0   ||  tokens [ 0 ]. length ()   >   0 )
             return  tokens ;

         // don't include first token if it is leading whitespace
         String []  decapitokens  =   new   String [ tokens . length - 1 ];
         for   ( int  i  =   0 ;  i  <  tokens . length  -   1 ;  i ++ )
            decapitokens [ i ]   =  tokens [ i + 1 ];
         return  decapitokens ;
     }

     /**
     * Reads all remaining lines from standard input and returns them as an array of strings.
     *  @return  all remaining lines on standard input, as an array of strings
     */
     public   static   String []  readAllLines ()   {
         ArrayList < String >  lines  =   new   ArrayList < String > ();
         while   ( hasNextLine ())   {
            lines . add ( readLine ());
         }
         return  lines . toArray ( new   String [ lines . size ()]);
     }

     /**
     * Reads all remaining tokens from standard input, parses them as integers, and returns
     * them as an array of integers.
     *  @return  all remaining integers on standard input, as an array
     *  @throws  InputMismatchException if any token cannot be parsed as an { @code  int}
     */
     public   static   int []  readAllInts ()   {
         String []  fields  =  readAllStrings ();
         int []  vals  =   new   int [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Integer . parseInt ( fields [ i ]);
         return  vals ;
     }

     /**
     * Reads all remaining tokens from standard input, parses them as longs, and returns
     * them as an array of longs.
     *  @return  all remaining longs on standard input, as an array
     *  @throws  InputMismatchException if any token cannot be parsed as a { @code  long}
     */
     public   static   long []  readAllLongs ()   {
         String []  fields  =  readAllStrings ();
         long []  vals  =   new   long [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Long . parseLong ( fields [ i ]);
         return  vals ;
     }

     /**
     * Reads all remaining tokens from standard input, parses them as doubles, and returns
     * them as an array of doubles.
     *  @return  all remaining doubles on standard input, as an array
     *  @throws  InputMismatchException if any token cannot be parsed as a { @code  double}
     */
     public   static   double []  readAllDoubles ()   {
         String []  fields  =  readAllStrings ();
         double []  vals  =   new   double [ fields . length ];
         for   ( int  i  =   0 ;  i  <  fields . length ;  i ++ )
            vals [ i ]   =   Double . parseDouble ( fields [ i ]);
         return  vals ;
     }
    
     //// end: section (2 of 2) of code duplicated from In to StdIn
    
    
     // do this once when StdIn is initialized
     static   {
        resync ();
     }

     /**
     * If StdIn changes, use this to reinitialize the scanner.
     */
     private   static   void  resync ()   {
        setScanner ( new   Scanner ( new  java . io . BufferedInputStream ( System . in ),  CHARSET_NAME ));
     }
    
     private   static   void  setScanner ( Scanner  scanner )   {
         StdIn . scanner  =  scanner ;
         StdIn . scanner . useLocale ( LOCALE );
     }

    /**
     * Reads all remaining tokens, parses them as integers, and returns
     * them as an array of integers.
     *  @return  all remaining integers, as an array
     *  @throws  InputMismatchException if any token cannot be parsed as an { @code  int}
     *  @deprecated  Replaced by { @link  #readAllInts()}.
     */
    @ Deprecated
     public   static   int []  readInts ()   {
         return  readAllInts ();
     }

    /**
     * Reads all remaining tokens, parses them as doubles, and returns
     * them as an array of doubles.
     *  @return  all remaining doubles, as an array
     *  @throws  InputMismatchException if any token cannot be parsed as a { @code  double}
     *  @deprecated  Replaced by { @link  #readAllDoubles()}.
     */
    @ Deprecated
     public   static   double []  readDoubles ()   {
         return  readAllDoubles ();
     }

    /**
     * Reads all remaining tokens and returns them as an array of strings.
     *  @return  all remaining tokens, as an array of strings
     *  @deprecated  Replaced by { @link  #readAllStrings()}.
     */
    @ Deprecated
     public   static   String []  readStrings ()   {
         return  readAllStrings ();
     }


     /**
     * Interactive test of basic functionality.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         StdOut . print ( "Type a string: " );
         String  s  =   StdIn . readString ();
         StdOut . println ( "Your string was: "   +  s );
         StdOut . println ();

         StdOut . print ( "Type an int: " );
         int  a  =   StdIn . readInt ();
         StdOut . println ( "Your int was: "   +  a );
         StdOut . println ();

         StdOut . print ( "Type a boolean: " );
         boolean  b  =   StdIn . readBoolean ();
         StdOut . println ( "Your boolean was: "   +  b );
         StdOut . println ();

         StdOut . print ( "Type a double: " );
         double  c  =   StdIn . readDouble ();
         StdOut . println ( "Your double was: "   +  c );
         StdOut . println ();
     }

}

StdInTest.java

StdInTest.java

/**
 * Test client for StdIn and In. 
 **/

import  java . util . Scanner ;
import  java . lang . reflect . Array ;
import  java . lang . reflect . Method ;
import  java . io . ByteArrayInputStream ;

public   class   StdInTest   {
     private   static   boolean  testStdIn ;
     private   static   Method  resyncMethod ;
     private   static   int  testCount  =   0 ;

    
     // make a printable/readable version of an object
     public   static   Object  escape ( Object  original )   {
         if   ( original  instanceof   Character )   {
             char  u  =   ( char )   (( Character )  original );
             int  idx  =   "\b\t\n\f\r\"\'\\" . indexOf ( u );
             if   ( idx  >=   0 )
                 return   "\\" + "btnfr\"\'\\" . charAt ( idx );
             if   ( <   32 )  
                 return   "\\" + Integer . toOctalString ( u );
             if   ( >   126 )  
                 return   "\\u"   +   String . format ( "%04X" ,   ( int )  u );
             return  original ;
         }
         else   if   ( original  instanceof   String )   {
             StringBuilder  result  =   new   StringBuilder ();
             for   ( char  c  :   (( String )  original ). toCharArray ())
                result . append ( escape ( c ));
             return   "\""   +  result . toString ()   +   "\"" ;
         }
         else   if   ( original . getClass (). isArray ())   {
             StringBuilder  result  =   new   StringBuilder ( "[" );
             int  len  =   Array . getLength ( original );
             for   ( int  i  =   0 ;  i  <  len ;  i ++ )
                result . append ( " " ). append ( escape ( Array . get ( original ,  i )));
             return  result . append ( "]" ). toString ();
         }
         return  original ;
     }
    
     public   static   boolean  canResync ()   {
         try   {
            resyncMethod  =   StdIn . class . getMethod ( "resync" );
         }
         catch   ( NoSuchMethodException  e )   {
             return   false ;
         }
         return   true ;
     }
    
     /**
     * In the two methods below, each Object[] of "steps" is a length-2
     * array: the first is a String holding a method name, the second
     * is the expected return value when that method is called in sequence.
     */
     public   static   void  test ( String  input ,   Object [][]  steps )   {
        test ( input ,  steps ,   false );   // create Scanner from String
         if   ( testStdIn )
            test ( input ,  steps ,   true );    // uses stdIn/System.setIn
        testCount ++ ;
     }
    
     public   static   void  test ( String  input ,   Object [][]  steps ,   boolean  useStdIn )   {
         In  in  =   null ;
         if   ( useStdIn )   {
             try   {
                 System . setIn ( new   ByteArrayInputStream ( input . getBytes ( "UTF-8" )));
             }
             catch   ( java . io . UnsupportedEncodingException  e )   {
                 throw   new   RuntimeException ( e . toString ());
             }

             // in order for this to work, you need to change resync to public
            
             try   {   //call StdIn.resync();
                resyncMethod . invoke ( null );
             }
             catch   ( IllegalAccessException  e )   {
                 throw   new   RuntimeException ( e . toString ());
             }
             catch   ( java . lang . reflect . InvocationTargetException  e )   {
                 throw   new   RuntimeException ( e . toString ());                    
             }
         }
         else  
            in  =   new   In ( new   Scanner ( input ));

         int  count  =   0 ;
         for   ( Object []  step  :  steps )   {
             String  cmd  =   ( String )  step [ 0 ];
             Object  expected  =  step [ 1 ];
             Object  result ;
            
             String  preamble  =   "Failed input %s\nStep %d (%s)\n" ;

             try   {
                 Method  method ;
                 // nice and easy since these methods take no arguments
                 if   ( useStdIn )
                    method  =   StdIn . class . getMethod ( cmd );
                 else
                    method  =  in . getClass (). getMethod ( cmd );
                result  =  method . invoke ( in );   // fine to be null for static
             }
             catch   ( NoSuchMethodException  e )   {
                java . io . StringWriter  errors  =   new  java . io . StringWriter ();
                e . printStackTrace ( new  java . io . PrintWriter ( errors ));
                 throw   new   RuntimeException ( String . format ( preamble ,  
                                                         input ,  count ,  cmd )   +
                                           errors . toString ());
             }
             catch   ( IllegalAccessException  e )   {
                java . io . StringWriter  errors  =   new  java . io . StringWriter ();
                e . printStackTrace ( new  java . io . PrintWriter ( errors ));
                 throw   new   RuntimeException ( String . format ( preamble ,  
                                                         input ,  count ,  cmd )   +
                                           errors . toString ());
             }
             catch   ( java . lang . reflect . InvocationTargetException  e )   {
                java . io . StringWriter  errors  =   new  java . io . StringWriter ();
                e . printStackTrace ( new  java . io . PrintWriter ( errors ));
                e . getCause (). printStackTrace ( new  java . io . PrintWriter ( errors ));
                 throw   new   RuntimeException ( String . format ( preamble ,  
                                                         input ,  count ,  cmd )   +
                                           errors . toString ());
             }
                        
             if   ( expected . getClass (). isArray ())   {
                 if   ( ! ( result . getClass (). isArray ()))   {
                     StdOut . printf ( preamble  +   "Expected array, got %s\n" ,
                                  input ,  count ,  cmd ,  result );
                     continue ;
                 }
                 Object  r  =  result ,  e  =  expected ;   // to shorten lines below
                 int  rl  =   Array . getLength ( r );
                 int  el  =   Array . getLength ( e );
                 if   ( el  !=  rl )
                     StdOut . printf ( preamble  +   "Expected %d, got %d items:\n%s\n" ,
                                  escape ( input ),  count ,  cmd ,  el ,  rl ,  escape ( r ));
                 else   {
                     for   ( int  i  =   0 ;  i  <  rl ;  i ++ )   {
                         if   ( ! ( Array . get ( r ,  i ). equals ( Array . get ( e ,  i ))))  
                         StdOut . printf ( preamble  +   "\nExpected [%d]=%s, got %s\n" ,
                                      escape ( input ),  count ,  cmd ,  i ,  
                                      escape ( Array . get ( e ,  i )),  
                                      escape ( Array . get ( r ,  i )));
                     }
                 }
             }
             else   if   ( ! result . equals ( expected ))   {
                 StdOut . printf ( preamble  +   "Expected %s, got %s\n" ,
                              escape ( input ),  count ,  cmd ,  escape ( expected ),  
                              escape ( result ));
             }
            count ++ ;
         }
     }
    
     public   static   void  main ( String []  args )   {
        testStdIn  =  canResync ();
        
         if   ( testStdIn )  
             StdOut . println ( "Note: any errors appear duplicated since tests run 2x." );
         else  
             StdOut . println ( "Note: StdIn.resync is private, only In will be tested." );

        test ( "this is a test" ,  
              new   Object [][]   {
             { "isEmpty" ,   false },   { "hasNextChar" ,   true },   { "hasNextLine" ,   true },
             { "readAllStrings" ,   new   String []   { "this" ,   "is" ,   "a" ,   "test" }},
             { "isEmpty" ,   true },   { "hasNextChar" ,   false },   { "hasNextLine" ,   false }
         });
        test ( "\n\n\n" ,  
              new   Object [][]   {
             { "isEmpty" ,   true },   { "hasNextChar" ,   true },   { "hasNextLine" ,   true },
             { "readAll" ,   "\n\n\n" }
         });
        test ( "" ,  
              new   Object [][]   {
             { "isEmpty" ,   true },   { "hasNextChar" ,   false },   { "hasNextLine" ,   false }
         });
        test ( "\t\t  \t\t" ,  
              new   Object [][]   {
             { "isEmpty" ,   true },   { "hasNextChar" ,   true },   { "hasNextLine" ,   true },
             { "readAll" ,   "\t\t  \t\t" }
         });
        test ( "readLine consumes newline\nyeah!" ,  
              new   Object [][]   {
             { "readLine" ,   "readLine consumes newline" },   { "readChar" ,   'y' }
         });
        test ( "readString doesn't consume spaces" ,  
              new   Object [][]   {
             { "readString" ,   "readString" },   { "readChar" ,   ' ' }
         });
        test ( "\n\nblank lines test" ,
              new   Object [][]   {
             { "readLine" ,   "" },   { "readLine" ,   "" },   { "hasNextLine" ,   true },
             { "readLine" ,   "blank lines test" },   { "hasNextLine" ,   false }
         });
        test ( "   \n  \t \n  correct  \n\t\n\t .trim replacement \n\t" ,
              new   Object [][]   {
             { "readAllStrings" ,   new   String []{ "correct" ,   ".trim" ,   "replacement" }},
             { "hasNextChar" ,   false }
         });
         StringBuilder  sb  =   new   StringBuilder ();
         Object [][]  expected  =   new   Object [ 2000 ][ 2 ];
         for   ( int  i = 0 ;  i  <   1000 ;  i ++ )   {
            sb . append (( char )  i );
            sb . append (( char )   ( +   8000 ));   // include weird non-breaking spaces
            expected [ 2 * i ][ 0 ]   =   "readChar" ;
            expected [ 2 * i + 1 ][ 0 ]   =   "readChar" ;
            expected [ 2 * i ][ 1 ]   =   ( char ) i ;
            expected [ 2 * i + 1 ][ 1 ]   =   ( char )( i + 8000 );
         }
        test ( sb . toString (),  expected );
        test ( " this \n and \that \n " ,
              new   Object [][]   {
             { "readString" ,   "this" },   { "readString" ,   "and" },   { "readChar" ,   ' ' },
             { "readString" ,   "hat" },   { "readChar" ,   ' ' },   { "isEmpty" ,   true },
             { "hasNextLine" ,   true },   { "readLine" ,   "" },   { "readLine" ,   " " }
         });
        test ( " 1 2 3 \n\t 4 5 " ,
              new   Object [][]   {
             { "readAllInts" ,   new   int []   { 1 ,   2 ,   3 ,   4 ,   5 }}
         });
        test ( " 0 1 False true falsE True " ,
              new   Object [][]   {
             { "readBoolean" ,   false },   { "readBoolean" ,   true },  
             { "readBoolean" ,   false },   { "readBoolean" ,   true },  
             { "readBoolean" ,   false },   { "readBoolean" ,   true }
         });
        test ( " \240\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008"
                  +   "\u2009\u200A\u205F\u3000" ,
              new   Object [][]   {
             { "readString" ,   "\240" },     // non-breaking space - not java whitespace
             { "readString" ,   "\u2007" },   // similarly
             { "hasNextChar" ,   true },   // there is some stuff left over
             { "isEmpty" ,   true },          // but it is all whitespace
             { "readChar" ,   '\u2008' }      // such as this one
         });
        
         // line sep, par sep, NEL, unit sep, vtab --- first 3 are newlines
         // NB: \205 is treated as a line separator, but not whitespace!
        test ( "a\u2028b\u2029c\37d\13e\205f" ,  
              new   Object [][]   {
             { "readAllStrings" ,   new   String []{ "a" ,   "b" ,   "c" ,   "d" ,   "e\205f" }}
         });
        test ( "a\u2028b\u2029c\37d\13e\205f" ,  
              new   Object [][]   {
             { "readLine" ,   "a" },
             { "readLine" ,   "b" },
             { "readLine" ,   "c\37d\13e" },
             { "readLine" ,   "f" }
         });
        test ( "\u2028\u2029" ,   // line separator, par separator
              new   Object [][]   {
             { "readLine" ,   "" },   { "hasNextLine" ,   true },   { "hasNextChar" ,   true },
             { "readLine" ,   "" },   { "hasNextLine" ,   false },   { "hasNextChar" ,   false }
         });
        test ( "\n\n" ,  
              new   Object [][]   {
             { "readLine" ,   "" },   { "hasNextLine" ,   true },   { "hasNextChar" ,   true },
             { "readLine" ,   "" },   { "hasNextLine" ,   false },   { "hasNextChar" ,   false }
         });
        test ( "\r\n\r\n" ,  
              new   Object [][]   {
             { "readLine" ,   "" },   { "hasNextLine" ,   true },   { "hasNextChar" ,   true },
             { "readLine" ,   "" },   { "hasNextLine" ,   false },   { "hasNextChar" ,   false }
         });
        test ( "\n\r" ,  
              new   Object [][]   {
             { "readLine" ,   "" },   { "hasNextLine" ,   true },   { "hasNextChar" ,   true },
             { "readLine" ,   "" },   { "hasNextLine" ,   false },   { "hasNextChar" ,   false }
         });
        test ( "\r\n" ,  
              new   Object [][]   {
             { "readLine" ,   "" },   { "hasNextChar" ,   false },   { "hasNextLine" ,   false }
         });
        test ( "3E4 \t -0.5 \n \t +4" ,  
              new   Object [][]   {
             { "readAllDoubles" ,   new   double []   { 30000 ,   - 0.5 ,   4 }}
         });
        test ( " whitespace " ,  
              new   Object [][]   {
             { "readString" ,   "whitespace" },   { "readChar" ,   ' ' },
             { "hasNextLine" ,   false }
         });
        test ( " whitespace \n" ,  
              new   Object [][]   {
             { "readString" ,   "whitespace" },   { "readChar" ,   ' ' },
             { "readLine" ,   "" },   { "hasNextLine" ,   false }
         });
        test ( " whitespace \n " ,  
              new   Object [][]   {
             { "readString" ,   "whitespace" },   { "readChar" ,   ' ' },
             { "readLine" ,   "" },   { "hasNextLine" ,   true },
             { "readLine" ,   " " },   { "hasNextLine" ,   false }
         });
        test ( " 34 -12983   3.25\n\t foo!" ,
              new   Object [][]   {
             { "readByte" ,   ( byte )   34 },  
             { "readShort" ,   ( short )   - 12983 },
             { "readDouble" ,   3.25 },
             { "readAll" ,   "\n\t foo!" }
         });
        test ( "30000000000  3.5 3e4, foo   \t\t ya" ,
              new   Object [][]   {
             { "readLong" ,   30000000000L },
             { "readFloat" ,   ( float )   3.5 },
             { "readAllStrings" ,   new   String []   { "3e4," ,   "foo" ,   "ya" }}
         });
         // testing consistency of whitespace and read(All)String(s)
        test ( " \u0001 foo \u0001 foo \u0001 foo" ,
              new   Object [][]   {
             { "readAllStrings" ,   new   String []   {
                 "\u0001" ,   "foo" ,   "\u0001" ,   "foo" ,   "\u0001" ,   "foo" }}
         });
        test ( " \u2005 foo \u2005 foo \u2005 foo" ,
              new   Object [][]   {
             { "readAllStrings" ,   new   String []   { "foo" ,   "foo" ,   "foo" }}
         });
        test ( " \u0001 foo \u0001 foo \u0001 foo" ,
              new   Object [][]   {
             { "readString" ,   "\u0001" },   { "readString" ,   "foo" },
             { "readString" ,   "\u0001" },   { "readString" ,   "foo" },
             { "readString" ,   "\u0001" },   { "readString" ,   "foo" }
         });
        test ( " \u2005 foo \u2005 foo \u2005 foo" ,
              new   Object [][]   {
             { "readString" ,   "foo" },   { "readString" ,   "foo" },   { "readString" ,   "foo" }
         });
         StdOut . printf ( "Ran %d tests.\n" ,  testCount );
     }
}

StdOut.java

StdOut.java

/******************************************************************************
 *  Compilation:  javac StdOut.java
 *  Execution:    java StdOut
 *  Dependencies: none
 *
 *  Writes data of various types to standard output.
 *
 ******************************************************************************/

import  java . io . OutputStreamWriter ;
import  java . io . PrintWriter ;
import  java . io . UnsupportedEncodingException ;
import  java . util . Locale ;

/**
 *  This class provides methods for printing strings and numbers to standard output.
 *  <p>
 *  <b>Getting started.</b>
 *  To use this class, you must have { @code  StdOut.class} in your
 *  Java classpath. If you used our autoinstaller, you should be all set.
 *  Otherwise, either download
 *  <a href = "https://introcs.cs.princeton.edu/java/code/stdlib.jar">stdlib.jar</a>
 *  and add to your Java classpath or download
 *  <a href = "https://introcs.cs.princeton.edu/java/stdlib/StdOut.java">StdOut.java</a>
 *  and put a copy in your working directory.
 *  <p>
 *  Here is an example program that uses { @code  StdOut}:
 *  <pre>
 *   public class TestStdOut {
 *       public static void main(String[] args) {
 *           int a = 17;
 *           int b = 23;
 *           int sum = a + b;
 *           StdOut.println("Hello, World");
 *           StdOut.printf("%d + %d = %d\n", a, b, sum);
 *       }
 *   }
 *  </pre>
 *  <p>
 *  <b>Differences with System.out.</b>
 *  The behavior of { @code  StdOut} is similar to that of { @link  System#out},
 *  but there are a few technical differences:
 *  <ul>
 *  <li> { @code  StdOut} coerces the character-set encoding to UTF-8,
 *       which is a standard character encoding for Unicode.
 *  <li> { @code  StdOut} coerces the locale to { @link  Locale#US},
 *       for consistency with { @link  StdIn}, { @link  Double#parseDouble(String)},
 *       and floating-point literals.
 *  <li> { @code  StdOut} <em>flushes</em> standard output after each call to
 *       { @code  print()} so that text will appear immediately in the terminal.
 *  </ul>
 *  <p>
 *  <b>Reference.</b>
 *  For additional documentation,
 *  see <a href="https://introcs.cs.princeton.edu/15inout">Section 1.5</a> of
 *  <em>Computer Science: An Interdisciplinary Approach</em>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   StdOut   {

     // force Unicode UTF-8 encoding; otherwise it's system dependent
     private   static   final   String  CHARSET_NAME  =   "UTF-8" ;

     // assume language = English, country = US for consistency with StdIn
     private   static   final   Locale  LOCALE  =   Locale . US ;

     // send output here
     private   static   PrintWriter  out ;

     // this is called before invoking any methods
     static   {
         try   {
            out  =   new   PrintWriter ( new   OutputStreamWriter ( System . out ,  CHARSET_NAME ),   true );
         }
         catch   ( UnsupportedEncodingException  e )   {
             System . out . println ( e );
         }
     }

     // don't instantiate
     private   StdOut ()   {   }

    /**
     * Terminates the current line by printing the line-separator string.
     */
     public   static   void  println ()   {
        out . println ();
     }

    /**
     * Prints an object to this output stream and then terminates the line.
     *
     *  @param  x the object to print
     */
     public   static   void  println ( Object  x )   {
        out . println ( x );
     }

    /**
     * Prints a boolean to standard output and then terminates the line.
     *
     *  @param  x the boolean to print
     */
     public   static   void  println ( boolean  x )   {
        out . println ( x );
     }

    /**
     * Prints a character to standard output and then terminates the line.
     *
     *  @param  x the character to print
     */
     public   static   void  println ( char  x )   {
        out . println ( x );
     }

    /**
     * Prints a double to standard output and then terminates the line.
     *
     *  @param  x the double to print
     */
     public   static   void  println ( double  x )   {
        out . println ( x );
     }

    /**
     * Prints an integer to standard output and then terminates the line.
     *
     *  @param  x the integer to print
     */
     public   static   void  println ( float  x )   {
        out . println ( x );
     }

    /**
     * Prints an integer to standard output and then terminates the line.
     *
     *  @param  x the integer to print
     */
     public   static   void  println ( int  x )   {
        out . println ( x );
     }

    /**
     * Prints a long to standard output and then terminates the line.
     *
     *  @param  x the long to print
     */
     public   static   void  println ( long  x )   {
        out . println ( x );
     }

    /**
     * Prints a short integer to standard output and then terminates the line.
     *
     *  @param  x the short to print
     */
     public   static   void  println ( short  x )   {
        out . println ( x );
     }

    /**
     * Prints a byte to standard output and then terminates the line.
     * <p>
     * To write binary data, see { @link  BinaryStdOut}.
     *
     *  @param  x the byte to print
     */
     public   static   void  println ( byte  x )   {
        out . println ( x );
     }

    /**
     * Flushes standard output.
     */
     public   static   void  print ()   {
        out . flush ();
     }

    /**
     * Prints an object to standard output and flushes standard output.
     * 
     *  @param  x the object to print
     */
     public   static   void  print ( Object  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a boolean to standard output and flushes standard output.
     * 
     *  @param  x the boolean to print
     */
     public   static   void  print ( boolean  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a character to standard output and flushes standard output.
     * 
     *  @param  x the character to print
     */
     public   static   void  print ( char  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a double to standard output and flushes standard output.
     * 
     *  @param  x the double to print
     */
     public   static   void  print ( double  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a float to standard output and flushes standard output.
     * 
     *  @param  x the float to print
     */
     public   static   void  print ( float  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints an integer to standard output and flushes standard output.
     * 
     *  @param  x the integer to print
     */
     public   static   void  print ( int  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a long integer to standard output and flushes standard output.
     * 
     *  @param  x the long integer to print
     */
     public   static   void  print ( long  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a short integer to standard output and flushes standard output.
     * 
     *  @param  x the short integer to print
     */
     public   static   void  print ( short  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a byte to standard output and flushes standard output.
     *
     *  @param  x the byte to print
     */
     public   static   void  print ( byte  x )   {
        out . print ( x );
        out . flush ();
     }

    /**
     * Prints a formatted string to standard output, using the specified format
     * string and arguments, and then flushes standard output.
     *
     *
     *  @param  format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
     *  @param  args   the arguments accompanying the format string
     */
     public   static   void  printf ( String  format ,   Object ...  args )   {
        out . printf ( LOCALE ,  format ,  args );
        out . flush ();
     }

    /**
     * Prints a formatted string to standard output, using the locale and
     * the specified format string and arguments; then flushes standard output.
     *
     *  @param  locale the locale
     *  @param  format the <a href = "http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">format string</a>
     *  @param  args   the arguments accompanying the format string
     */
     public   static   void  printf ( Locale  locale ,   String  format ,   Object ...  args )   {
        out . printf ( locale ,  format ,  args );
        out . flush ();
     }

    /**
     * Unit tests some of the methods in { @code  StdOut}.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {

         // write to stdout
         StdOut . println ( "Test" );
         StdOut . println ( 17 );
         StdOut . println ( true );
         StdOut . printf ( "%.6f\n" ,   1.0 / 7.0 );
     }

}

StdRandom.java

StdRandom.java

/******************************************************************************
 *  Compilation:  javac StdRandom.java
 *  Execution:    java StdRandom
 *  Dependencies: StdOut.java
 *
 *  A library of static methods to generate pseudo-random numbers from
 *  different distributions (bernoulli, uniform, gaussian, discrete,
 *  and exponential). Also includes a method for shuffling an array.
 *
 *
 *  %  java StdRandom 5
 *  seed = 1316600602069
 *  59 16.81826  true 8.83954  0 
 *  32 91.32098  true 9.11026  0 
 *  35 10.11874  true 8.95396  3 
 *  92 32.88401  true 8.87089  0 
 *  72 92.55791  true 9.46241  0 
 *
 *  % java StdRandom 5
 *  seed = 1316600616575
 *  96 60.17070  true 8.72821  0 
 *  79 32.01607  true 8.58159  0 
 *  81 59.49065  true 9.10423  1 
 *  96 51.65818  true 9.02102  0 
 *  99 17.55771  true 8.99762  0 
 *
 *  % java StdRandom 5 1316600616575
 *  seed = 1316600616575
 *  96 60.17070  true 8.72821  0 
 *  79 32.01607  true 8.58159  0 
 *  81 59.49065  true 9.10423  1 
 *  96 51.65818  true 9.02102  0 
 *  99 17.55771  true 8.99762  0 
 *
 *
 *  Remark
 *  ------
 *    - Relies on randomness of nextDouble() method in java.util.Random
 *      to generate pseudo-random numbers in [0, 1).
 *
 *    - This library allows you to set and get the pseudo-random number seed.
 *
 *    - See http://www.honeylocust.com/RngPack/ for an industrial
 *      strength random number generator in Java.
 *
 ******************************************************************************/

import  java . util . Random ;

/**
 *  The { @code  StdRandom} class provides static methods for generating
 *  random number from various discrete and continuous distributions, 
 *  including uniform, Bernoulli, geometric, Gaussian, exponential, Pareto,
 *  Poisson, and Cauchy. It also provides method for shuffling an
 *  array or subarray and generating random permutations.
 *  <p>
 *  By convention, all intervals are half open. For example,
 *  <code>uniform(-1.0, 1.0)</code> returns a random number between
 *  <code>-1.0</code> (inclusive) and <code>1.0</code> (exclusive).
 *  Similarly, <code>shuffle(a, lo, hi)</code> shuffles the <code>hi - lo</code>
 *  elements in the array <code>a[]</code>, starting at index <code>lo</code>
 *  (inclusive) and ending at index <code>hi</code> (exclusive).
 *  <p>
 *  For additional documentation,
 *  see <a href="https://introcs.cs.princeton.edu/22library">Section 2.2</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   StdRandom   {

     private   static   Random  random ;      // pseudo-random number generator
     private   static   long  seed ;          // pseudo-random number generator seed

     // static initializer
     static   {
         // this is how the seed was set in Java 1.4
        seed  =   System . currentTimeMillis ();
        random  =   new   Random ( seed );
     }

     // don't instantiate
     private   StdRandom ()   {   }

     /**
     * Sets the seed of the pseudo-random number generator.
     * This method enables you to produce the same sequence of "random"
     * number for each execution of the program.
     * Ordinarily, you should call this method at most once per program.
     *
     *  @param  s the seed
     */
     public   static   void  setSeed ( long  s )   {
        seed    =  s ;
        random  =   new   Random ( seed );
     }

     /**
     * Returns the seed of the pseudo-random number generator.
     *
     *  @return  the seed
     */
     public   static   long  getSeed ()   {
         return  seed ;
     }

     /**
     * Returns a random real number uniformly in [0, 1).
     *
     *  @return  a random real number uniformly in [0, 1)
     */
     public   static   double  uniform ()   {
         return  random . nextDouble ();
     }

     /**
     * Returns a random integer uniformly in [0, n).
     * 
     *  @param  n number of possible integers
     *  @return  a random integer uniformly between 0 (inclusive) and { @code  n} (exclusive)
     *  @throws  IllegalArgumentException if { @code  n <= 0}
     */
     public   static   int  uniform ( int  n )   {
         if   ( <=   0 )   throw   new   IllegalArgumentException ( "argument must be positive: "   +  n );
         return  random . nextInt ( n );
     }


     /**
     * Returns a random long integer uniformly in [0, n).
     * 
     *  @param  n number of possible { @code  long} integers
     *  @return  a random long integer uniformly between 0 (inclusive) and { @code  n} (exclusive)
     *  @throws  IllegalArgumentException if { @code  n <= 0}
     */
     public   static   long  uniform ( long  n )   {
         if   ( <=   0L )   throw   new   IllegalArgumentException ( "argument must be positive: "   +  n );

         // https://docs.oracle.com/javase/8/docs/api/java/util/Random.html#longs-long-long-long-
         long  r  =  random . nextLong ();
         long  m  =  n  -   1 ;

         // power of two
         if   (( &  m )   ==   0L )   {
             return  r  &  m ;
         }

         // reject over-represented candidates
         long  u  =  r  >>>   1 ;
         while   ( +  m  -   ( =  u  %  n )   <   0L )   {
            u  =  random . nextLong ()   >>>   1 ;
         }
         return  r ;
     }

     ///////////////////////////////////////////////////////////////////////////
     //  STATIC METHODS BELOW RELY ON JAVA.UTIL.RANDOM ONLY INDIRECTLY VIA
     //  THE STATIC METHODS ABOVE.
     ///////////////////////////////////////////////////////////////////////////

     /**
     * Returns a random real number uniformly in [0, 1).
     * 
     *  @return      a random real number uniformly in [0, 1)
     *  @deprecated  Replaced by { @link  #uniform()}.
     */
    @ Deprecated
     public   static   double  random ()   {
         return  uniform ();
     }

     /**
     * Returns a random integer uniformly in [a, b).
     * 
     *  @param   a the left endpoint
     *  @param   b the right endpoint
     *  @return  a random integer uniformly in [a, b)
     *  @throws  IllegalArgumentException if { @code  b <= a}
     *  @throws  IllegalArgumentException if { @code  b - a >= Integer.MAX_VALUE}
     */
     public   static   int  uniform ( int  a ,   int  b )   {
         if   (( <=  a )   ||   (( long )  b  -  a  >=   Integer . MAX_VALUE ))   {
             throw   new   IllegalArgumentException ( "invalid range: ["   +  a  +   ", "   +  b  +   ")" );
         }
         return  a  +  uniform ( -  a );
     }

     /**
     * Returns a random real number uniformly in [a, b).
     * 
     *  @param   a the left endpoint
     *  @param   b the right endpoint
     *  @return  a random real number uniformly in [a, b)
     *  @throws  IllegalArgumentException unless { @code  a < b}
     */
     public   static   double  uniform ( double  a ,   double  b )   {
         if   ( ! ( <  b ))   {
             throw   new   IllegalArgumentException ( "invalid range: ["   +  a  +   ", "   +  b  +   ")" );
         }
         return  a  +  uniform ()   *   ( b - a );
     }

     /**
     * Returns a random boolean from a Bernoulli distribution with success
     * probability <em>p</em>.
     *
     *  @param   p the probability of returning { @code  true}
     *  @return  { @code  true} with probability { @code  p} and
     *         { @code  false} with probability { @code  1 - p}
     *  @throws  IllegalArgumentException unless { @code  0} &le; { @code  p} &le; { @code  1.0}
     */
     public   static   boolean  bernoulli ( double  p )   {
         if   ( ! ( >=   0.0   &&  p  <=   1.0 ))
             throw   new   IllegalArgumentException ( "probability p must be between 0.0 and 1.0: "   +  p );
         return  uniform ()   <  p ;
     }

     /**
     * Returns a random boolean from a Bernoulli distribution with success
     * probability 1/2.
     * 
     *  @return  { @code  true} with probability 1/2 and
     *         { @code  false} with probability 1/2
     */
     public   static   boolean  bernoulli ()   {
         return  bernoulli ( 0.5 );
     }

     /**
     * Returns a random real number from a standard Gaussian distribution.
     * 
     *  @return  a random real number from a standard Gaussian distribution
     *         (mean 0 and standard deviation 1).
     */
     public   static   double  gaussian ()   {
         // use the polar form of the Box-Muller transform
         double  r ,  x ,  y ;
         do   {
            x  =  uniform ( - 1.0 ,   1.0 );
            y  =  uniform ( - 1.0 ,   1.0 );
            r  =  x * +  y * y ;
         }   while   ( >=   1   ||  r  ==   0 );
         return  x  *   Math . sqrt ( - 2   *   Math . log ( r )   /  r );

         // Remark:  y * Math.sqrt(-2 * Math.log(r) / r)
         // is an independent random gaussian
     }

     /**
     * Returns a random real number from a Gaussian distribution with mean &mu;
     * and standard deviation &sigma;.
     * 
     *  @param   mu the mean
     *  @param   sigma the standard deviation
     *  @return  a real number distributed according to the Gaussian distribution
     *         with mean { @code  mu} and standard deviation { @code  sigma}
     */
     public   static   double  gaussian ( double  mu ,   double  sigma )   {
         return  mu  +  sigma  *  gaussian ();
     }

     /**
     * Returns a random integer from a geometric distribution with success
     * probability <em>p</em>.
     * The integer represents the number of independent trials
     * before the first success.
     * 
     *  @param   p the parameter of the geometric distribution
     *  @return  a random integer from a geometric distribution with success
     *         probability { @code  p}; or { @code  Integer.MAX_VALUE} if
     *         { @code  p} is (nearly) equal to { @code  1.0}.
     *  @throws  IllegalArgumentException unless { @code  p >= 0.0} and { @code  p <= 1.0}
     */
     public   static   int  geometric ( double  p )   {
         if   ( ! ( >=   0 ))   {
             throw   new   IllegalArgumentException ( "probability p must be greater than 0: "   +  p );
         }
         if   ( ! ( <=   1.0 ))   {
             throw   new   IllegalArgumentException ( "probability p must not be larger than 1: "   +  p );
         }
         // using algorithm given by Knuth
         return   ( int )   Math . ceil ( Math . log ( uniform ())   /   Math . log ( 1.0   -  p ));
     }

     /**
     * Returns a random integer from a Poisson distribution with mean &lambda;.
     *
     *  @param   lambda the mean of the Poisson distribution
     *  @return  a random integer from a Poisson distribution with mean { @code  lambda}
     *  @throws  IllegalArgumentException unless { @code  lambda > 0.0} and not infinite
     */
     public   static   int  poisson ( double  lambda )   {
         if   ( ! ( lambda  >   0.0 ))
             throw   new   IllegalArgumentException ( "lambda must be positive: "   +  lambda );
         if   ( Double . isInfinite ( lambda ))
             throw   new   IllegalArgumentException ( "lambda must not be infinite: "   +  lambda );
         // using algorithm given by Knuth
         // see http://en.wikipedia.org/wiki/Poisson_distribution
         int  k  =   0 ;
         double  p  =   1.0 ;
         double  expLambda  =   Math . exp ( - lambda );
         do   {
            k ++ ;
            p  *=  uniform ();
         }   while   ( >=  expLambda );
         return  k - 1 ;
     }

     /**
     * Returns a random real number from the standard Pareto distribution.
     *
     *  @return  a random real number from the standard Pareto distribution
     */
     public   static   double  pareto ()   {
         return  pareto ( 1.0 );
     }

     /**
     * Returns a random real number from a Pareto distribution with
     * shape parameter &alpha;.
     *
     *  @param   alpha shape parameter
     *  @return  a random real number from a Pareto distribution with shape
     *         parameter { @code  alpha}
     *  @throws  IllegalArgumentException unless { @code  alpha > 0.0}
     */
     public   static   double  pareto ( double  alpha )   {
         if   ( ! ( alpha  >   0.0 ))
             throw   new   IllegalArgumentException ( "alpha must be positive: "   +  alpha );
         return   Math . pow ( 1   -  uniform (),   - 1.0 / alpha )   -   1.0 ;
     }

     /**
     * Returns a random real number from the Cauchy distribution.
     *
     *  @return  a random real number from the Cauchy distribution.
     */
     public   static   double  cauchy ()   {
         return   Math . tan ( Math . PI  *   ( uniform ()   -   0.5 ));
     }

     /**
     * Returns a random integer from the specified discrete distribution.
     *
     *  @param   probabilities the probability of occurrence of each integer
     *  @return  a random integer from a discrete distribution:
     *         { @code  i} with probability { @code  probabilities[i]}
     *  @throws  IllegalArgumentException if { @code  probabilities} is { @code  null}
     *  @throws  IllegalArgumentException if sum of array entries is not (very nearly) equal to { @code  1.0}
     *  @throws  IllegalArgumentException unless { @code  probabilities[i] >= 0.0} for each index { @code  i}
     */
     public   static   int  discrete ( double []  probabilities )   {
         if   ( probabilities  ==   null )   throw   new   IllegalArgumentException ( "argument array is null" );
         double  EPSILON  =   1.0E-14 ;
         double  sum  =   0.0 ;
         for   ( int  i  =   0 ;  i  <  probabilities . length ;  i ++ )   {
             if   ( ! ( probabilities [ i ]   >=   0.0 ))
                 throw   new   IllegalArgumentException ( "array entry "   +  i  +   " must be nonnegative: "   +  probabilities [ i ]);
            sum  +=  probabilities [ i ];
         }
         if   ( sum  >   1.0   +  EPSILON  ||  sum  <   1.0   -  EPSILON )
             throw   new   IllegalArgumentException ( "sum of array entries does not approximately equal 1.0: "   +  sum );

         // the for loop may not return a value when both r is (nearly) 1.0 and when the
         // cumulative sum is less than 1.0 (as a result of floating-point roundoff error)
         while   ( true )   {
             double  r  =  uniform ();
            sum  =   0.0 ;
             for   ( int  i  =   0 ;  i  <  probabilities . length ;  i ++ )   {
                sum  =  sum  +  probabilities [ i ];
                 if   ( sum  >  r )   return  i ;
             }
         }
     }

     /**
     * Returns a random integer from the specified discrete distribution.
     *
     *  @param   frequencies the frequency of occurrence of each integer
     *  @return  a random integer from a discrete distribution:
     *         { @code  i} with probability proportional to { @code  frequencies[i]}
     *  @throws  IllegalArgumentException if { @code  frequencies} is { @code  null}
     *  @throws  IllegalArgumentException if all array entries are { @code  0}
     *  @throws  IllegalArgumentException if { @code  frequencies[i]} is negative for any index { @code  i}
     *  @throws  IllegalArgumentException if sum of frequencies exceeds { @code  Integer.MAX_VALUE} (2<sup>31</sup> - 1)
     */
     public   static   int  discrete ( int []  frequencies )   {
         if   ( frequencies  ==   null )   throw   new   IllegalArgumentException ( "argument array is null" );
         long  sum  =   0 ;
         for   ( int  i  =   0 ;  i  <  frequencies . length ;  i ++ )   {
             if   ( frequencies [ i ]   <   0 )
                 throw   new   IllegalArgumentException ( "array entry "   +  i  +   " must be nonnegative: "   +  frequencies [ i ]);
            sum  +=  frequencies [ i ];
         }
         if   ( sum  ==   0 )
             throw   new   IllegalArgumentException ( "at least one array entry must be positive" );
         if   ( sum  >=   Integer . MAX_VALUE )
             throw   new   IllegalArgumentException ( "sum of frequencies overflows an int" );

         // pick index i with probabilitity proportional to frequency
         double  r  =  uniform (( int )  sum );
        sum  =   0 ;
         for   ( int  i  =   0 ;  i  <  frequencies . length ;  i ++ )   {
            sum  +=  frequencies [ i ];
             if   ( sum  >  r )   return  i ;
         }

         // can't reach here
         assert   false ;
         return   - 1 ;
     }

     /**
     * Returns a random real number from an exponential distribution
     * with rate &lambda;.
     * 
     *  @param   lambda the rate of the exponential distribution
     *  @return  a random real number from an exponential distribution with
     *         rate { @code  lambda}
     *  @throws  IllegalArgumentException unless { @code  lambda > 0.0}
     */
     public   static   double  exp ( double  lambda )   {
         if   ( ! ( lambda  >   0.0 ))
             throw   new   IllegalArgumentException ( "lambda must be positive: "   +  lambda );
         return   - Math . log ( 1   -  uniform ())   /  lambda ;
     }

     /**
     * Rearranges the elements of the specified array in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     */
     public   static   void  shuffle ( Object []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             int  r  =  i  +  uniform ( n - i );       // between i and n-1
             Object  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified array in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     */
     public   static   void  shuffle ( double []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             int  r  =  i  +  uniform ( n - i );       // between i and n-1
             double  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified array in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     */
     public   static   void  shuffle ( int []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             int  r  =  i  +  uniform ( n - i );       // between i and n-1
             int  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified array in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     */
     public   static   void  shuffle ( char []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             int  r  =  i  +  uniform ( n - i );       // between i and n-1
             char  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified subarray in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @param   lo the left endpoint (inclusive)
     *  @param   hi the right endpoint (exclusive)
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     * 
     */
     public   static   void  shuffle ( Object []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
             int  r  =  i  +  uniform ( hi - i );       // between i and hi-1
             Object  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified subarray in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @param   lo the left endpoint (inclusive)
     *  @param   hi the right endpoint (exclusive)
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   void  shuffle ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
             int  r  =  i  +  uniform ( hi - i );       // between i and hi-1
             double  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Rearranges the elements of the specified subarray in uniformly random order.
     *
     *  @param   a the array to shuffle
     *  @param   lo the left endpoint (inclusive)
     *  @param   hi the right endpoint (exclusive)
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   void  shuffle ( int []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
             int  r  =  i  +  uniform ( hi - i );       // between i and hi-1
             int  temp  =  a [ i ];
            a [ i ]   =  a [ r ];
            a [ r ]   =  temp ;
         }
     }

     /**
     * Returns a uniformly random permutation of <em>n</em> elements.
     *
     *  @param   n number of elements
     *  @throws  IllegalArgumentException if { @code  n} is negative
     *  @return  an array of length { @code  n} that is a uniformly random permutation
     *         of { @code  0}, { @code  1}, ..., { @code  n-1}
     */
     public   static   int []  permutation ( int  n )   {
         if   ( <   0 )   throw   new   IllegalArgumentException ( "argument is negative" );
         int []  perm  =   new   int [ n ];
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )
            perm [ i ]   =  i ;
        shuffle ( perm );
         return  perm ;
     }

     /**
     * Returns a uniformly random permutation of <em>k</em> of <em>n</em> elements.
     *
     *  @param   n number of elements
     *  @param   k number of elements to select
     *  @throws  IllegalArgumentException if { @code  n} is negative
     *  @throws  IllegalArgumentException unless { @code  0 <= k <= n}
     *  @return  an array of length { @code  k} that is a uniformly random permutation
     *         of { @code  k} of the elements from { @code  0}, { @code  1}, ..., { @code  n-1}
     */
     public   static   int []  permutation ( int  n ,   int  k )   {
         if   ( <   0 )   throw   new   IllegalArgumentException ( "argument is negative" );
         if   ( <   0   ||  k  >  n )   throw   new   IllegalArgumentException ( "k must be between 0 and n" );
         int []  perm  =   new   int [ k ];
         for   ( int  i  =   0 ;  i  <  k ;  i ++ )   {
             int  r  =  uniform ( i + 1 );      // between 0 and i
            perm [ i ]   =  perm [ r ];
            perm [ r ]   =  i ;
         }
         for   ( int  i  =  k ;  i  <  n ;  i ++ )   {
             int  r  =  uniform ( i + 1 );      // between 0 and i
             if   ( <  k )  perm [ r ]   =  i ;
         }
         return  perm ;
     }

     // throw an IllegalArgumentException if x is null
     // (x can be of type Object[], double[], int[], ...)
     private   static   void  validateNotNull ( Object  x )   {
         if   ( ==   null )   {
             throw   new   IllegalArgumentException ( "argument is null" );
         }
     }

     // throw an exception unless 0 <= lo <= hi <= length
     private   static   void  validateSubarrayIndices ( int  lo ,   int  hi ,   int  length )   {
         if   ( lo  <   0   ||  hi  >  length  ||  lo  >  hi )   {
             throw   new   IllegalArgumentException ( "subarray indices out of bounds: ["   +  lo  +   ", "   +  hi  +   ")" );
         }
     }

     /**
     * Unit tests the methods in this class.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         int  n  =   Integer . parseInt ( args [ 0 ]);
         if   ( args . length  ==   2 )   StdRandom . setSeed ( Long . parseLong ( args [ 1 ]));
         double []  probabilities  =   {   0.5 ,   0.3 ,   0.1 ,   0.1   };
         int []  frequencies  =   {   5 ,   3 ,   1 ,   1   };
         String []  a  =   "A B C D E F G" . split ( " " );

         StdOut . println ( "seed = "   +   StdRandom . getSeed ());
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             StdOut . printf ( "%2d " ,    uniform ( 100 ));
             StdOut . printf ( "%8.5f " ,  uniform ( 10.0 ,   99.0 ));
             StdOut . printf ( "%5b " ,    bernoulli ( 0.5 ));
             StdOut . printf ( "%7.5f " ,  gaussian ( 9.0 ,   0.2 ));
             StdOut . printf ( "%1d " ,    discrete ( probabilities ));
             StdOut . printf ( "%1d " ,    discrete ( frequencies ));
             StdOut . printf ( "%11d " ,   uniform ( 100000000000L ));
             StdRandom . shuffle ( a );
             for   ( String  s  :  a )
                 StdOut . print ( s );
             StdOut . println ();
         }
     }

}

StdStats.java

StdStats.java

/******************************************************************************
 *  Compilation:  javac StdStats.java
 *  Execution:    java StdStats < input.txt
 *  Dependencies: StdOut.java
 *
 *  Library of statistical functions.
 *
 *  The test client reads an array of real numbers from standard
 *  input, and computes the minimum, mean, maximum, and
 *  standard deviation.
 *
 *  The functions all throw a java.lang.IllegalArgumentException
 *  if the array passed in as an argument is null.
 *
 *  The floating-point functions all return NaN if any input is NaN.
 *
 *  Unlike Math.min() and Math.max(), the min() and max() functions
 *  do not differentiate between -0.0 and 0.0.
 *
 *  % more tiny.txt
 *  5
 *  3.0 1.0 2.0 5.0 4.0
 *
 *  % java StdStats < tiny.txt
 *         min   1.000
 *        mean   3.000
 *         max   5.000
 *     std dev   1.581
 *
 *  Should these funtions use varargs instead of array arguments?
 *
 ******************************************************************************/

/**
 *  The { @code  StdStats} class provides static methods for computing
 *  statistics such as min, max, mean, sample standard deviation, and
 *  sample variance.
 *  <p>
 *  For additional documentation, see
 *  <a href="https://introcs.cs.princeton.edu/22library">Section 2.2</a> of
 *  <i>Computer Science: An Interdisciplinary Approach</i>
 *  by Robert Sedgewick and Kevin Wayne.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */
public   final   class   StdStats   {

     private   StdStats ()   {   }

     /**
     * Returns the maximum value in the specified array.
     *
     *  @param   a the array
     *  @return  the maximum value in the array { @code  a[]};
     *         { @code  Double.NEGATIVE_INFINITY} if no such value
     */
     public   static   double  max ( double []  a )   {
        validateNotNull ( a );

         double  max  =   Double . NEGATIVE_INFINITY ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
             if   ( Double . isNaN ( a [ i ]))   return   Double . NaN ;
             if   ( a [ i ]   >  max )  max  =  a [ i ];
         }
         return  max ;
     }

     /**
     * Returns the maximum value in the specified subarray.
     *
     *  @param   a the array
     *  @param   lo the left endpoint of the subarray (inclusive)
     *  @param   hi the right endpoint of the subarray (exclusive)
     *  @return  the maximum value in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NEGATIVE_INFINITY} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null}
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  max ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         double  max  =   Double . NEGATIVE_INFINITY ;
         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
             if   ( Double . isNaN ( a [ i ]))   return   Double . NaN ;
             if   ( a [ i ]   >  max )  max  =  a [ i ];
         }
         return  max ;
     }

     /**
     * Returns the maximum value in the specified array.
     *
     *  @param   a the array
     *  @return  the maximum value in the array { @code  a[]};
     *         { @code  Integer.MIN_VALUE} if no such value
     */
     public   static   int  max ( int []  a )   {
        validateNotNull ( a );

         int  max  =   Integer . MIN_VALUE ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
             if   ( a [ i ]   >  max )  max  =  a [ i ];
         }
         return  max ;
     }

     /**
     * Returns the minimum value in the specified array.
     *
     *  @param   a the array
     *  @return  the minimum value in the array { @code  a[]};
     *         { @code  Double.POSITIVE_INFINITY} if no such value
     */
     public   static   double  min ( double []  a )   {
        validateNotNull ( a );

         double  min  =   Double . POSITIVE_INFINITY ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
             if   ( Double . isNaN ( a [ i ]))   return   Double . NaN ;
             if   ( a [ i ]   <  min )  min  =  a [ i ];
         }
         return  min ;
     }

     /**
     * Returns the minimum value in the specified subarray.
     *
     *  @param   a the array
     *  @param   lo the left endpoint of the subarray (inclusive)
     *  @param   hi the right endpoint of the subarray (exclusive)
     *  @return  the maximum value in the subarray { @code  a[lo..hi)};
     *         { @code  Double.POSITIVE_INFINITY} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  min ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         double  min  =   Double . POSITIVE_INFINITY ;
         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
             if   ( Double . isNaN ( a [ i ]))   return   Double . NaN ;
             if   ( a [ i ]   <  min )  min  =  a [ i ];
         }
         return  min ;
     }

     /**
     * Returns the minimum value in the specified array.
     *
     *  @param   a the array
     *  @return  the minimum value in the array { @code  a[]};
     *         { @code  Integer.MAX_VALUE} if no such value
     */
     public   static   int  min ( int []  a )   {
        validateNotNull ( a );

         int  min  =   Integer . MAX_VALUE ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
             if   ( a [ i ]   <  min )  min  =  a [ i ];
         }
         return  min ;
     }

     /**
     * Returns the average value in the specified array.
     *
     *  @param   a the array
     *  @return  the average value in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  mean ( double []  a )   {
        validateNotNull ( a );

         if   ( a . length  ==   0 )   return   Double . NaN ;
         double  sum  =  sum ( a );
         return  sum  /  a . length ;
     }

     /**
     * Returns the average value in the specified subarray.
     *
     *  @param  a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the average value in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NaN} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  mean ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         int  length  =  hi  -  lo ;
         if   ( length  ==   0 )   return   Double . NaN ;

         double  sum  =  sum ( a ,  lo ,  hi );
         return  sum  /  length ;
     }

     /**
     * Returns the average value in the specified array.
     *
     *  @param   a the array
     *  @return  the average value in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  mean ( int []  a )   {
        validateNotNull ( a );

         if   ( a . length  ==   0 )   return   Double . NaN ;
         int  sum  =  sum ( a );
         return   1.0   *  sum  /  a . length ;
     }

     /**
     * Returns the sample variance in the specified array.
     *
     *  @param   a the array
     *  @return  the sample variance in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  var ( double []  a )   {
        validateNotNull ( a );

         if   ( a . length  ==   0 )   return   Double . NaN ;
         double  avg  =  mean ( a );
         double  sum  =   0.0 ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
            sum  +=   ( a [ i ]   -  avg )   *   ( a [ i ]   -  avg );
         }
         return  sum  /   ( a . length  -   1 );
     }

     /**
     * Returns the sample variance in the specified subarray.
     *
     *  @param   a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the sample variance in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NaN} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  var ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         int  length  =  hi  -  lo ;
         if   ( length  ==   0 )   return   Double . NaN ;

         double  avg  =  mean ( a ,  lo ,  hi );
         double  sum  =   0.0 ;
         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
            sum  +=   ( a [ i ]   -  avg )   *   ( a [ i ]   -  avg );
         }
         return  sum  /   ( length  -   1 );
     }

     /**
     * Returns the sample variance in the specified array.
     *
     *  @param   a the array
     *  @return  the sample variance in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  var ( int []  a )   {
        validateNotNull ( a );
         if   ( a . length  ==   0 )   return   Double . NaN ;
         double  avg  =  mean ( a );
         double  sum  =   0.0 ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
            sum  +=   ( a [ i ]   -  avg )   *   ( a [ i ]   -  avg );
         }
         return  sum  /   ( a . length  -   1 );
     }

     /**
     * Returns the population variance in the specified array.
     *
     *  @param   a the array
     *  @return  the population variance in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  varp ( double []  a )   {
        validateNotNull ( a );
         if   ( a . length  ==   0 )   return   Double . NaN ;
         double  avg  =  mean ( a );
         double  sum  =   0.0 ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
            sum  +=   ( a [ i ]   -  avg )   *   ( a [ i ]   -  avg );
         }
         return  sum  /  a . length ;
     }

     /**
     * Returns the population variance in the specified subarray.
     *
     *  @param   a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the population variance in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NaN} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  varp ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         int  length  =  hi  -  lo ;
         if   ( length  ==   0 )   return   Double . NaN ;

         double  avg  =  mean ( a ,  lo ,  hi );
         double  sum  =   0.0 ;
         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
            sum  +=   ( a [ i ]   -  avg )   *   ( a [ i ]   -  avg );
         }
         return  sum  /  length ;
     }

     /**
     * Returns the sample standard deviation in the specified array.
     *
     *  @param   a the array
     *  @return  the sample standard deviation in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  stddev ( double []  a )   {
        validateNotNull ( a );
         return   Math . sqrt ( var ( a ));
     }

     /**
     * Returns the sample standard deviation in the specified array.
     *
     *  @param   a the array
     *  @return  the sample standard deviation in the array { @code  a[]};
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  stddev ( int []  a )   {
        validateNotNull ( a );
         return   Math . sqrt ( var ( a ));
     }

     /**
     * Returns the sample standard deviation in the specified subarray.
     *
     *  @param   a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the sample standard deviation in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NaN} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  stddev ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         return   Math . sqrt ( var ( a ,  lo ,  hi ));
     }


     /**
     * Returns the population standard deviation in the specified array.
     *
     *  @param   a the array
     *  @return  the population standard deviation in the array;
     *         { @code  Double.NaN} if no such value
     */
     public   static   double  stddevp ( double []  a )   {
        validateNotNull ( a );
         return   Math . sqrt ( varp ( a ));
     }

     /**
     * Returns the population standard deviation in the specified subarray.
     *
     *  @param   a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the population standard deviation in the subarray { @code  a[lo..hi)};
     *         { @code  Double.NaN} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     public   static   double  stddevp ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         return   Math . sqrt ( varp ( a ,  lo ,  hi ));
     }

     /**
     * Returns the sum of all values in the specified array.
     *
     *  @param   a the array
     *  @return  the sum of all values in the array { @code  a[]};
     *         { @code  0.0} if no such value
     */
     private   static   double  sum ( double []  a )   {
        validateNotNull ( a );
         double  sum  =   0.0 ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
            sum  +=  a [ i ];
         }
         return  sum ;
     }

     /**
     * Returns the sum of all values in the specified subarray.
     *
     *  @param   a the array
     *  @param  lo the left endpoint of the subarray (inclusive)
     *  @param  hi the right endpoint of the subarray (exclusive)
     *  @return  the sum of all values in the subarray { @code  a[lo..hi)};
     *         { @code  0.0} if no such value
     *  @throws  IllegalArgumentException if { @code  a} is { @code  null} 
     *  @throws  IllegalArgumentException unless { @code  (0 <= lo) && (lo < hi) && (hi <= a.length)}
     */
     private   static   double  sum ( double []  a ,   int  lo ,   int  hi )   {
        validateNotNull ( a );
        validateSubarrayIndices ( lo ,  hi ,  a . length );

         double  sum  =   0.0 ;
         for   ( int  i  =  lo ;  i  <  hi ;  i ++ )   {
            sum  +=  a [ i ];
         }
         return  sum ;
     }

     /**
     * Returns the sum of all values in the specified array.
     *
     *  @param   a the array
     *  @return  the sum of all values in the array { @code  a[]};
     *         { @code  0.0} if no such value
     */
     private   static   int  sum ( int []  a )   {
        validateNotNull ( a );
         int  sum  =   0 ;
         for   ( int  i  =   0 ;  i  <  a . length ;  i ++ )   {
            sum  +=  a [ i ];
         }
         return  sum ;
     }

    /**
     * Plots the points (0, <em>a</em><sub>0</sub>), (1, <em>a</em><sub>1</sub>), ...,
     * (<em>n</em>-1, <em>a</em><sub><em>n</em>-1</sub>) to standard draw.
     *
     *  @param  a the array of values
     */
     public   static   void  plotPoints ( double []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         StdDraw . setXscale ( - 1 ,  n );
         StdDraw . setPenRadius ( 1.0   /   ( 3.0   *  n ));
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             StdDraw . point ( i ,  a [ i ]);
         }
     }

    /**
     * Plots the line segments connecting 
     * (<em>i</em>, <em>a</em><sub><em>i</em></sub>) to
     * (<em>i</em>+1, <em>a</em><sub><em>i</em>+1</sub>) for 
     * each <em>i</em> to standard draw.
     *
     *  @param  a the array of values
     */
     public   static   void  plotLines ( double []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         StdDraw . setXscale ( - 1 ,  n );
         StdDraw . setPenRadius ();
         for   ( int  i  =   1 ;  i  <  n ;  i ++ )   {
             StdDraw . line ( i - 1 ,  a [ i - 1 ],  i ,  a [ i ]);
         }
     }

    /**
     * Plots bars from (0, <em>a</em><sub><em>i</em></sub>) to
     * (<em>a</em><sub><em>i</em></sub>) for each <em>i</em>
     * to standard draw.
     *
     *  @param  a the array of values
     */
     public   static   void  plotBars ( double []  a )   {
        validateNotNull ( a );
         int  n  =  a . length ;
         StdDraw . setXscale ( - 1 ,  n );
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             StdDraw . filledRectangle ( i ,  a [ i ] / 2 ,   0.25 ,  a [ i ] / 2 );
         }
     }

     // throw an IllegalArgumentException if x is null
     // (x is either of type double[] or int[])
     private   static   void  validateNotNull ( Object  x )   {
         if   ( ==   null )
             throw   new   IllegalArgumentException ( "argument is null" );
     }

     // throw an exception unless 0 <= lo <= hi <= length
     private   static   void  validateSubarrayIndices ( int  lo ,   int  hi ,   int  length )   {
         if   ( lo  <   0   ||  hi  >  length  ||  lo  >  hi )
             throw   new   IllegalArgumentException ( "subarray indices out of bounds: ["   +  lo  +   ", "   +  hi  +   ")" );
     }


    /**
     * Unit tests { @code  StdStats}.
     * Convert command-line arguments to array of doubles and call various methods.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         double []  a  =   StdArrayIO . readDouble1D ();
         StdOut . printf ( "       min %10.3f\n" ,  min ( a ));
         StdOut . printf ( "      mean %10.3f\n" ,  mean ( a ));
         StdOut . printf ( "       max %10.3f\n" ,  max ( a ));
         StdOut . printf ( "    stddev %10.3f\n" ,  stddev ( a ));
         StdOut . printf ( "       var %10.3f\n" ,  var ( a ));
         StdOut . printf ( "   stddevp %10.3f\n" ,  stddevp ( a ));
         StdOut . printf ( "      varp %10.3f\n" ,  varp ( a ));
     }
}

StopwatchCPU.java

StopwatchCPU.java

/******************************************************************************
 *  Compilation:  javac StopwatchCPU.java
 *  Execution:    none
 *  Dependencies: none
 *
 *  A version of Stopwatch.java that measures CPU time on a single
 *  core or processor (instead of wall clock time).
 *
 ******************************************************************************/

import  java . lang . management . ThreadMXBean ;
import  java . lang . management . ManagementFactory ;

/**
 *  The { @code  StopwatchCPU} data type is for measuring
 *  the CPU time used during a programming task.
 *
 *  See { @link  Stopwatch} for a version that measures wall-clock time
 *  (the real time that elapses).
 *
 *   @author  Josh Hug
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */

public   class   StopwatchCPU   {
     private   static   final   double  NANOSECONDS_PER_SECOND  =   1000000000 ;

     private   final   ThreadMXBean  threadTimer ;
     private   final   long  start ;
            
     /**
     * Initializes a new stopwatch.
     */
     public   StopwatchCPU ()   {   
        threadTimer  =   ManagementFactory . getThreadMXBean ();
        start  =  threadTimer . getCurrentThreadCpuTime ();
     }    
        
     /**
     * Returns the elapsed CPU time (in seconds) since the stopwatch was created.
     *
     *  @return  elapsed CPU time (in seconds) since the stopwatch was created
     */
     public   double  elapsedTime ()   {
         long  now  =  threadTimer . getCurrentThreadCpuTime ();
         return   ( now  -  start )   /  NANOSECONDS_PER_SECOND ;
     }    
}

Stopwatch.java

Stopwatch.java

/******************************************************************************
 *  Compilation:  javac Stopwatch.java
 *  Execution:    java Stopwatch n
 *  Dependencies: none
 *
 *  A utility class to measure the running time (wall clock) of a program.
 *
 *  % java8 Stopwatch 100000000
 *  6.666667e+11  0.5820 seconds
 *  6.666667e+11  8.4530 seconds
 *
 ******************************************************************************/

/**
 *  The { @code  Stopwatch} data type is for measuring
 *  the time that elapses between the start and end of a
 *  programming task (wall-clock time).
 *
 *  See { @link  StopwatchCPU} for a version that measures CPU time.
 *
 *   @author  Robert Sedgewick
 *   @author  Kevin Wayne
 */


public   class   Stopwatch   {  

     private   final   long  start ;

     /**
     * Initializes a new stopwatch.
     */
     public   Stopwatch ()   {
        start  =   System . currentTimeMillis ();
     }  


     /**
     * Returns the elapsed CPU time (in seconds) since the stopwatch was created.
     *
     *  @return  elapsed CPU time (in seconds) since the stopwatch was created
     */
     public   double  elapsedTime ()   {
         long  now  =   System . currentTimeMillis ();
         return   ( now  -  start )   /   1000.0 ;
     }

    
     /**
     * Unit tests the { @code  Stopwatch} data type.
     * Takes a command-line argument { @code  n} and computes the 
     * sum of the square roots of the first { @code  n} positive integers,
     * first using { @code  Math.sqrt()}, then using { @code  Math.pow()}.
     * It prints to standard output the sum and the amount of time to
     * compute the sum. Note that the discrete sum can be approximated by
     * an integral - the sum should be approximately 2/3 * (n^(3/2) - 1).
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         int  n  =   Integer . parseInt ( args [ 0 ]);

         // sum of square roots of integers from 1 to n using Math.sqrt(x).
         Stopwatch  timer1  =   new   Stopwatch ();
         double  sum1  =   0.0 ;
         for   ( int  i  =   1 ;  i  <=  n ;  i ++ )   {
            sum1  +=   Math . sqrt ( i );
         }
         double  time1  =  timer1 . elapsedTime ();
         StdOut . printf ( "%e (%.2f seconds)\n" ,  sum1 ,  time1 );

         // sum of square roots of integers from 1 to n using Math.pow(x, 0.5).
         Stopwatch  timer2  =   new   Stopwatch ();
         double  sum2  =   0.0 ;
         for   ( int  i  =   1 ;  i  <=  n ;  i ++ )   {
            sum2  +=   Math . pow ( i ,   0.5 );
         }
         double  time2  =  timer2 . elapsedTime ();
         StdOut . printf ( "%e (%.2f seconds)\n" ,  sum2 ,  time2 );
     }
}  

TestIntroCS.java

TestIntroCS.java

/******************************************************************************
 *  Compilation:  javac-introcs TestIntroCS.java
 *  Execution:    java-introcs TestIntroCS n
 *  
 *  Play chaos game to produce Barnsley's fern.
 *  This program is intended to test that stdlib.jar is properly installed.
 *
 *  % java-introcs TestIntroCS 10000
 * 
 ******************************************************************************/

public   class   TestIntroCS   {

     public   static   void  main ( String []  args )   {
         int  n  =   10000 ;    // number of points to draw (default 10000)
         if   ( args . length  ==   1 )   {
            n  =   Integer . parseInt ( args [ 0 ]);
         }
         StdDraw . setScale ( - 0.1 ,   1.1 );                // leave a 10% border
         StdDraw . clear ( StdDraw . BOOK_LIGHT_BLUE );     // background color
         StdDraw . setPenColor ( 0 ,   114 ,   0 );             // a shade of green

         // starting point
         double  x  =   0.5 ;
         double  y  =   0.0 ;

         // repeated choose one of four update rules at random
         for   ( int  i  =   0 ;  i  <  n ;  i ++ )   {
             double  tempx ,  tempy ;
             double  r  =   StdRandom . uniform ( 0.0 ,   1.0 );

             // stem
             if   ( <=   0.01 )    {
                tempx  =   0.50 ;
                tempy  =   0.16   *  y ;
             }

             // largest left-hand leaflet
             else   if   ( <=   0.08 )   {
                tempx  =    0.20   *  x  -   0.26   *  y  +   0.400 ;
                tempy  =    0.23   *  x  +   0.22   *  y  -   0.045 ;
             }

             // largest right-hand leaflet
             else   if   ( <=   0.15 )   {
                tempx  =   - 0.15   *  x  +   0.28   *  y  +   0.575 ;
                tempy  =    0.26   *  x  +   0.24   *  y  -   0.086 ;
             }

             // successively smaller leaflets
             else   {
                tempx  =    0.85   *  x  +   0.04   *  y  +   0.075 ;
                tempy  =   - 0.04   *  x  +   0.85   *  y  +   0.180 ;
             }

             // update (x, y) and draw point
            x  =  tempx ;
            y  =  tempy ;
             StdDraw . point ( x ,  y );
         }
     }    
}

UnicodeTest.java

UnicodeTest.java

/******************************************************************************
 *  Compilation:  javac-introcs  UnicodeTest.java
 *  Execution:    java-introcs  UnicodeTest
 *  Dependencies: StdOut.java
 *
 *  This programs prints out all of the Unicode characters in the basic
 *  multilingual plane (U+0000 to U+FFFF) in a table. It skips the
 *  following types of characters:
 *    -  undefined
 *    -  control characters
 *    -  modifier symbols
 *    -  non-spacing marks
 *    -  Unicode formatting commands
 *    -  reserved for surrogate pairs
 *    -  reserved for private use
 *
 *
 *  % java-introcs UnicodeTest
 *  U+0020      !  "  #  $  %  &  '  (  )  *  +  ,  -  .  /  
 *  U+0030   0  1  2  3  4  5  6  7  8  9  :  ;  <  =  >  ?  
 *  U+0040   @  A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  
 *  U+0050   P  Q  R  S  T  U  V  W  X  Y  Z  [  \  ]     _  
 *  U+0060      a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  
 *  U+0070   p  q  r  s  t  u  v  w  x  y  z  {  |  }  ~     
 *  U+00A0      ¡  ¢  £  ¤  ¥  ¦  §     ©  ª  «  ¬     ®     
 *  U+00B0   °  ±  ²  ³     µ  ¶  ·     ¹  º  »  ¼  ½  ¾  ¿  
 *  U+00C0   À  Á  Â  Ã  Ä  Å  Æ  Ç  È  É  Ê  Ë  Ì  Í  Î  Ï  
 *  U+00D0   Ð  Ñ  Ò  Ó  Ô  Õ  Ö  ×  Ø  Ù  Ú  Û  Ü  Ý  Þ  ß  
 *  U+00E0   à  á  â  ã  ä  å  æ  ç  è  é  ê  ë  ì  í  î  ï  
 *  U+00F0   ð  ñ  ò  ó  ô  õ  ö  ÷  ø  ù  ú  û  ü  ý  þ  ÿ 
 *  U+0100   Ā  ā  Ă  ă  Ą  ą  Ć  ć  Ĉ  ĉ  Ċ  ċ  Č  č  Ď  ď
 *  ...
 *
 *  Depending on your system setup and font, not all of the Unicode
 *  characters may display properly.
 *
 *  Quirks: when printing certain Hebrew or Arabic characters, the
 *  table may print right-to-left instead of left-to-right.
 *
 *  For a description of Unicode terminology, see:
 *  http://docs.oracle.com/javase/tutorial/i18n/text/terminology.html
 *
 *  For the Character API, see:
 *  http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html
 *
 *  To see what each Unicode character should look like, see:
 *  http://www.fileformat.info/info/unicode/index.htm
 *  http://www.fileformat.info/info/unicode/char/05D0/index.htm
 *
 *
 ******************************************************************************/


public   class   UnicodeTest   {
     // number of Unicode characters to display per line
     private   static   final   int  CHARS_PER_LINE  =   16 ;

     // number of Unicode characters to display (basic multilingual plane)
     private   static   final   int  MAX_CHAR  =   65536 ;

     // do not instantiate
     private   UnicodeTest ()   {   }

     // Returns a string representation of the given codePoint, or a single
     // space if the codePoint should not be suppressed when printing.
     private   static   String  toString ( int  codePoint )   {
         if   ( ! Character . isDefined ( codePoint ))               return   " " ;
         if   ( Character . isISOControl ( codePoint ))             return   " " ;
         if   ( Character . isWhitespace ( codePoint ))             return   " " ;
      // if (Character.isSurrogate(codePoint)             return " ";   // Java 1.7+ only
         if   ( Character . isLowSurrogate (( char )  codePoint ))    return   " " ;     // Java 1.5+
         if   ( Character . isHighSurrogate (( char )  codePoint ))   return   " " ;     // Java 1.5+

         switch ( Character . getType ( codePoint ))   {
             case   Character . MODIFIER_SYMBOL :                return   " " ;
             case   Character . CONTROL :                        return   " " ;
             case   Character . MODIFIER_LETTER :                return   " " ;
             case   Character . NON_SPACING_MARK :               return   " " ;
             case   Character . FORMAT :                         return   " " ;
             case   Character . PRIVATE_USE :                    return   " " ;
             default :   return   new   String ( Character . toChars ( codePoint ));
         }
     }

    /**
     * Prints Unicode characters to standard output.
     *
     *  @param  args the command-line arguments
     */
     public   static   void  main ( String []  args )   {
         for   ( int  line  =   0 ;  line  <   2 * Character . MAX_VALUE  /  CHARS_PER_LINE ;  line ++ )   {
             StringBuilder  buffer  =   new   StringBuilder ();
             for   ( int  i  =   0 ;  i  <  CHARS_PER_LINE ;  i ++ )   {
                 int  codePoint  =  CHARS_PER_LINE * line  +  i ;
                buffer . append ( toString ( codePoint )   +   "  " );
             }
             String  output  =  buffer . toString ();
             if   ( ! output . trim (). equals ( "" ))   {
                 // U+202D is the Unicode override to force left-to-right direction
                 // but doesn't seem to work with Unix more
                 StdOut . printf ( "U+%04X   %s\n" ,   16 * line ,  output );
             }
         }
     }
}

BinaryIn.class

public final synchronized class BinaryIn {
    private static final int EOF = -1;
    private java.io.BufferedInputStream in;
    private int buffer;
    private int n;
    public void BinaryIn();
    public void BinaryIn(java.io.InputStream);
    public void BinaryIn(java.net.Socket);
    public void BinaryIn(java.net.URL);
    public void BinaryIn(String);
    private void fillBuffer();
    public boolean exists();
    public boolean isEmpty();
    public boolean readBoolean();
    public char readChar();
    public char readChar(int);
    public String readString();
    public short readShort();
    public int readInt();
    public int readInt(int);
    public long readLong();
    public double readDouble();
    public float readFloat();
    public byte readByte();
    public static void main(String[]);
}

BinaryOut.class

public final synchronized class BinaryOut {
    private java.io.BufferedOutputStream out;
    private int buffer;
    private int n;
    public void BinaryOut();
    public void BinaryOut(java.io.OutputStream);
    public void BinaryOut(String);
    public void BinaryOut(java.net.Socket);
    private void writeBit(boolean);
    private void writeByte(int);
    private void clearBuffer();
    public void flush();
    public void close();
    public void write(boolean);
    public void write(byte);
    public void write(int);
    public void write(int, int);
    public void write(double);
    public void write(long);
    public void write(float);
    public void write(short);
    public void write(char);
    public void write(char, int);
    public void write(String);
    public void write(String, int);
    public static void main(String[]);
    static void <clinit>();
}

BinaryStdIn.class

public final synchronized class BinaryStdIn {
    private static final int EOF = -1;
    private static java.io.BufferedInputStream in;
    private static int buffer;
    private static int n;
    private static boolean isInitialized;
    private void BinaryStdIn();
    private static void initialize();
    private static void fillBuffer();
    public static void close();
    public static boolean isEmpty();
    public static boolean readBoolean();
    public static char readChar();
    public static char readChar(int);
    public static String readString();
    public static short readShort();
    public static int readInt();
    public static int readInt(int);
    public static long readLong();
    public static double readDouble();
    public static float readFloat();
    public static byte readByte();
    public static void main(String[]);
}

BinaryStdOut.class

public final synchronized class BinaryStdOut {
    private static java.io.BufferedOutputStream out;
    private static int buffer;
    private static int n;
    private static boolean isInitialized;
    private void BinaryStdOut();
    private static void initialize();
    private static void writeBit(boolean);
    private static void writeByte(int);
    private static void clearBuffer();
    public static void flush();
    public static void close();
    public static void write(boolean);
    public static void write(byte);
    public static void write(int);
    public static void write(int, int);
    public static void write(double);
    public static void write(long);
    public static void write(float);
    public static void write(short);
    public static void write(char);
    public static void write(char, int);
    public static void write(String);
    public static void write(String, int);
    public static void main(String[]);
    static void <clinit>();
}

Draw.class

public final synchronized class Draw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
    public static final java.awt.Color BLACK;
    public static final java.awt.Color BLUE;
    public static final java.awt.Color CYAN;
    public static final java.awt.Color DARK_GRAY;
    public static final java.awt.Color GRAY;
    public static final java.awt.Color GREEN;
    public static final java.awt.Color LIGHT_GRAY;
    public static final java.awt.Color MAGENTA;
    public static final java.awt.Color ORANGE;
    public static final java.awt.Color PINK;
    public static final java.awt.Color RED;
    public static final java.awt.Color WHITE;
    public static final java.awt.Color YELLOW;
    public static final java.awt.Color BOOK_BLUE;
    public static final java.awt.Color BOOK_LIGHT_BLUE;
    public static final java.awt.Color BOOK_RED;
    public static final java.awt.Color PRINCETON_ORANGE;
    private static final java.awt.Color DEFAULT_PEN_COLOR;
    private static final java.awt.Color DEFAULT_CLEAR_COLOR;
    private static final double BORDER = 0.0;
    private static final double DEFAULT_XMIN = 0.0;
    private static final double DEFAULT_XMAX = 1.0;
    private static final double DEFAULT_YMIN = 0.0;
    private static final double DEFAULT_YMAX = 1.0;
    private static final int DEFAULT_SIZE = 512;
    private static final double DEFAULT_PEN_RADIUS = 0.002;
    private static final java.awt.Font DEFAULT_FONT;
    private java.awt.Color penColor;
    private int width;
    private int height;
    private double penRadius;
    private boolean defer;
    private double xmin;
    private double ymin;
    private double xmax;
    private double ymax;
    private String name;
    private final Object mouseLock;
    private final Object keyLock;
    private java.awt.Font font;
    private javax.swing.JLabel draw;
    private java.awt.image.BufferedImage offscreenImage;
    private java.awt.image.BufferedImage onscreenImage;
    private java.awt.Graphics2D offscreen;
    private java.awt.Graphics2D onscreen;
    private javax.swing.JFrame frame;
    private boolean isMousePressed;
    private double mouseX;
    private double mouseY;
    private final java.util.LinkedList keysTyped;
    private final java.util.TreeSet keysDown;
    private final java.util.ArrayList listeners;
    public void Draw(String);
    public void Draw();
    private void init();
    public void setLocationOnScreen(int, int);
    public void setDefaultCloseOperation(int);
    public void setCanvasSize(int, int);
    private javax.swing.JMenuBar createMenuBar();
    private static void validate(double, String);
    private static void validateNonnegative(double, String);
    private static void validateNotNull(Object, String);
    public void setXscale();
    public void setYscale();
    public void setXscale(double, double);
    public void setYscale(double, double);
    private double scaleX(double);
    private double scaleY(double);
    private double factorX(double);
    private double factorY(double);
    private double userX(double);
    private double userY(double);
    public void clear();
    public void clear(java.awt.Color);
    public double getPenRadius();
    public void setPenRadius();
    public void setPenRadius(double);
    public java.awt.Color getPenColor();
    public void setPenColor();
    public void setPenColor(java.awt.Color);
    public void setPenColor(int, int, int);
    public void xorOn();
    public void xorOff();
    public javax.swing.JLabel getJLabel();
    public java.awt.Font getFont();
    public void setFont();
    public void setFont(java.awt.Font);
    public void line(double, double, double, double);
    private void pixel(double, double);
    public void point(double, double);
    public void circle(double, double, double);
    public void filledCircle(double, double, double);
    public void ellipse(double, double, double, double);
    public void filledEllipse(double, double, double, double);
    public void arc(double, double, double, double, double);
    public void square(double, double, double);
    public void filledSquare(double, double, double);
    public void rectangle(double, double, double, double);
    public void filledRectangle(double, double, double, double);
    public void polygon(double[], double[]);
    public void filledPolygon(double[], double[]);
    private static java.awt.Image getImage(String);
    public void picture(double, double, String);
    public void picture(double, double, String, double);
    public void picture(double, double, String, double, double);
    public void picture(double, double, String, double, double, double);
    public void text(double, double, String);
    public void text(double, double, String, double);
    public void textLeft(double, double, String);
    public void textRight(double, double, String);
    public void show(int);
    public void pause(int);
    public void show();
    private void draw();
    public void enableDoubleBuffering();
    public void disableDoubleBuffering();
    public void save(String);
    public void actionPerformed(java.awt.event.ActionEvent);
    public void addListener(DrawListener);
    public boolean isMousePressed();
    public boolean mousePressed();
    public double mouseX();
    public double mouseY();
    public void mouseEntered(java.awt.event.MouseEvent);
    public void mouseExited(java.awt.event.MouseEvent);
    public void mousePressed(java.awt.event.MouseEvent);
    public void mouseReleased(java.awt.event.MouseEvent);
    public void mouseClicked(java.awt.event.MouseEvent);
    public void mouseDragged(java.awt.event.MouseEvent);
    public void mouseMoved(java.awt.event.MouseEvent);
    public boolean hasNextKeyTyped();
    public char nextKeyTyped();
    public boolean isKeyPressed(int);
    public void keyTyped(java.awt.event.KeyEvent);
    public void keyPressed(java.awt.event.KeyEvent);
    public void keyReleased(java.awt.event.KeyEvent);
    public static void main(String[]);
    static void <clinit>();
}

DrawListener.class

public abstract interface DrawListener {
    public abstract void mousePressed(double, double);
    public abstract void mouseDragged(double, double);
    public abstract void mouseReleased(double, double);
    public abstract void mouseClicked(double, double);
    public abstract void keyTyped(char);
    public abstract void keyPressed(int);
    public abstract void keyReleased(int);
}

Draw$RetinaImageIcon.class

synchronized class Draw$RetinaImageIcon extends javax.swing.ImageIcon {
    public void Draw$RetinaImageIcon(java.awt.Image);
    public int getIconWidth();
    public int getIconHeight();
    public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}

GrayscalePicture.class

public final synchronized class GrayscalePicture implements java.awt.event.ActionListener {
    private java.awt.image.BufferedImage image;
    private javax.swing.JFrame frame;
    private String filename;
    private boolean isOriginUpperLeft;
    private final int width;
    private final int height;
    public void GrayscalePicture(int, int);
    public void GrayscalePicture(GrayscalePicture);
    public void GrayscalePicture(String);
    private static java.awt.Color toGray(java.awt.Color);
    public javax.swing.JLabel getJLabel();
    public void setOriginUpperLeft();
    public void setOriginLowerLeft();
    public void show();
    public int height();
    public int width();
    private void validateRowIndex(int);
    private void validateColumnIndex(int);
    private void validateGrayscaleValue(int);
    public java.awt.Color get(int, int);
    public int getGrayscale(int, int);
    public void set(int, int, java.awt.Color);
    public void setGrayscale(int, int, int);
    public boolean equals(Object);
    public String toString();
    public int hashCode();
    public void save(String);
    public void save(java.io.File);
    public void actionPerformed(java.awt.event.ActionEvent);
    public static void main(String[]);
}

In.class

public final synchronized class In {
    private static final String CHARSET_NAME = UTF-8;
    private static final java.util.Locale LOCALE;
    private static final java.util.regex.Pattern WHITESPACE_PATTERN;
    private static final java.util.regex.Pattern EMPTY_PATTERN;
    private static final java.util.regex.Pattern EVERYTHING_PATTERN;
    private java.util.Scanner scanner;
    public void In();
    public void In(java.net.Socket);
    public void In(java.net.URL);
    public void In(java.io.File);
    public void In(String);
    public void In(java.util.Scanner);
    public boolean exists();
    public boolean isEmpty();
    public boolean hasNextLine();
    public boolean hasNextChar();
    public String readLine();
    public char readChar();
    public String readAll();
    public String readString();
    public int readInt();
    public double readDouble();
    public float readFloat();
    public long readLong();
    public short readShort();
    public byte readByte();
    public boolean readBoolean();
    public String[] readAllStrings();
    public String[] readAllLines();
    public int[] readAllInts();
    public long[] readAllLongs();
    public double[] readAllDoubles();
    public void close();
    public static int[] readInts(String);
    public static double[] readDoubles(String);
    public static String[] readStrings(String);
    public static int[] readInts();
    public static double[] readDoubles();
    public static String[] readStrings();
    public static void main(String[]);
    static void <clinit>();
}

Out.class

public synchronized class Out {
    private static final String CHARSET_NAME = UTF-8;
    private static final java.util.Locale LOCALE;
    private java.io.PrintWriter out;
    public void Out(java.io.OutputStream);
    public void Out();
    public void Out(java.net.Socket);
    public void Out(String);
    public void close();
    public void println();
    public void println(Object);
    public void println(boolean);
    public void println(char);
    public void println(double);
    public void println(float);
    public void println(int);
    public void println(long);
    public void println(byte);
    public void print();
    public void print(Object);
    public void print(boolean);
    public void print(char);
    public void print(double);
    public void print(float);
    public void print(int);
    public void print(long);
    public void print(byte);
    public transient void printf(String, Object[]);
    public transient void printf(java.util.Locale, String, Object[]);
    public static void main(String[]);
    static void <clinit>();
}

Picture.class

public final synchronized class Picture implements java.awt.event.ActionListener {
    private java.awt.image.BufferedImage image;
    private javax.swing.JFrame frame;
    private String filename;
    private boolean isOriginUpperLeft;
    private final int width;
    private final int height;
    public void Picture(int, int);
    public void Picture(Picture);
    public void Picture(String);
    public void Picture(java.io.File);
    public javax.swing.JLabel getJLabel();
    public void setOriginUpperLeft();
    public void setOriginLowerLeft();
    public void show();
    public int height();
    public int width();
    private void validateRowIndex(int);
    private void validateColumnIndex(int);
    public java.awt.Color get(int, int);
    public int getRGB(int, int);
    public void set(int, int, java.awt.Color);
    public void setRGB(int, int, int);
    public boolean equals(Object);
    public String toString();
    public int hashCode();
    public void save(String);
    public void save(java.io.File);
    public void actionPerformed(java.awt.event.ActionEvent);
    public static void main(String[]);
}

PlayMusic$1.class

final synchronized class PlayMusic$1 implements Runnable {
    void PlayMusic$1(String);
    public void run();
}

PlayMusic.class

public synchronized class PlayMusic {
    public void PlayMusic();
    private static void playApplet(String);
    public static synchronized void play(String);
    private static void stream(String);
    public static void main(String[]);
}

StdArrayIO.class

public synchronized class StdArrayIO {
    private void StdArrayIO();
    public static double[] readDouble1D();
    public static void print(double[]);
    public static double[][] readDouble2D();
    public static void print(double[][]);
    public static int[] readInt1D();
    public static void print(int[]);
    public static int[][] readInt2D();
    public static void print(int[][]);
    public static boolean[] readBoolean1D();
    public static void print(boolean[]);
    public static boolean[][] readBoolean2D();
    public static void print(boolean[][]);
    public static void main(String[]);
}

StdAudio$1.class

final synchronized class StdAudio$1 implements Runnable {
    void StdAudio$1(String);
    public void run();
}

StdAudio$2.class

final synchronized class StdAudio$2 implements Runnable {
    void StdAudio$2();
    public void run();
}

StdAudio.class

public final synchronized class StdAudio {
    public static final int SAMPLE_RATE = 44100;
    private static final int BYTES_PER_SAMPLE = 2;
    private static final int BITS_PER_SAMPLE = 16;
    private static final double MAX_16_BIT = 32768.0;
    private static final int SAMPLE_BUFFER_SIZE = 4096;
    private static final int MONO = 1;
    private static final int STEREO = 2;
    private static final boolean LITTLE_ENDIAN = 0;
    private static final boolean BIG_ENDIAN = 1;
    private static final boolean SIGNED = 1;
    private static final boolean UNSIGNED = 0;
    private static javax.sound.sampled.SourceDataLine line;
    private static byte[] buffer;
    private static int bufferSize;
    private void StdAudio();
    private static void init();
    private static javax.sound.sampled.AudioInputStream getAudioInputStreamFromFile(String);
    public static void close();
    public static void play(double);
    public static void play(double[]);
    public static double[] read(String);
    public static void save(String, double[]);
    public static synchronized void play(String);
    private static void stream(javax.sound.sampled.AudioInputStream);
    public static synchronized void loop(String);
    private static double[] note(double, double, double);
    public static void main(String[]);
    static void <clinit>();
}

StdDraw.class

public final synchronized class StdDraw implements java.awt.event.ActionListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener, java.awt.event.KeyListener {
    public static final java.awt.Color BLACK;
    public static final java.awt.Color BLUE;
    public static final java.awt.Color CYAN;
    public static final java.awt.Color DARK_GRAY;
    public static final java.awt.Color GRAY;
    public static final java.awt.Color GREEN;
    public static final java.awt.Color LIGHT_GRAY;
    public static final java.awt.Color MAGENTA;
    public static final java.awt.Color ORANGE;
    public static final java.awt.Color PINK;
    public static final java.awt.Color RED;
    public static final java.awt.Color WHITE;
    public static final java.awt.Color YELLOW;
    public static final java.awt.Color BOOK_BLUE;
    public static final java.awt.Color BOOK_LIGHT_BLUE;
    public static final java.awt.Color BOOK_RED;
    public static final java.awt.Color PRINCETON_ORANGE;
    private static final java.awt.Color DEFAULT_PEN_COLOR;
    private static final java.awt.Color DEFAULT_CLEAR_COLOR;
    private static java.awt.Color penColor;
    private static final int DEFAULT_SIZE = 512;
    private static int width;
    private static int height;
    private static final double DEFAULT_PEN_RADIUS = 0.002;
    private static double penRadius;
    private static boolean defer;
    private static final double BORDER = 0.0;
    private static final double DEFAULT_XMIN = 0.0;
    private static final double DEFAULT_XMAX = 1.0;
    private static final double DEFAULT_YMIN = 0.0;
    private static final double DEFAULT_YMAX = 1.0;
    private static double xmin;
    private static double ymin;
    private static double xmax;
    private static double ymax;
    private static Object mouseLock;
    private static Object keyLock;
    private static final java.awt.Font DEFAULT_FONT;
    private static java.awt.Font font;
    private static java.awt.image.BufferedImage offscreenImage;
    private static java.awt.image.BufferedImage onscreenImage;
    private static java.awt.Graphics2D offscreen;
    private static java.awt.Graphics2D onscreen;
    private static StdDraw std;
    private static javax.swing.JFrame frame;
    private static boolean isMousePressed;
    private static double mouseX;
    private static double mouseY;
    private static java.util.LinkedList keysTyped;
    private static java.util.TreeSet keysDown;
    private void StdDraw();
    public static void setCanvasSize();
    public static void setCanvasSize(int, int);
    private static void init();
    private static javax.swing.JMenuBar createMenuBar();
    private static void validate(double, String);
    private static void validateNonnegative(double, String);
    private static void validateNotNull(Object, String);
    public static void setXscale();
    public static void setYscale();
    public static void setScale();
    public static void setXscale(double, double);
    public static void setYscale(double, double);
    public static void setScale(double, double);
    private static double scaleX(double);
    private static double scaleY(double);
    private static double factorX(double);
    private static double factorY(double);
    private static double userX(double);
    private static double userY(double);
    public static void clear();
    public static void clear(java.awt.Color);
    public static double getPenRadius();
    public static void setPenRadius();
    public static void setPenRadius(double);
    public static java.awt.Color getPenColor();
    public static void setPenColor();
    public static void setPenColor(java.awt.Color);
    public static void setPenColor(int, int, int);
    public static java.awt.Font getFont();
    public static void setFont();
    public static void setFont(java.awt.Font);
    public static void line(double, double, double, double);
    private static void pixel(double, double);
    public static void point(double, double);
    public static void circle(double, double, double);
    public static void filledCircle(double, double, double);
    public static void ellipse(double, double, double, double);
    public static void filledEllipse(double, double, double, double);
    public static void arc(double, double, double, double, double);
    public static void square(double, double, double);
    public static void filledSquare(double, double, double);
    public static void rectangle(double, double, double, double);
    public static void filledRectangle(double, double, double, double);
    public static void polygon(double[], double[]);
    public static void filledPolygon(double[], double[]);
    private static java.awt.Image getImage(String);
    public static void picture(double, double, String);
    public static void picture(double, double, String, double);
    public static void picture(double, double, String, double, double);
    public static void picture(double, double, String, double, double, double);
    public static void text(double, double, String);
    public static void text(double, double, String, double);
    public static void textLeft(double, double, String);
    public static void textRight(double, double, String);
    public static void show(int);
    public static void pause(int);
    public static void show();
    private static void draw();
    public static void enableDoubleBuffering();
    public static void disableDoubleBuffering();
    public static void save(String);
    public void actionPerformed(java.awt.event.ActionEvent);
    public static boolean isMousePressed();
    public static boolean mousePressed();
    public static double mouseX();
    public static double mouseY();
    public void mouseClicked(java.awt.event.MouseEvent);
    public void mouseEntered(java.awt.event.MouseEvent);
    public void mouseExited(java.awt.event.MouseEvent);
    public void mousePressed(java.awt.event.MouseEvent);
    public void mouseReleased(java.awt.event.MouseEvent);
    public void mouseDragged(java.awt.event.MouseEvent);
    public void mouseMoved(java.awt.event.MouseEvent);
    public static boolean hasNextKeyTyped();
    public static char nextKeyTyped();
    public static boolean isKeyPressed(int);
    public void keyTyped(java.awt.event.KeyEvent);
    public void keyPressed(java.awt.event.KeyEvent);
    public void keyReleased(java.awt.event.KeyEvent);
    public static void main(String[]);
    static void <clinit>();
}

StdDraw$RetinaImageIcon.class

synchronized class StdDraw$RetinaImageIcon extends javax.swing.ImageIcon {
    public void StdDraw$RetinaImageIcon(java.awt.Image);
    public int getIconWidth();
    public int getIconHeight();
    public synchronized void paintIcon(java.awt.Component, java.awt.Graphics, int, int);
}

StdIn.class

public final synchronized class StdIn {
    private static final String CHARSET_NAME = UTF-8;
    private static final java.util.Locale LOCALE;
    private static final java.util.regex.Pattern WHITESPACE_PATTERN;
    private static final java.util.regex.Pattern EMPTY_PATTERN;
    private static final java.util.regex.Pattern EVERYTHING_PATTERN;
    private static java.util.Scanner scanner;
    private void StdIn();
    public static boolean isEmpty();
    public static boolean hasNextLine();
    public static boolean hasNextChar();
    public static String readLine();
    public static char readChar();
    public static String readAll();
    public static String readString();
    public static int readInt();
    public static double readDouble();
    public static float readFloat();
    public static long readLong();
    public static short readShort();
    public static byte readByte();
    public static boolean readBoolean();
    public static String[] readAllStrings();
    public static String[] readAllLines();
    public static int[] readAllInts();
    public static long[] readAllLongs();
    public static double[] readAllDoubles();
    private static void resync();
    private static void setScanner(java.util.Scanner);
    public static int[] readInts();
    public static double[] readDoubles();
    public static String[] readStrings();
    public static void main(String[]);
    static void <clinit>();
}

StdInTest.class

public synchronized class StdInTest {
    private static boolean testStdIn;
    private static reflect.Method resyncMethod;
    private static int testCount;
    public void StdInTest();
    public static Object escape(Object);
    public static boolean canResync();
    public static void test(String, Object[][]);
    public static void test(String, Object[][], boolean);
    public static void main(String[]);
    static void <clinit>();
}

StdOut.class

public final synchronized class StdOut {
    private static final String CHARSET_NAME = UTF-8;
    private static final java.util.Locale LOCALE;
    private static java.io.PrintWriter out;
    private void StdOut();
    public static void println();
    public static void println(Object);
    public static void println(boolean);
    public static void println(char);
    public static void println(double);
    public static void println(float);
    public static void println(int);
    public static void println(long);
    public static void println(short);
    public static void println(byte);
    public static void print();
    public static void print(Object);
    public static void print(boolean);
    public static void print(char);
    public static void print(double);
    public static void print(float);
    public static void print(int);
    public static void print(long);
    public static void print(short);
    public static void print(byte);
    public static transient void printf(String, Object[]);
    public static transient void printf(java.util.Locale, String, Object[]);
    public static void main(String[]);
    static void <clinit>();
}

StdRandom.class

public final synchronized class StdRandom {
    private static java.util.Random random;
    private static long seed;
    private void StdRandom();
    public static void setSeed(long);
    public static long getSeed();
    public static double uniform();
    public static int uniform(int);
    public static long uniform(long);
    public static double random();
    public static int uniform(int, int);
    public static double uniform(double, double);
    public static boolean bernoulli(double);
    public static boolean bernoulli();
    public static double gaussian();
    public static double gaussian(double, double);
    public static int geometric(double);
    public static int poisson(double);
    public static double pareto();
    public static double pareto(double);
    public static double cauchy();
    public static int discrete(double[]);
    public static int discrete(int[]);
    public static double exp(double);
    public static void shuffle(Object[]);
    public static void shuffle(double[]);
    public static void shuffle(int[]);
    public static void shuffle(char[]);
    public static void shuffle(Object[], int, int);
    public static void shuffle(double[], int, int);
    public static void shuffle(int[], int, int);
    public static int[] permutation(int);
    public static int[] permutation(int, int);
    private static void validateNotNull(Object);
    private static void validateSubarrayIndices(int, int, int);
    public static void main(String[]);
    static void <clinit>();
}

StdStats.class

public final synchronized class StdStats {
    private void StdStats();
    public static double max(double[]);
    public static double max(double[], int, int);
    public static int max(int[]);
    public static double min(double[]);
    public static double min(double[], int, int);
    public static int min(int[]);
    public static double mean(double[]);
    public static double mean(double[], int, int);
    public static double mean(int[]);
    public static double var(double[]);
    public static double var(double[], int, int);
    public static double var(int[]);
    public static double varp(double[]);
    public static double varp(double[], int, int);
    public static double stddev(double[]);
    public static double stddev(int[]);
    public static double stddev(double[], int, int);
    public static double stddevp(double[]);
    public static double stddevp(double[], int, int);
    private static double sum(double[]);
    private static double sum(double[], int, int);
    private static int sum(int[]);
    public static void plotPoints(double[]);
    public static void plotLines(double[]);
    public static void plotBars(double[]);
    private static void validateNotNull(Object);
    private static void validateSubarrayIndices(int, int, int);
    public static void main(String[]);
}

Stopwatch.class

public synchronized class Stopwatch {
    private final long start;
    public void Stopwatch();
    public double elapsedTime();
    public static void main(String[]);
}

StopwatchCPU.class

public synchronized class StopwatchCPU {
    private static final double NANOSECONDS_PER_SECOND = 1.0E9;
    private final management.ThreadMXBean threadTimer;
    private final long start;
    public void StopwatchCPU();
    public double elapsedTime();
}

TestIntroCS.class

public synchronized class TestIntroCS {
    public void TestIntroCS();
    public static void main(String[]);
}

UnicodeTest.class

public synchronized class UnicodeTest {
    private static final int CHARS_PER_LINE = 16;
    private static final int MAX_CHAR = 65536;
    private void UnicodeTest();
    private static String toString(int);
    public static void main(String[]);
}

InTest.txt

This is a test file. Here is line 2.

mandrill.jpg