CS 211 Homework 2 (Regular Stream) Solution

 

Comments:

               

                This was a very difficult assignment.  To keep grading consistent, we ran each program with several inputs:

 

1.                 

2.                3

3.                g x y +

4.                3 x y + 1

5.                3 x +

6.                3 3b

7.                3 x 1.5 + y 2 + +

8.                3 x 1.5 – y 2 - -

9.                3 x 1.5 “*” y 2 “*” “*”

10.            3 x 1.5 / y 2 / /

11.                 3 x 2.5 + 11 x y - / “*”

 

In case 1, there is simply no input. You should print out appropriate error messages for cases 1 to 6, and you should print out the correct matrix for cases 7 to 11. Each case is worth 5 points.

 

The rest of the points were spread into parts where the graders try their best to give you points wherever possible while being consistent with what was stated on the homework sheet.

 

Solution:

 

import java.util.*;

 

/**

 * This interface handles functions that take an unspecified number of arguments

 */

interface Function {

 

  /**

   * Returns the number of arguments that this Function takes.

   * @return number of arguments this function uses

   */

  public int argCount();

 

  /**

   * Evaluate the Function.

   * @param args the arguments to the function

   * @return the value of the function evaluated on the given arguments

   * @exception IllegalArgumentException is thrown for wrong number of arguments

   */

  public double evaluate (double[] args);

}

 

/**

 * This interface handles functions that take exactly two arguments.

 */

interface Function2 extends Function {

 

  /**

   * Evaluate the function.

   * @param x the first argument to the function

   * @param y the second argument to the function

   * @return the value of the function evaluated on x and y

   */

  public double evaluate (double x, double y);

}

 

/**

 * This class implements a function in x and y defined by a String array.

 */

class StringFunction implements Function2 {

 

      private Object[] commands;

 

      /**

       * Create a function defined by a String array.

       * @param args the String array; a postfix function in x and y

       */

      public StringFunction (String[] args) {

            commands = new Object[args.length];

            for (int i=0; i<args.length; i++) {

                  /**

                   * same as: if (args[i].equals("+") || args[i].equals("-")

                   *           || args[i].equals("*") || args[i].equals("/")

                   *           || args[i].equals("x") || args[i].equals("y"))

                   *          commands[i] = args[i];       

                   */

                  if (args[i].length() == 1)

                        switch (args[i].charAt(0)) {

                        case '+':

                        case '-':

                        case '*':

                        case '/':

                        case 'x':

                        case 'y': commands[i] = args[i]; continue;

                        }

                  try {

                        commands[i] = Double.valueOf(args[i]);

                  }

                  catch (NumberFormatException e) {

                        System.out.println ("\"" + args[i] + "\" is not in the appropriate format.");

                        System.exit(-1);

                  }

            }

      }

 

    /**

     * Evaluate the function.

     * @param x the first argument to the function

     * @param y the second argument to the function

     * @return the value of the function evaluated on x and y

     */

      public double evaluate (double x, double y) {

            Stack argStack = new Stack();

            try {

                  for (int i=0; i<commands.length; i++) {

                  if (commands[i].equals("x"))        // check for x

                        argStack.push(new Double(x));

                  else if (commands[i].equals("y"))   // check for y

                        argStack.push(new Double(y));

                  else if (commands[i].equals("+")) { // check for Plus

                        double rhs=((Double)argStack.pop()).doubleValue();

                        double lhs=((Double)argStack.pop()).doubleValue();

                        argStack.push(new Double(lhs + rhs));

                  }

                  else if (commands[i].equals("-")) { // check for Minus

                        double rhs=((Double)argStack.pop()).doubleValue();

                        double lhs=((Double)argStack.pop()).doubleValue();

                        argStack.push(new Double(lhs - rhs));

                  }

                  else if (commands[i].equals("*")) { // check for Multiply

                        double rhs=((Double)argStack.pop()).doubleValue();

                        double lhs=((Double)argStack.pop()).doubleValue();

                        argStack.push(new Double(lhs * rhs));

                  }

                  else if (commands[i].equals("/")) { // check for Divide

                        double rhs=((Double)argStack.pop()).doubleValue();

                        double lhs=((Double)argStack.pop()).doubleValue();

                        argStack.push(new Double(lhs / rhs));

                  }

                  else argStack.push(commands[i]); // otherwise it's a number

                  }

            }

            catch (EmptyStackException e) {

                  System.out.println ("Error: Ran out of values to pop from stack!");

                  System.exit(-1);

            }

            if (argStack.size() > 1) {

                  System.out.println ("Error: Evaluation completed but stack contains more than just the result.");

                  System.exit(-1);

            }

            return ((Double)argStack.pop()).doubleValue();

      }

 

    public int argCount() {return 2;}

     

      public double evaluate (double[] args) {

            if (args.length >= 2)

                  return evaluate (args[0], args[1]);

            else {

                  System.out.println ("not enough arguments to evaluate");

                  System.exit(-1);

            }

      }

}

 

/**

 * This class takes an array of arguments as Strings from command line and parses

 * them to create a matrix populated with functions on the indices of the matrix.

 */

public class Evaluator {

 

      public static void main (String[] args) {

 

              /**

               * Check parameters

               */

              if (args.length == 0) {

                    System.out.println ("Error: Please supply arguments.");

                    System.exit(-1);

              }

              if (args.length == 1) {

                    System.out.println ("Error: Please supply the post-fix function.");

                    System.exit(-1);

              }

             

              /**

               *  Extract the size of the matrix

               */

              int size = 0;

              try {

                    size = Integer.parseInt(args[0]);

              }

              catch (NumberFormatException e) {

                    System.out.println ("First command line input must describe the size of the matrix.");

                    System.exit(-1);

              }

 

              /**

               * Remove the size from the actual commands

               */

              String[] commands = new String [args.length - 1];

              for (int i=1; i<args.length; i++)

                    commands[i - 1] = args[i];

 

              /**

               * Create a StringFunction based on the arguments and evaluate it

               * to fill in the matrix, and then print out the matrix.

               * Note: It is optional whether students choose to store the matrix before printing.

               */

              StringFunction sf = new StringFunction (commands);

              for (int y=0; y<size; y++) {

                    for (int x=0; x<size; x++)

                          System.out.print (sf.evaluate(x,y) + " ");

                    System.out.println();

              }

      }

}