The RouteCipher problem from the 2011 AP Computer Science Exam is typical of free response problems that test 2 dimensional arrays. The problem requires you to traverse the array in row major order, which is most easily accomplished with a nested for loop.
Review the RouteCipher free response problem with AP CS Tutor Brandon Horn.
RouteCipher Part (a): fillBlock
private void fillBlock(String str)
{
int strIndex = 0;
for (int r = 0; r < numRows; r++)
{
for (int c = 0; c < numCols; c++)
{
if (strIndex >= str.length())
letterBlock[r][c] = "A";
else
letterBlock[r][c] = str.substring(strIndex, strIndex + 1);
strIndex++;
}
}
}
RouteCipher Part (a): fillBlock – alternate solution
private void fillBlock(String str)
{
for (int i = 0; i < numRows * numCols; i++)
{
if (i >= str.length())
letterBlock[i / numCols][i % numCols] = "A";
else
letterBlock[i / numCols][i % numCols] = str.substring(i, i + 1);
}
}
RouteCipher Part (b): encryptMessage
public String encryptMessage(String message)
{
String cipherText = "";
int mIndex = 0;
while(mIndex < message.length())
{
fillBlock(message.substring(mIndex)); // ignores extra characters
cipherText += encryptBlock();
mIndex += numRows * numCols;
}
return cipherText;
}
RouteCipher Part (b): encryptMessage – alternate solution 1
public String encryptMessage(String message)
{
String cipherText = "";
while (message.length() > 0)
{
fillBlock(message); // ignores extra characters
cipherText += encryptBlock();
if(message.length() > numRows * numCols)
message = message.substring(numRows * numCols);
else
message = "";
}
return cipherText;
}
RouteCipher Part (b): encryptMessage – alternate solution 2
public String encryptMessage(String message)
{
String cipherText = "";
for(int i = 0; i < message.length(); i += numRows * numCols)
{
fillBlock(message.substring(i));
cipherText += encryptBlock();
}
return cipherText;
}
This is the same as the first solution except with a for loop.
2011 AP CS Exam Free Response Solutions |
Recommended Practice Problems |
for part a, would this work?
int k=0;
int size=string.length(); string temp=””;
while(k<numRows*numCols){
if(k<size)
temp=string.substring(k,k+1);
else temp="A";
int row=k/numCols;
int col=k%numCols;
letterBlock[row][col]=temp;
k++;
}
Your logic is correct; however, you have some minor syntax errors. Here is a working version using your logic.
thank you!
for part b, I am not sure if I understood this correctly, but
fillBlock(message); doesn’t this line fill the array with the message?? not concatenate it??
Thank You
fillBlock(message)
starts at the beginning of the message and copies as much of the message as possible into the array. If there are more characters in the message than there are spaces in the array,fillBlock
ignores the remaining characters in the message. If there are fewer characters in the message than there are spaces in the array,fillBlock
fills each remaining space in the array with"A"
. Each timefillBlock
is run everything previously in the array is removed.In part (b),
encryptMessage
repeatedly:– fills the array using
fillBlock
(regardless of the number of characters that remain in the message)– encrypts the array by calling
encryptBlock
– concatenates the existing ciphertext with the encrypted result
– removes the number of characters encrypted from the front of the message
Is there a way to do it using a for loop?
This is what I was trying to do:
int size = numRows * numCols;
String encrypted = “”;
if(message.length()==0)
return encrypted; //to return an empty string right away without filling block entirely of “A”s (is this needed?)
else //problem starts here..:(
{
for(int k=0; k<message.length(); k+=size)
{
fillBlock(message.substring(k, k+size); //Q: How do you do this without causing indexOutOfBoundsException at the last loop?
encrypted += encryptBlock();
}
}
return encrypted;
Also, please let me know if there are any other mistakes.
Thank you!
Both parts can be done with simple
for
loops. I added an alternate solution for each part that demonstrates the technique. The problem with your code is the second parameter tosubstring
.fillBlock already
ignores excess characters. It is unnecessary to obtain a substring of the exact length and results in an exception on the last run.