FRQ 3: WordChecker Class — Homework Assignment

7 min read

Overview

This question involves analyzing a list of words using a WordChecker class. You will implement two methods: isWordChain and createList.

Learning Objectives

  • Traverse an ArrayList<String> using index-based loops
  • Use contains to check substring relationships between adjacent words
  • Use startsWith and substring to build transformed lists

Instructions

  • Complete Part A (isWordChain) first, then Part B (createList)
  • Run each code cell and verify expected output
  • Complete the combined challenge cell
  • Add screenshots in the placeholder sections

Part A — isWordChain

Returns true only if every word (after the first) contains the previous word as a substring.

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    private ArrayList<String> wordList;

    public Main(ArrayList<String> words) {
        wordList = words;
    }

    /**
     * Returns true if each element of wordList (except the first) contains
     * the previous element as a substring.
     */
    public boolean isWordChain() {
        for (int i = 1; i < wordList.size(); i++) {
            if (!wordList.get(i).contains(wordList.get(i - 1))) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        ArrayList<String> test1 = new ArrayList<>(Arrays.asList("an", "band", "band", "abandon"));
        Main checker1 = new Main(test1);

        ArrayList<String> test2 = new ArrayList<>(Arrays.asList("to", "too", "stool", "tools"));
        Main checker2 = new Main(test2);

        System.out.println("Test 1: " + test1);
        System.out.println("Expected: true");
        System.out.println("Result: " + checker1.isWordChain());
        System.out.println();

        System.out.println("Test 2: " + test2);
        System.out.println("Expected: false");
        System.out.println("Result: " + checker2.isWordChain());
    }
}
run:Main.main(null);

Screenshot Placeholder — Part A

  • Insert code runner screenshot here

Part A Screenshot Placeholder

Part B — createList

Creates a new list of words that begin with target, with the initial target removed.

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    private ArrayList<String> wordList;

    public Main(ArrayList<String> words) {
        wordList = words;
    }

    /**
     * Returns an ArrayList<String> containing words that start with target,
     * with the starting target removed from each included word.
     */
    public ArrayList<String> createList(String target) {
        ArrayList<String> result = new ArrayList<String>();

        for (String word : wordList) {
            if (word.startsWith(target)) {
                result.add(word.substring(target.length()));
            }
        }

        return result;
    }

    public static void main(String[] args) {
        ArrayList<String> words = new ArrayList<>(Arrays.asList("catch", "bobcat", "catchacat", "cat", "at"));
        Main checker = new Main(words);

        System.out.println("Original wordList: " + words);
        System.out.println();

        ArrayList<String> result1 = checker.createList("cat");
        System.out.println("createList(\"cat\")");
        System.out.println("Expected: [ch, chacat, ]");
        System.out.println("Result: " + result1);
        System.out.println();

        ArrayList<String> result2 = checker.createList("catch");
        System.out.println("createList(\"catch\")");
        System.out.println("Expected: [, acat]");
        System.out.println("Result: " + result2);
        System.out.println();

        ArrayList<String> result3 = checker.createList("dog");
        System.out.println("createList(\"dog\")");
        System.out.println("Expected: []");
        System.out.println("Result: " + result3);
    }
}
run:Main.main(null);

Screenshot Placeholder — Part B

  • Insert code runner screenshot here

Part B Screenshot Placeholder

Task — Combine

Implement both methods together in one WordChecker class and test both parts.

import java.util.ArrayList;
import java.util.Arrays;

public class Main {
    static class WordChecker {
        private ArrayList<String> wordList;

        public WordChecker(ArrayList<String> words) {
            wordList = words;
        }

        public boolean isWordChain() {
            for (int i = 1; i < wordList.size(); i++) {
                if (!wordList.get(i).contains(wordList.get(i - 1))) {
                    return false;
                }
            }
            return true;
        }

        public ArrayList<String> createList(String target) {
            ArrayList<String> result = new ArrayList<String>();
            for (String word : wordList) {
                if (word.startsWith(target)) {
                    result.add(word.substring(target.length()));
                }
            }
            return result;
        }
    }

    public static void main(String[] args) {
        ArrayList<String> chainWords1 = new ArrayList<>(Arrays.asList("an", "band", "band", "abandon"));
        ArrayList<String> chainWords2 = new ArrayList<>(Arrays.asList("to", "too", "stool", "tools"));

        WordChecker wc1 = new WordChecker(chainWords1);
        WordChecker wc2 = new WordChecker(chainWords2);

        System.out.println("Combined isWordChain Tests:");
        System.out.println(chainWords1 + " -> " + wc1.isWordChain() + " (expected true)");
        System.out.println(chainWords2 + " -> " + wc2.isWordChain() + " (expected false)");
        System.out.println();

        ArrayList<String> words = new ArrayList<>(Arrays.asList("catch", "bobcat", "catchacat", "cat", "at"));
        WordChecker wc3 = new WordChecker(words);

        System.out.println("Combined createList Tests:");
        System.out.println("createList(\"cat\"): " + wc3.createList("cat") + " (expected [ch, chacat, ])");
        System.out.println("createList(\"catch\"): " + wc3.createList("catch") + " (expected [, acat])");
        System.out.println("createList(\"dog\"): " + wc3.createList("dog") + " (expected [])");
    }
}
run:Main.main(null);

Screenshot Placeholder — Combined

  • Insert code runner screenshot here

Combined Screenshot Placeholder

Grading Rubric — Total: 9 points

Part (a) - isWordChain - 4 points

  • +1 Traverses adjacent pairs in wordList
  • +1 Checks whether current word contains previous word
  • +1 Returns false immediately on first failing pair
  • +1 Returns true only when all pairs satisfy condition

Part (b) - createList - 5 points

  • +1 Creates a new ArrayList<String> for results
  • +1 Identifies words that start with target
  • +1 Removes the initial occurrence using substring(target.length())
  • +1 Preserves original order from wordList
  • +1 Leaves wordList unchanged

Main Takeaways (Submission Notes)

I used a simple adjacent-pair loop for isWordChain, which is the cleanest way to verify each word contains the one before it. Returning early on a mismatch keeps the method efficient and easy to read.

For createList, I built a new result list and only added transformed words that start with target. Using substring(target.length()) removes exactly the first prefix occurrence and preserves order naturally during traversal.

This FRQ helps with AP CSA patterns around string methods, list traversal, and writing methods that satisfy pre/postconditions without mutating the original data.