A problem was reported through the Runestone "Report a Problem" form.
The character-by-character strategy the option describes is valid — the CED explicitly says solutions to part (b) that iterate over the string character-by-character can earn full credit — so I assume the parentheses were dropped accidentally rather than as a deliberate distractor. The feedback text for C discusses only the approach and doesn't mention the syntax, which supports that.
Worth fixing because it works against the rubric it's preparing students for: scoring point 6 for part (b) requires that all String method calls are syntactically valid, so message.length in an actual FRQ response would cost that point.
Suggested fix: add the parentheses.
[warn] No ad placements found.
[log] Timezone cookie matches, not sending timezone to server
[log] This page served by undefined
[log] triggering runestone:pre-login-complete
[log] Runestone pre-login complete
[log] Loading Runestone component: multiplechoice
[log] Loading Runestone component: answer
[log] Loading Runestone component: feedback
[log] Loading Runestone component: activecode
[log] before get hist
[log] before get hist
[log] before get hist
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-loop-type undefined
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-variables undefined
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-string-methods undefined
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-string-methods2 undefined
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop undefined
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] Response from server: 200
[log] adding video popouts
[log] setting up pretext
[log] Data from server: "no data" calling repopulateFromStorage
[log] resolving checkServer with server data
[log] Response from server: 200
[log] making a new scrubber
[log] Fake change event, skipping the log
[log] Response from server: 200
[log] Response from server: 200
[log] Response from server: 200
[log] making a new scrubber
[log] Fake change event, skipping the log
[log] Data from server: "no data" calling repopulateFromStorage
[log] resolving checkServer with server data
[log] Data from server: "no data" calling repopulateFromStorage
[log] resolving checkServer with server data
[log] making a new scrubber
[log] Fake change event, skipping the log
[log] Data from server: {"answer":"1","correct":true,"percent":1,"timestamp":"2026-09-11T16:09:33.653616+00:00","div_id":"csawesome2__msgbuilder-variables","sid":"MCampbellFPS","course_name":"27_CSA","id":98644108} calling repopulateFromStorage
[log] resolving checkServer with server data
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-variables_feedback undefined
[log] Data from server: {"answer":"1","correct":true,"percent":1,"timestamp":"2026-09-11T16:09:20.523915+00:00","div_id":"csawesome2__msgbuilder-loop-type","sid":"MCampbellFPS","course_name":"27_CSA","id":98644088} calling repopulateFromStorage
[log] resolving checkServer with server data
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-loop-type_feedback undefined
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] Save logging event {"event":"activecode","act":"edit","div_id":"csawesome2__FRQmessageBuilderPartA","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n while(getNextWord(tempWord) != null)\n {\n tempWord = getNextWord(tempWord);\n message = message + \" \" + tempWord;\n numWords = numWords + 1;\n }\n \n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:25.00:passed:1:failed:3","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n while(getNextWord(tempWord) != null)\n {\n tempWord = getNextWord(tempWord);\n message = message + \" \" + tempWord;\n numWords++;\n }\n \n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n while(getNextWord(tempWord) != null)\n {\n System.out.println(\"tempWord: \" + tempWord);\n tempWord = getNextWord(tempWord);\n message = message + \" \" + tempWord;\n numWords++;\n }\n \n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n while(getNextWord(tempWord) != null)\n {\n System.out.println(\"tempWord BgNW: \" + tempWord);\n tempWord = getNextWord(tempWord);\n System.out.println(\"tempWord AgNW: \" + tempWord);\n message = message + \" \" + tempWord;\n numWords++;\n }\n \n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n \n startingWord = getNextWord(startingWord);\n \n message = message + \" \" + startingWord;\n numWords++;\n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 1;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n message = message + \" \" + startingWord;\n startingWord = getNextWord(startingWord);\n \n \n numWords++;\n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 0;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n message = message + startingWord;\n startingWord = \" \" + getNextWord(startingWord);\n \n \n numWords++;\n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"13","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n String tempWord = startingWord;\n message = startingWord;\n \n numWords = 0;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n message = message + startingWord;\n startingWord = getNextWord(startingWord);\n \n \n numWords++;\n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"event":"activecode","act":"slide:Original","div_id":"csawesome2__FRQmessageBuilderPartA","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"event":"activecode","act":"slide:9/13/2026, 8:40:47 AM","div_id":"csawesome2__FRQmessageBuilderPartA","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n message = startingWord;\n numWords = 1;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n \n startingWord = getNextWord(startingWord);\n message = message + \" \" + startingWord;\n \n numWords++;\n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:50.00:passed:2:failed:2","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[uncaught] Uncaught ReferenceError: knowl_focus_stack is not defined @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:1370
[log] running {"div_id":"csawesome2__FRQmessageBuilderPartA","code":"public class MessageBuilder\n{\n private String message; // To be initialized in part (a)\n private int numWords; // To be initialized in part (a)\n \n /**\n * Part A: MessageBuilder(startingWord) constructor\n * Builds a message of words with spaces in between\n * starting with the word in the parameter\n * and counts the number of words in the message.\n * Precondition: startingWord is a single word with no spaces.\n */ \n public MessageBuilder(String startingWord)\n {\n message = startingWord;\n numWords = 1;\n \n // Complete the loop to build the message using the getNextWord method and increment numWords\n // Remember the 3 steps of writing a loop!\n while(startingWord != null)\n {\n \n startingWord = getNextWord(startingWord);\n if(startingWord != null)\n {\n message = message + \" \" + startingWord;\n numWords++;\n }\n \n }\n\n }\n \n /* These variables and methods were added to simulate Example 1 for testing purposes \n (implementation not shown in AP exam)\n */\n private String[] wordsForTesting = {\"the\", \"book\", \"on\", \"the\", \"table\"};\n private int currentWordIndex = 0;\n \n public String getNextWord(String s)\n { \n if(currentWordIndex < wordsForTesting.length - 1)\n {\n currentWordIndex++;\n return wordsForTesting[currentWordIndex];\n }\n else\n {\n return null;\n }\n }\n public String getMessage()\n {\n return message;\n } \n public int getNumWords()\n {\n return numWords;\n }\n public static void main(String[] args) \n {\n MessageBuilder builder = new MessageBuilder(\"the\");\n System.out.println(\"Message: \" + builder.getMessage());\n System.out.println(\"Number of words: \" + builder.getNumWords());\n }\n }\n","language":"java","errinfo":"success","to_save":"True","prefix":"","suffix":"import static org.junit.Assert.*;\n\nimport org.junit.*;\n\nimport java.io.*;\n\npublic class RunestoneTests extends CodeTestHelper\n{\n public RunestoneTests()\n {\n super(\"MessageBuilder\");\n }\n\n @Test\n public void testMain()\n {\n String output = getMethodOutput(\"main\");\n String expect = \"Message: the book on the table\\nNumber of words: 5\\n\";\n\n boolean passed = getResults(expect, output, \"Running main\");\n assertTrue(passed);\n }\n \n @Test\n public void testWhile() {\n boolean passed = checkCodeContains(\"while loop\",\"while\");\n assertTrue(passed);\n }\n @Test\n public void testNumWordsInc() {\n boolean passed = checkCodeContains(\"numWords++\");\n assertTrue(passed);\n }\n @Test\n public void testNextWordCall() {\n boolean passed = checkCodeContains(\"getNextWord(nextWord)\");\n assertTrue(passed);\n }\n}\n","partner":"","editDist":0,"changesPerSecond":0,"course":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] Save logging event {"act":"percent:75.00:passed:3:failed:1","div_id":"csawesome2__FRQmessageBuilderPartA","event":"unittest","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4}
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] SpliceWrapper: received message subject: undefined from iframe: unknown
[log] Save logging event {"event":"mChoice","act":"answer:2:correct","answer":"2","correct":"T","div_id":"csawesome2__msgbuilder-string-methods","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":1}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-string-methods_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:1:correct","answer":"1","correct":"T","div_id":"csawesome2__msgbuilder-string-methods2","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":1}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-string-methods2_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:1:no","answer":"1","correct":false,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":0}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:1,2:no","answer":"1,2","correct":false,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":0.5}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:0,1:no","answer":"0,1","correct":false,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":0.5}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:1:no","answer":"1","correct":false,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":0}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
[log] Save logging event {"event":"mChoice","act":"answer:0,2:correct","answer":"0,2","correct":true,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":1}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
[uncaught] Uncaught TypeError: Cannot read properties of null (reading 'classList') @ https://runestone.academy/ns/books/published/27_CSA/_static/pretext/js/dist/pretext-core.js?v=2.50:2467
[log] Save logging event {"event":"mChoice","act":"answer:0,2:correct","answer":"0,2","correct":true,"div_id":"csawesome2__msgbuilder-partb-loop","course_name":"27_CSA","clientLoginStatus":true,"timezoneoffset":4,"percent":1}
[log] MathJax Ready -- dequeing a typesetting run for csawesome2__msgbuilder-partb-loop_feedback undefined
A problem was reported through the Runestone "Report a Problem" form.
Description
Activity 2.25.6 (
csawesome2__msgbuilder-partb-loop), "Which of the following loop patterns can be used to find the next space in a String?"Option C is scored as correct but does not compile:
for(int i=0; i < message.length; i++)messageis a String, so this needsmessage.length()with parentheses.lengthwithout parentheses is the array field, not the String method.The character-by-character strategy the option describes is valid — the CED explicitly says solutions to part (b) that iterate over the string character-by-character can earn full credit — so I assume the parentheses were dropped accidentally rather than as a deliberate distractor. The feedback text for C discusses only the approach and doesn't mention the syntax, which supports that.
Worth fixing because it works against the rubric it's preparing students for: scoring point 6 for part (b) requires that all String method calls are syntactically valid, so
message.lengthin an actual FRQ response would cost that point.Suggested fix: add the parentheses.
Browser console log