FRQ 2016 Number 3 Homework 2
Homework
FRQ 2016 #3: Crossword Puzzle Labeling
Complete Solution with Detailed Explanation
Problem Overview
A crossword puzzle grid is a 2D array where some squares are black (blocked) and some are white (playable). Only certain white squares get labeled with positive numbers according to the Crossword Labeling Rule.
Crossword Labeling Rule
A white square is labeled if and only if:
- The square is white (not black), AND
- At least one of these is true:
- No white square immediately above (top row or square above is black)
- No white square immediately to the left (left column or square to left is black)
Numbers are assigned consecutively in row-major order starting at 1.
Example Grid
[B W W] [BLACK 1 2]
[W W B] → [3 0 BLACK]
[W W W] [4 5 6]
Where B = black, W = white, 0 = unlabeled white square
Part (a): toBeLabeled Method - 3 points
What It Does
Returns true if the square at position [r][c] should be labeled according to the crossword labeling rule.
The Logic (Step by Step)
- Check if white:
!blackSquares[r][c] - Check top/left boundary:
r == 0→ In first row (nothing above)c == 0→ In first column (nothing to left)blackSquares[r-1][c]→ Square above is blackblackSquares[r][c-1]→ Square to left is black
If the square is white AND at least one boundary condition is true → labeled
Key Insight
The four conditions in the OR check cover all ways a white square can be the start of a clue:
- First row always starts a down clue
- First column always starts an across clue
- Black square above means start of a down clue
- Black square to left means start of an across clue
// PART (a) SOLUTION - toBeLabeled
private boolean toBeLabeled(int r, int c, boolean[][] blackSquares)
{
return (!(blackSquares[r][c]) &&
(r == 0 || c == 0 || blackSquares[r - 1][c] ||
blackSquares[r][c - 1]));
}
/* Scoring (3 points):
* +1 Checks blackSquares[r][c]
* +1 Checks for a black square or grid border above and to the left (no bounds errors)
* +1 Returns correct boolean result
*/
Part (b): Crossword Constructor - 6 points
What It Does
Creates a crossword puzzle grid with:
- Same dimensions as the
blackSquaresinput - Each cell contains a
Squareobject with correct color and number - Only squares that satisfy
toBeLabeled()get positive numbers (1, 2, 3, …) - All other squares get 0
Algorithm Overview
Step 1: Initialize puzzle grid with correct dimensions
puzzle = new Square[blackSquares.length][blackSquares[0].length];
Step 2: Loop through ALL cells in row-major order (ensures consecutive numbering)
for (int r = 0; r < blackSquares.length; r++)
for (int c = 0; c < blackSquares[r].length; c++)
Step 3: For each cell, check if it should be labeled
- If
toBeLabeled()returns true → Create Square with current label (then increment) - Otherwise → Create Square with label 0
Step 4: All squares get a Square object (whether labeled or not)
Key Points for Full Credit
Initialize puzzle with blackSquares.length and blackSquares[0].length
se toBeLabeled() to determine labeling
ssign correct color based on blackSquares[r][c]
umbers increment: 1, 2, 3, … (only for labeled squares)
Every cell gets a Square object
Row-major order for numbering
// PART (b) SOLUTION - Crossword Constructor
public Crossword(boolean[][] blackSquares)
{
// Initialize puzzle with correct dimensions (+1 point)
puzzle = new Square[blackSquares.length][blackSquares[0].length];
int label = 1;
// Access all locations in puzzle (+1 point)
for (int r = 0; r < blackSquares.length; r++)
{
for (int c = 0; c < blackSquares[r].length; c++)
{
// Call toBeLabeled correctly (+1 point)
if (toBeLabeled(r, c, blackSquares))
{
// Create Square with consecutive label starting at 1 (+2 points)
puzzle[r][c] = new Square(blackSquares[r][c], label);
label++;
}
else
{
// Create Square with 0 if not labeled (+1 point)
puzzle[r][c] = new Square(blackSquares[r][c], 0);
}
}
}
}
/* Scoring (6 points):
* +1 Initializes puzzle with correct dimensions
* +1 Accesses all locations in puzzle
* +1 Calls toBeLabeled correctly
* +1 Creates and assigns Square objects
* +1 Labels squares consecutively in row-major order starting at 1
* +1 Final grid has correct color and numbers
*/
// COMPLETE WORKING SOLUTION WITH TEST CASES
class Square {
private boolean isBlack;
private int num;
public Square(boolean isBlack, int num) {
this.isBlack = isBlack;
this.num = num;
}
public String toString() {
return isBlack ? "BLACK" : String.valueOf(num);
}
}
public class Crossword {
private Square[][] puzzle;
// Part (a): Check if square should be labeled
private boolean toBeLabeled(int r, int c, boolean[][] blackSquares)
{
return (!(blackSquares[r][c]) &&
(r == 0 || c == 0 || blackSquares[r - 1][c] ||
blackSquares[r][c - 1]));
}
// Part (b): Constructor
public Crossword(boolean[][] blackSquares)
{
puzzle = new Square[blackSquares.length][blackSquares[0].length];
int label = 1;
for (int r = 0; r < blackSquares.length; r++)
{
for (int c = 0; c < blackSquares[r].length; c++)
{
if (toBeLabeled(r, c, blackSquares))
{
puzzle[r][c] = new Square(blackSquares[r][c], label);
label++;
}
else
{
puzzle[r][c] = new Square(blackSquares[r][c], 0);
}
}
}
}
// Display the puzzle grid
public void displayGrid() {
for (int r = 0; r < puzzle.length; r++) {
for (int c = 0; c < puzzle[r].length; c++) {
System.out.print(puzzle[r][c] + "\t");
}
System.out.println();
}
}
// Test cases
public static void main(String[] args) {
// Test 1: 3x3 grid (from problem statement)
System.out.println("TEST 1: 3x3 Grid");
System.out.println("Input: {[T,F,F], [F,F,T], [F,T,F]}");
boolean[][] test1 = {
{true, false, false},
{false, false, true},
{false, true, false}
};
Crossword cw1 = new Crossword(test1);
System.out.println("Output:");
cw1.displayGrid();
System.out.println("Expected: [BLACK, 1, 2] / [3, 0, BLACK] / [4, BLACK, 5]\n");
// Test 2: All white (no black squares)
System.out.println("TEST 2: All White 2x2");
System.out.println("Input: {[F,F], [F,F]}");
boolean[][] test2 = {
{false, false},
{false, false}
};
Crossword cw2 = new Crossword(test2);
System.out.println("Output:");
cw2.displayGrid();
System.out.println("Expected: [1, 2] / [3, 0]\n");
// Test 3: Larger grid with mixed black/white
System.out.println("TEST 3: 4x4 Mixed Grid");
System.out.println("Input: {[F,F,T,F], [T,F,F,F], [F,F,T,F], [F,T,F,F]}");
boolean[][] test3 = {
{false, false, true, false},
{true, false, false, false},
{false, false, true, false},
{false, true, false, false}
};
Crossword cw3 = new Crossword(test3);
System.out.println("Output:");
cw3.displayGrid();
System.out.println();
}
}
// Run tests
Crossword.main(new String[]{});
TEST 1: 3x3 Grid
Input: {[T,F,F], [F,F,T], [F,T,F]}
Output:
BLACK 1 2
3 0 BLACK
4 BLACK 5
Expected: [BLACK, 1, 2] / [3, 0, BLACK] / [4, BLACK, 5]
TEST 2: All White 2x2
Input: {[F,F], [F,F]}
Output:
1 2
3 0
Expected: [1, 2] / [3, 0]
TEST 3: 4x4 Mixed Grid
Input: {[F,F,T,F], [T,F,F,F], [F,F,T,F], [F,T,F,F]}
Output:
1 2 BLACK 3
BLACK 4 5 0
6 0 BLACK 7
8 BLACK 9 0
Detailed Walkthrough: Test Case 1
Given grid:
Input: {[T,F,F], Output: [BLACK, 1, 2 ]
[F,F,T], [3, 0, BLACK]
[F,T,F]} [4, BLACK, 5 ]
Step-by-Step Execution
Iteration through row-major order:
| r,c | Value | toBeLabeled? | Reason | Result |
|---|---|---|---|---|
| 0,0 | T (black) | N/A | Black square | Square(true, 0) |
| 0,1 | F (white) | YES | r==0 (top row) | Square(false, 1), label→2 |
| 0,2 | F (white) | YES | r==0 (top row) | Square(false, 2), label→3 |
| 1,0 | F (white) | YES | c==0 (left col) | Square(false, 3), label→4 |
| 1,1 | F (white) | NO | [0,1]&[1,0] both white | Square(false, 0) |
| 1,2 | T (black) | N/A | Black square | Square(true, 0) |
| 2,0 | F (white) | YES | c==0 (left col) | Square(false, 4), label→5 |
| 2,1 | T (black) | N/A | Black square | Square(true, 0) |
| 2,2 | F (white) | YES | [2,1] is black | Square(false, 5), label→6 |
Notice: position [1,1] is NOT labeled because:
- Position above [0,1] is WHITE
- Position to left [1,0] is WHITE
- So it’s NOT the start of any clue
Summary: What Earns Full 9 Points
Part (a) - 3 points:
- Checks if square is white ✓
- Checks boundaries correctly without causing IndexOutOfBoundsException ✓
- Returns correct boolean ✓
Part (b) - 6 points:
- Initializes puzzle with right dimensions ✓
- Accesses all cells (double loop) ✓
- Calls toBeLabeled() appropriately ✓
- Creates Square objects properly ✓
- Numbers are consecutive (1,2,3,…) in row-major order ✓
- Final grid matches expected output ✓