FRQ 2019

Question #1

a.

/**
     * Returns true if year is a leap year and false otherwise 
     * 
     * @param year
     * @return
     */
    private static boolean isLeapYear(int year)
    {
        if ((year % 4 == 0) || // must occur every 4th year
                (year % 100 == 0) || // must be divisible by 100
                (year % 400 == 0)) // must be divisible by 400
        {
            return true;
        }
        else return false;   
    }
/**
     * Returns number of leap years between year1 and year2,
     * inclusive 
     * 
     * 0 <= year1 <= year2
     * 
     * @param year1
     * @param year2
     * @return
     */
    public static int numberofLeapYears(int year1, int year2)
    {
        int leapYear = 0;
        
        for(int loop = year1; loop <= year2; loop++)
        {
            if ((loop % 4 == 0) || // must occur every 4th year
                (loop % 100 == 0) || // must be divisible by 100
                (loop % 400 == 0)) // must be divisible by 400
            {
                leapYear++; // increases number of leap years
            }
        }
        return leapYear;
    }
/**
 * main 
 * 
 */
final int YEAR = 2022;
        final int YEAR_1 = 2000;
        final int YEAR_2 = 2024;

        // PART A
        System.out.printf("PART A:\n");
        boolean isLeapYear = isLeapYear(YEAR);
        System.out.printf("%d: %b\n",YEAR, isLeapYear);
        
        int numLeapYears = numberofLeapYears(YEAR_1, YEAR_2);
        System.out.printf("There are %d leap years between %d and %d\n\n",
                numLeapYears, YEAR_1, YEAR_2);
PART A:
2022: false
There are 7 leap years between 2000 and 2024

java.io.PrintStream@2cc5d8cd

b.

/**
 * Returns the value representing the day of the week for
 * the first day of year, where 0 denotes Sunday, 1 denotes
 * Monday, ..., and 6 denotes Saturday 
 * 
 * @param month
 * @param day
 * @param year
 * @return
 */
private static int firstDayOfYear(int year)
{
    return 1;
}
/**
 * Returns n, where month, day, and year specify the nth
 * day of the year. Returns 1 for January 1 (Monday = 1,
 * day = 1) of any year 
 * 
 * @param month
 * @param day
 * @param year
 * @return
 */
private static int dayOfYear(int month, int day, int year)
{
    return 1;
}
/**
 * Returns the value representing the day of the week for
 * the given date, (month, day, year) where 0 denotes Sunday,
 * 1 denotes Monday, ..., and 6 denotes Saturday
 * 
 * @param the given month
 * @param the given day
 * @param the given year
 * @return dayOfWeek
 */
public static int dayofWeek(int month, int day, int year)
{
    // assuming that firstDayOfYear() is implemented
    int firstDay = firstDayOfYear(year);
    // assuming that dayOfYear() is implemented
    int numDays = dayOfYear(month, day, year);
    
    // subtract 1 so days of year start at 0
    int addDays = (firstDay + numDays) - 1;
    
    // 7 represents the number of days in a week
    int dayOfWeek = addDays % 7;
    
    return dayOfWeek;
}
/**
 * main 
 * 
 * @param Args
 */

// array of week
final String[] DAYS = {"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"};

final int THE_MONTH = 11;
final int THE_DAY = 14;
final int THE_YEAR = 2022;

// PART B
System.out.printf("PART B:\n");
int day = dayofWeek(THE_MONTH, THE_DAY, THE_YEAR);
System.out.printf("%d/%d/%d is on a %s\n", THE_MONTH, THE_DAY, THE_YEAR, DAYS[day]);
PART B:
11/14/2022 is on a Monday
java.io.PrintStream@2c3314aa

Question #2

/**
 * StepTracker.java
 *
 * FRQ 2019 #2
 *
 * @author Natalie Beckwith
 * @version 1
 */

/**
 * Main class for StepTracker.java
 *
 */
public class StepTracker
{

    private int _stepsToBeActive;
    private int _activeDays;
    private int _steps;
    private int _daysTracked;
    private int _stepsToday;

    public StepTracker(int stepsToBeActive)
    {
        stepsToBeActive = _stepsToBeActive;
        _activeDays = 0;
        _steps = 0;
        _daysTracked = 0;
        _stepsToday = 0;
    }

    /**
     * number of active days
     * 
     * @return the number of active days
     */
    public int activeDays()
    {
        _daysTracked++;

        // days with at least 10,000 steps are an active day
        if (_stepsToday >= 10000)
        {
            _activeDays++;

            return _activeDays;
        }
        return _activeDays;
    }

    /**
     * takes the average steps by dividing the number of steps taken by the number of
     * days tracked
     * 
     * @return the average number of steps per day
     */
    public double averageSteps()
    {
        if (_daysTracked == 0)
        {
            return 0.0;
        }

        // number of steps divided by days tracked
        return (double) _steps / (double) _daysTracked;
    }

    /**
     * accumulates information about steps, in readings taken once per day
     * 
     * @param steps
     */
    public int addDailySteps(int steps)
    {
        _stepsToday = steps;

        _steps += _stepsToday;

        return _steps;
    }

    /**
     * prints the total number of steps
     * 
     * @param steps
     */
    public static void printSteps(int steps)
    {
        System.out.printf("Number of steps: %d\n", steps);
    }

    /**
     * prints the number of active days
     * 
     * @param days
     */
    public static void printActiveDays(int days)
    {
        System.out.printf("Number of active days: %d\n", days);
    }

    /**
     * print the average number of steps
     * 
     * @param average
     */
    public static void printAverage(double average)
    {
        System.out.printf("Average number of steps: %.1f\n\n", average);
    }

    /**
     * main
     * 
     * @param Args
     */
    public static void main(String[] Args)
    {
        // days with at least 10,000 steps are considered
        // active, days must be positive
        StepTracker tr = new StepTracker(10000);

        int numSteps;
        int numActiveDays;
        double numAverageSteps;

        numSteps = tr.addDailySteps(9000);
        numActiveDays = tr.activeDays();
        numAverageSteps = tr.averageSteps();

        printSteps(numSteps);
        printActiveDays(numActiveDays);
        printAverage(numAverageSteps);

        numSteps = tr.addDailySteps(5000);
        numActiveDays = tr.activeDays();
        numAverageSteps = tr.averageSteps();

        printSteps(numSteps);
        printActiveDays(numActiveDays);
        printAverage(numAverageSteps);

        numSteps = tr.addDailySteps(13000);
        numActiveDays = tr.activeDays();
        numAverageSteps = tr.averageSteps();

        printSteps(numSteps);
        printActiveDays(numActiveDays);
        printAverage(numAverageSteps);

        numSteps = tr.addDailySteps(23000);
        numActiveDays = tr.activeDays();
        numAverageSteps = tr.averageSteps();

        printSteps(numSteps);
        printActiveDays(numActiveDays);
        printAverage(numAverageSteps);

        numSteps = tr.addDailySteps(1111);
        numActiveDays = tr.activeDays();
        numAverageSteps = tr.averageSteps();

        printSteps(numSteps);
        printActiveDays(numActiveDays);
        printAverage(numAverageSteps);
    }
}
StepTracker.main(null);
Number of steps: 9000
Number of active days: 0
Average number of steps: 9000.0

Number of steps: 14000
Number of active days: 0
Average number of steps: 7000.0

Number of steps: 27000
Number of active days: 1
Average number of steps: 9000.0

Number of steps: 50000
Number of active days: 2
Average number of steps: 12500.0

Number of steps: 51111
Number of active days: 2
Average number of steps: 10222.2

Question #3

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

/* In mathematics,
    an expression or mathematical expression is a finite combination of symbols that is well-formed
    according to rules that depend on the context.
   In computers,
    expression can be hard to calculate with precedence rules and user input errors
    to handle computer math we often convert strings into reverse polish notation
    to handle errors we perform try / catch or set default conditions to trap errors
     */
public class Calculator
{
    // Key instance variables
    private final String expression;
    private ArrayList<String> tokens;
    private ArrayList<String> reverse_polish;
    private Double result = 0.0;

    // Helper definition for supported operators
    private final Map<String, Integer> OPERATORS = new HashMap<>();
    {
        // Map<"token", precedence>
        OPERATORS.put("*", 3);
        OPERATORS.put("/", 3);
        OPERATORS.put("%", 3);
        OPERATORS.put("+", 4);
        OPERATORS.put("-", 4);
        OPERATORS.put("^", 4);
        OPERATORS.put("SQRT", 4);
    }
    private final Map<Character, Integer> NUMBERS = new HashMap<>();
    {
        // Map<"token", precedence>
        NUMBERS.put('0', 3);
        NUMBERS.put('1', 3);
        NUMBERS.put('2', 3);
        NUMBERS.put('3', 4);
        NUMBERS.put('4', 4);
        NUMBERS.put('5', 4);
        NUMBERS.put('6', 4);
        NUMBERS.put('7', 4);
        NUMBERS.put('8', 4);
        NUMBERS.put('9', 4);
        NUMBERS.put('.', 4);
    }
    

    // Helper definition for supported operators
    private final Map<String, Integer> SEPARATORS = new HashMap<>();
    {
        // Map<"separator", not_used>
        SEPARATORS.put(" ", 0);
        SEPARATORS.put("(", 0);
        SEPARATORS.put(")", 0);
    }

    // Create a 1 argument constructor expecting a mathematical expression
    public Calculator(String expression) throws Exception
    {
        // original input
        this.expression = expression;

        // parse expression into terms
        this.termTokenizer();

        // place terms into reverse polish notation
        this.tokensToReversePolishNotation();

        // calculate reverse polish notation
        this.rpnToResult();
    }

    // Test if token is an operator
    private boolean isOperator(String token)
    {
        // find the token in the hash map
        return OPERATORS.containsKey(token);
    }

        // Test if token is an number
        private boolean isNumber(String token)
        {
            for (int charNum = 0;  charNum < token.length(); charNum++ )
            {
                if (!NUMBERS.containsKey(token.charAt(charNum)))
                {
                    return false;
                }
            }
            return true;
            // find the token in the hash map
   //         return NUMBERS.containsKey(token);
        }
    // Test if token is an separator
    private boolean isSeparator(String token)
    {
        // find the token in the hash map
        return SEPARATORS.containsKey(token);
    }

    // Compare precedence of operators.
    private Boolean isPrecedent(String token1, String token2)
    {
        // token 1 is precedent if it is greater than token 2
        return (OPERATORS.get(token1) - OPERATORS.get(token2) >= 0);
    }

    // Term Tokenizer takes original expression and converts it to ArrayList of
    // tokens
    private void termTokenizer()
    {
        // contains final list of tokens
        this.tokens = new ArrayList<>();

        int start = 0; // term split starting index
        StringBuilder multiCharTerm = new StringBuilder(); // term holder
        for (int i = 0; i < this.expression.length(); i++)
        {
            Character c = this.expression.charAt(i);
            if (isOperator(c.toString()) || isSeparator(c.toString()))
            {
                // 1st check for working term and add if it exists
                if (multiCharTerm.length() > 0)
                {
                    tokens.add(this.expression.substring(start, i));
                }
                // Add operator or parenthesis term to list
                if (c != ' ')
                {
                    tokens.add(c.toString());
                }
                // Get ready for next term
                start = i + 1;
                multiCharTerm = new StringBuilder();
            }
            else
            {
                // multi character terms: numbers, functions, perhaps non-supported elements
                // Add next character to working term
                multiCharTerm.append(c);
            }

        }
        // Add last term
        if (multiCharTerm.length() > 0)
        {
            tokens.add(this.expression.substring(start));
        }
    }

    // Takes tokens and converts to Reverse Polish Notation (RPN), this is one where
    // the operator follows its operands.
    private void tokensToReversePolishNotation() throws Exception
    {
        // contains final list of tokens in RPN
        this.reverse_polish = new ArrayList<>();

        // stack is used to reorder for appropriate grouping and precedence
        Stack<String> tokenStack = new Stack<String>();
        int count = 0;
        for (String token : tokens)
        {
            switch (token)
            {
                // If left bracket push token on to stack
                case "(":
                    tokenStack.push(token);
                    count++;
                    break;
                case ")":
                    while (!tokenStack.empty() && tokenStack.peek() != null && !tokenStack.peek().equals("("))
                    {
                        reverse_polish.add(tokenStack.pop());
                        
                    }                    

                    if(!tokenStack.empty())
                    {
                        tokenStack.pop();
                    }
                    count--;
                    break;
                case "+":
                    
                case "-":
                case "*":
                case "/":
                case "^":
                case "SQRT":
                case "%":
                    // While stack
                    // not empty AND stack top element
                    // and is an operator
                    while (tokenStack.size() > 0 && isOperator(tokenStack.peek()))
                    {
                        if (isPrecedent(token, tokenStack.peek()))
                        {
                            reverse_polish.add(tokenStack.pop());
                            continue;
                        }
                        break;
                    }
                    // Push the new operator on the stack
                    tokenStack.push(token);
                    break;
                
                default: // Default should be a number, there could be test here
                    if(!isNumber(token))
                    {
                        Exception e = new Exception("\nThere are an unknown token in your expression: " + token);
                        throw e;
                    }
                    this.reverse_polish.add(token);
            }
        }

        //  Check misatched parenthesis
        if(count != 0)
        {
            //Exception e ("test");
            Exception e = new Exception("\nThere are uneven parenthesis in your expression.\n");
            throw e;
        }

        // Empty remaining tokens
        while (tokenStack.size() > 0)
        {
            reverse_polish.add(tokenStack.pop());
        }

    }

    // Takes RPN and produces a final result
    private void rpnToResult()
    {
        // stack is used to hold operands and each calculation
        Stack<Double> calcStack = new Stack<Double>();

        // RPN is processed, ultimately calcStack has final result
        for (String token : this.reverse_polish)
        {
            // If the token is an operator, calculate
            if (isOperator(token))
            {
                if(token.equals("SQRT"))
                {
                    Double x1 = calcStack.pop();
                    
                    result = calcStack.push(Math.sqrt(x1));
                        
                }
                else
                {

                
                // Pop the two top entries
                Double x1  = calcStack.pop();
                Double x2 = calcStack.pop();

                // Calculate intermediate results
                
                switch (token)
                {
                    case "+":
                    result = calcStack.push(x1 + x2);
                    break;

                    case "-":
                    result = calcStack.push(x2 - x1);
                    break;

                    case "*":
                    result = calcStack.push(x1 * x2);
                    break;

                    case "/":
                    result = calcStack.push(x2 / x1);
                    break;

                    case "^":
                    result = calcStack.push(Math.pow(x2, x1));
                    break;
                }
            }
                // Push intermediate result back onto the stack
                calcStack.push(result);
            }
            // else the token is a number push it onto the stack
            else
            {
                calcStack.push(Double.valueOf(token));
            }
        }
        // Pop final result and set as final result for expression
        this.result = calcStack.pop();
    }

    // Print the expression, terms, and result
    public String toString()
    {
        return ("Original expression: " + this.expression + "\n" + "Tokenized expression: " + this.tokens.toString()
                + "\n" + "Reverse Polish Notation: " + this.reverse_polish.toString() + "\n" + "Final result: "
                + String.format("%.2f", this.result));
    }

    // Tester method
    public static void main(String[] args)
    {
        try
        {
            // Random set of test cases
        Calculator simpleMath = new Calculator("100 + 200  * 3");
        System.out.println("\nSimple Math\n" + simpleMath);

        System.out.println();

        
        Calculator parenthesisMath = new Calculator("((100 + 200)  * 3)");
        System.out.println("Parenthesis Math\n" + parenthesisMath);

        System.out.println();

        Calculator decimalMath = new Calculator("100.2 - 99.3");
        System.out.println("Decimal Math\n" + decimalMath);

        System.out.println();

        Calculator moduloMath = new Calculator("300 % 200");
        System.out.println("Modulo Math\n" + moduloMath);

        System.out.println();

        Calculator divisionMath = new Calculator("300/200");
        System.out.println("Division Math\n" + divisionMath);

        System.out.println();

        Calculator exponentMath = new Calculator("2^3");
        System.out.println("Exponent Math\n" + exponentMath);

        System.out.println();

        Calculator sqrtMath = new Calculator("SQRT(9)");
        System.out.println("Exponent Math\n" + sqrtMath);

        System.out.println();
        
        }
        catch (Exception e) // catches errors
        {
            System.out.printf("Error in calculation\n%s\n", e.getMessage());
        }
        

    }
}
Calculator.main(null);
Simple Math
Original expression: 100 + 200  * 3
Tokenized expression: [100, +, 200, *, 3]
Reverse Polish Notation: [100, 200, 3, *, +]
Final result: 1200.00

Parenthesis Math
Original expression: ((100 + 200)  * 3)
Tokenized expression: [(, (, 100, +, 200, ), *, 3, )]
Reverse Polish Notation: [100, 200, +, 3, *]
Final result: 900.00

Decimal Math
Original expression: 100.2 - 99.3
Tokenized expression: [100.2, -, 99.3]
Reverse Polish Notation: [100.2, 99.3, -]
Final result: 0.90

Modulo Math
Original expression: 300 % 200
Tokenized expression: [300, %, 200]
Reverse Polish Notation: [300, 200, %]
Final result: 0.00

Division Math
Original expression: 300/200
Tokenized expression: [300, /, 200]
Reverse Polish Notation: [300, 200, /]
Final result: 1.50

Exponent Math
Original expression: 2^3
Tokenized expression: [2, ^, 3]
Reverse Polish Notation: [2, 3, ^]
Final result: 8.00

Exponent Math
Original expression: SQRT(9)
Tokenized expression: [SQRT, (, 9, )]
Reverse Polish Notation: [9, SQRT]
Final result: 3.00

Question #4

/**
 * Main class for Light.java
 *
 */
public class Light
{
    private boolean _on;
    
    // light is on/off
    public boolean getLight()
    {
        return _on;
    }

    // turns light on/off
    public void setLight(boolean on)
    {
        if(on)
        {
            _on = true;
        }
        else
        {
            _on = false;
        }
    }

}
import java.lang.Math;

/**
 * Main class for LightBoard.java
 *
 */
public class LightBoard
{
    private boolean[][] _lights;
    
    private int _off;
    private int _on;
    
    private static int NUM_ROWS;
    private static int NUM_COLS;
    
    /*
     * =
    {
        {true, true, false, true, true},
        {true, false, false, true, false},
        {true, false, false, true, true},
        {true, false, false, false, true},
        {true, false, false, false, true},
        {true, true, false, true, true},
        {false, false, false, false, false}
    }
     */
    
    /**
     * Constructor for class
     *
     * @param numRows
     * @param numCols
     */
    public LightBoard(int numRows, int numCols)
    {    
        NUM_ROWS = numRows;
        NUM_COLS = numCols;
        
        _lights = new boolean [NUM_ROWS][NUM_COLS];
        
        Light light = new Light();
       
        // 2D array nested loops, used for initialization
        for (int row = 0; row < NUM_ROWS; row++)
        {
            for (int col = 0; col < NUM_COLS; col++)
            {            
                double probability;
                probability = Math.random() * 10;
                
                if(probability <= 4.0)
                {
                    light.setLight(true);
                    
                    _lights[row][col] = light.getLight();
                    _on++;
                }
                else
                {
                    light.setLight(false);
                    
                    _lights[row][col] = light.getLight();
                    _off++;
                }
            }
        }
    }
    
    private int numLightsOn(int colNum)
    {
        int count = 0;
        
        // iterate over column
        for(int row = 0; row < NUM_ROWS; row++)
        {
            if(_lights[row][colNum])
            {
                count++;
            }
        }
        return count;
    }
    
    /**
     * evaluateLight 
     * 
     * @param row
     * @param col
     * @return
     */
    public boolean evaluateLight (int row, int col)
    {
        int numLightsOn = numLightsOn(col);

        if(_lights[row][col])
        {            
            if (numLightsOn % 2 == 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        else
        {            
            if(numLightsOn % 3 == 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        
    }
   
    /**
     * main 
     * 
     * @param Args
     */
    public static void main (String[] Args)
    {
        //Light light = new Light();
        LightBoard lightBoard = new LightBoard(7, 5);
                  
        for (int row = 0; row < NUM_ROWS; row++)
        {
            for(int col = 0; col < NUM_COLS; col++)
            {
                System.out.printf("light (%d, %d): %b\t", row, col, lightBoard._lights[row][col]);
            }
            System.out.printf("\n");
        }
        
        System.out.printf("\n# of lights on: \t%d\n# of lights off: \t%d",
                lightBoard._on, lightBoard._off);
        
        System.out.printf("\n");
        boolean test1 = lightBoard.evaluateLight(0, 3);
        boolean test2 = lightBoard.evaluateLight(6, 0);
        boolean test3 = lightBoard.evaluateLight(4, 1);
       
        System.out.printf("\nlight (0, 3): %b\t%b\n", lightBoard._lights[0][3], test1);
        System.out.printf("light (6, 0): %b\t%b\n", lightBoard._lights[6][0], test2);
        System.out.printf("light (4, 1): %b\t%b\n", lightBoard._lights[4][1], test3);
    }
}
LightBoard.main(null);
light (0, 0): false	light (0, 1): false	light (0, 2): true	light (0, 3): true	light (0, 4): false	
light (1, 0): true	light (1, 1): false	light (1, 2): true	light (1, 3): false	light (1, 4): false	
light (2, 0): false	light (2, 1): true	light (2, 2): false	light (2, 3): false	light (2, 4): false	
light (3, 0): false	light (3, 1): false	light (3, 2): false	light (3, 3): true	light (3, 4): true	
light (4, 0): false	light (4, 1): true	light (4, 2): true	light (4, 3): true	light (4, 4): true	
light (5, 0): true	light (5, 1): true	light (5, 2): false	light (5, 3): false	light (5, 4): false	
light (6, 0): false	light (6, 1): true	light (6, 2): false	light (6, 3): false	light (6, 4): false	

# of lights on: 	14
# of lights off: 	21

light (0, 3): true	true
light (6, 0): false	false
light (4, 1): true	false

Testing Process

FRQ #1

  • I used JUnit Testing to test my code

image

  • I tested numberOfLeapYears() by using the years 2010 to 2018. In those range of years, the expected output should be 2 leap years, which is the output of the test code

image

  • I tested dayOfWeek() by using the date 11/14/22. The expected output should be 1, which is what the test code outputs

image

  • After I ran my test code, the output showed a green bar which means that there are no errors

  • I also implemented the calendar to have user input. The program now asks the user for two years and calculates the number of leap years within the years the user entered

FRQ #2

  • I tested my code by steping through each line using the debugger

image

  • I put a breakpoint on the highlighted line and then stepped into each method, in this case I was testing the method addDailySteps() to see if it was adding the specified steps

Before:
image

After:
image

  • One of the problems with my code was the method for calculating average number of steps. The equaltion I used to calculate the average was not correct. I was dividing the total number of days tracked by the number of active steps.