Sprint View

2019 FRQ 4

11 min read

FRQ Question Part A

The LightBoard class models a two-dimensional display of lights, where each light is either on or off, as represented by a Boolean value. You will implement a constructor to initialize the display and a method to evaluate a light.

Write the constructor for the LightBoard class, which initializes lights so that each light is set to on with a 40% probability. The notation lights[r][c] represents the array element at row r and column c.

Complete the LightBoard constructor below.

Code Runner Challenge

Lightboard Part A

View IPYNB Source
// CODE_RUNNER: Lightboard Part A

class LightBoard
{
    /** The lights on the board, where true represents on and false represents off.
     */
    private boolean[][] lights;
    
    /** Constructs a LightBoard object having numRows rows and numCols columns.
     * Precondition: numRows > 0, numCols > 0
     * Postcondition: each light has a 40% probability of being set to on.
     */
    public LightBoard(int numRows, int numCols)
    {
        lights = new boolean[numRows][numCols];
        for (int r = 0; r < numRows; r++) {
            for (int c = 0; c < numCols; c++) {
                if (Math.random() < 0.4) {
                    lights[r][c] = true;
                } else {
                    lights[r][c] = false;
                }
            }
        }
    }

    /** Evaluates a light in row index row and column index col and returns a status
     * as described in part (b).
     * Precondition: row and col are valid indexes in lights.
     */
    public boolean evaluateLight(int row, int col)
    { /* to be implemented in part (b) */ return false; }

    public void printBoard() {
        for (int r = 0; r < lights.length; r++) {
            for (int c = 0; c < lights[0].length; c++) {
                System.out.print((lights[r][c] ? "T" : "F") + " ");
            }
            System.out.println();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        LightBoard board = new LightBoard(5, 5);
        System.out.println("Part A - Initial Board (T = true/on, F = false/off):");
        board.printBoard();
    }
}

Main.main(null);
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

FRQ Question Part B

Write the method evaluateLight, which computes and returns the status of a light at a given row and column based on the following rules.

  1. If the light is on, return false if the number of lights in its column that are on is even, including the current light.
  2. If the light is off, return true if the number of lights in its column that are on is divisible by three.
  3. Otherwise, return the light’s current status. For example, suppose that LightBoard sim = new LightBoard(7, 5) creates a light board with the initial state shown below, where true represents a light that is on and false represents a light that is off. Lights that are off are shaded.

lights

  0 1 2 3 4
0 true true false true true
1 true false false true false
2 true false false true true
3 true false false false true
4 true false false false true
5 true true false true true
6 false false false false false

Sample calls to evaluateLight are shown below.

Call to evaluateLight Value Returned Explanation
sim.evaluateLight(0, 3); false The light is on, and the number of lights that are on in its column is even
sim.evaluateLight(6, 0); true The light is off, and the number of lights that are on in its column is divisible by 3.
sim.evaluateLight(4, 1); false Returns the light’s current status.
sim.evaluateLight(5, 4); true Returns the light’s current status.

Class information for this question

Code Runner Challenge

Lightboard Part B

View IPYNB Source
public class LightBoard
private boolean[][] lights
public LightBoard(int numRows, int numCols)
public boolean evaluateLight(int row, int col)
Lines: 1 Characters: 0
Output
Click "Run" in code control panel to see output ...

Complete the evaluateLight method below.

// CODE_RUNNER: Lightboard Part B

class LightBoard
{
    /** The lights on the board, where true represents on and false represents off.
     */
    private boolean[][] lights;
    
    /** Constructs a LightBoard object having numRows rows and numCols columns.
     * Precondition: numRows > 0, numCols > 0
     * Postcondition: each light has a 40% probability of being set to on.
     */
    public LightBoard(int numRows, int numCols)
    {
        lights = new boolean[numRows][numCols];
        for (int r = 0; r < numRows; r++) {
            for (int c = 0; c < numCols; c++) {
                if (Math.random() < 0.4) {
                    lights[r][c] = true;
                } else {
                    lights[r][c] = false;
                }
            }
        }
    }

    /** Evaluates a light in row index row and column index col and returns a status
     * as described in part (b).
     * Precondition: row and col are valid indexes in lights.
     */
    public boolean evaluateLight(int row, int col)
    {
        int onCount = 0;
        
        // Count lights strictly in the specified column
        for (int r = 0; r < lights.length; r++) {
            if (lights[r][col]) {
                onCount++;
            }
        }

        boolean currentStatus = lights[row][col];

        if (currentStatus) {
            // Rule 1: Light is on, return false if number of lights in column is even
            if (onCount % 2 == 0) {
                return false;
            }
        } else {
            // Rule 2: Light is off, return true if number of lights in column is divisible by 3
            if (onCount % 3 == 0) {
                return true;
            }
        }

        // Rule 3: Otherwise return current status
        return currentStatus;
    }

    public void printBoard() {
        for (int r = 0; r < lights.length; r++) {
            for (int c = 0; c < lights[0].length; c++) {
                System.out.print((lights[r][c] ? "T" : "F") + " ");
            }
            System.out.println();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        LightBoard board = new LightBoard(5, 5);
        System.out.println("Part B - Board State:");
        board.printBoard();
        System.out.println("Evaluation of Light at (0, 0): " + board.evaluateLight(0, 0));
        System.out.println("Evaluation of Light at (4, 4): " + board.evaluateLight(4, 4));
    }
}

Main.main(null);

Scoring Guidelines Part A

Intent: Define implementation of a constructor that initializes a 2D array of lights

  • +1 Creates a new boolean[numRows][numCols] and assigns to instance variable lights
  • +1 Accesses all elements in the created 2D array (no bounds errors)
  • +1 Computes the 40% probability
  • +1 Sets all values of 2D array based on computed probability
Part (a) LightBoard     4 points
Points Rubric Criteria Responses earn the point even if they… Responses will not earn the point if they…
+1 Creates a new boolean[numRows][numCols] and assigns to instance variable lights   • initialize a local variable that is never assigned to lights
• omit the keyword new
• use a type other than boolean
+1 Accesses all elements in the created 2D array (no bounds errors) • fail to create lights but assume lights[numRows][numCols]  
+1 Computes the 40% probability • use Math.random() <= .4 • incorrectly cast to int
+1 Sets all values of 2D array based on computed probability • only assign true values • compute a single probability but use it multiple times
• reverse the sense of the comparison when assigning
public LightBoard(int numRows, int numCols)
{
    lights = new boolean[numRows][numCols];

    for (int r = 0; r < numRows; r++)
    {
        for (int c = 0; c < numCols; c++)
        {
            double rnd = Math.random();
            lights[r][c] = rnd < 0.4;
        }
    }
}

Scoring Guidelines Part B

Intent: Evaluate the status of a light in a 2D array of lights

  • +1 Accesses an element of lights as a boolean value in an expression
  • +1 Traverses specified col of a 2D array (no bounds errors)
  • +1 Counts the number of true values in the traversal
  • +1 Performs an even calculation and a multiple of three calculation
  • +1 Returns true or false according to all three rules
Part (b) evaluateLight     5 points
Points Rubric Criteria Responses earn the point even if they… Responses will not earn the point if they…
+1 Accesses an element of lights as a boolean value in an expression   • access lights as a type other than boolean
+1 Traverses specified col of a 2D array (no bounds errors)    
+1 Counts the number of true values in the traversal • access too many or too few items in a single column
• access a single row instead of a single column
• count an item more than once
+1 Performs an even calculation and a multiple of three calculation   • use / instead of %
+1 Returns true or false according to all three rules • have an incorrect column count but use the correct logic • fail to return a value in some case
• implement counting loop more than once with one loop that is incorrect
public boolean evaluateLight(int row, int col)
{
    int numOn = 0;

    for (int r = 0; r < lights.length; r++)
    {
        if (lights[r][col])
        {
            numOn++;
        }
    }

    if (lights[row][col] && numOn % 2 == 0)
    {
        return false;
    }
    if (!lights[row][col] && numOn % 3 == 0)
    {
        return true;
    }
    return lights[row][col];
}

Detailed Explanation

Part A: Constructor Logic

The goal of the constructor is to initialize the lights 2D array.

  1. Instantiation: First, we must create the array object itself using lights = new boolean[numRows][numCols];. Without this, lights is null and cannot hold data.
  2. Traversal: We need to visit every single cell in this grid. A nested for-loop is the standard way to do this. The outer loop iterates through rows (0 to numRows - 1), and the inner loop iterates through columns (0 to numCols - 1).
  3. Probability: For each cell, we generate a random number using Math.random(), which returns a double between 0.0 (inclusive) and 1.0 (exclusive). To get a 40% probability of being true, we check if the random number is less than 0.4.

Part B: evaluateLight Logic

This method decides the status of a specific light based on the column it resides in.

  1. Counting Lights: Before checking rules, we need to know how many lights are “on” in the specified column (col). We iterate through every row r while keeping the column index fixed at col. If lights[r][col] is true, we increment a counter numOn.
  2. Applying Rules:
    • Rule 1 (Light is On): If lights[row][col] is true, we check if numOn is even (numOn % 2 == 0). If so, we return false.
    • Rule 2 (Light is Off): If lights[row][col] is false (implicit else logic typically, but handled via specific checks here), we check if numOn is divisible by 3 (numOn % 3 == 0). If so, we return true.
    • Rule 3 (Default): If neither of the specific conditions above triggers a change, we simply return the current state of the light: lights[row][col].

Common Mistakes

Part A

  • Forgetting new: A common error is declaring the array variable but forgetting to initialize it with new boolean[rows][cols].
  • Row/Column Confusion: Swapping numRows and numCols when creating the array or in the loops results in an ArrayIndexOutOfBoundsException if the grid isn’t square.
  • Incorrect Probability: Using Math.random() * 0.4 or incorrect integer casting (e.g., (int) Math.random()) will not produce the correct distribution.
  • Re-rolling Probability: Generating a random number once before the loops and applying it to every cell means all cells will be identical, rather than independently random.

Part B

  • Iterating Wrong Dimension: When counting lights in a column, the loop should vary the row index (r goes from 0 to lights.length), while the column index stays fixed. A common mistake is iterating over columns (c) instead.
  • Counting Logic: Forgetting to initialize the counter to 0 inside the method.
  • Modulus Operator: Using division / instead of modulus % to check for evenness or divisibility by 3.
  • Return Logic: Attempting to combine all logic into a single complex boolean return statement often leads to errors. It is usually cleaner to use if statements for the specific exceptions (Rules 1 and 2) and a default return for Rule 3.

Submit Your Work

Submit all your code challenges for this lesson.

Preview Submission (0 challenges)

Course Timeline