我正在使用 StringBuilder 更改字符串输入并根据输入进行移动。这是针对 META 编码实践网站的,我遇到了他们的两个测试用例的问题。一个通过了,另一个没有通过。
预期输出为
stuvRPQrpq-999.@
,输入为 abcdZXYzxy-999.@
,偏移为 200
。
这是我的代码
String rotationalCipher(String input, int rotationFactor) {
// Write your code here
int shift = rotationFactor % 26;
StringBuilder output = new StringBuilder();
for (char character : input.toCharArray()) {
if (character >= 'a' && character <= 'z') {
character = (char) (character + shift);
if (character > 'z') {
character = (char) (character + 'a' - 'z' - 1);
}
output.append(character);
} else if (character >= 'A' && character <= 'Z') {
character = (char) (character + shift);
if (character > 'Z') {
character = (char) (character + 'A' - 'Z' - 1);
}
output.append(character);
} else if (character >= '0' && character <= '9') {
character = (char) (character + shift);
if (character > '9') {
character = (char) (character + '0' - '9' - 1);
}
output.append(character);
} else {
output.append(character);
}
}
return output.toString();
}
我的问题是,我以某种方式输出
AAA
而不是 999
据我所知,从跟踪我的算法看来是可靠的。我查看了 JAVA 文档 StringBuilder 页面,看看我的使用方式是否存在任何问题。据我所知,应该很好去。
有人可以告诉我为什么我的输出是这样的吗?
这是测试用例代码:
String input_1 = "All-convoYs-9-be:Alert1.";
int rotationFactor_1 = 4;
String expected_1 = "Epp-gsrzsCw-3-fi:Epivx5.";
String output_1 = rotationalCipher(input_1, rotationFactor_1);
check(expected_1, output_1);
String input_2 = "abcdZXYzxy-999.@";
int rotationFactor_2 = 200;
String expected_2 = "stuvRPQrpq-999.@";
String output_2 = rotationalCipher(input_2, rotationFactor_2);
check(expected_2, output_2);
检查你的数学
200 % 26 = 18 (shift)
'9' + 18 = 57 + 18 = 75 ('K')
75 + '0' = 75 + 48 = 123 ('{')
123 - '9' = 123 - 57 = 66 ('B')
66 - 1 = 65 ('A')
现在的问题是,在 '9' 和 'A' 之间还有 7 个其他字符,所以
character = (char) (character + ('0' - '9') - 1);
必须变成 character = (char) (character + ('0' - '9') - 9);
才能将 9
移回 9
,但这会搞砸你的其他字符测试用例
我不认为 ASCII 操作是正确的方法,因为数字和大小写字符之间存在字符,随着旋转的增加,这些字符会弄乱事情。
事实上,对于数字,您确实想使用
factor % 10
来旋转。
另一种方法是生成字符列表并对这些字符应用移位。现在,如果我这样做,我会使用
List
和 Collections
,但我们假设你不能再这样做,相反,我们需要对数组应用移位,例如。 ..
public String[] rotate(String[] original, int offset) {
if (offset >= 0) {
return positiveRotate(original, offset);
}
return negativeRotate(original, Math.abs(offset));
}
public String[] positiveRotate(String[] original, int offset) {
String[] results = new String[original.length];
int count = original.length - offset;
System.arraycopy(original, count, results, 0, offset);
System.arraycopy(original, 0, results, offset, count);
return results;
}
public String[] negativeRotate(String[] original, int offset) {
String[] results = new String[original.length];
System.arraycopy(original, offset, results, 0, original.length - offset);
System.arraycopy(original, 0, results, original.length - offset, offset);
return results;
}
现在,有两种不同的方法,一种是“正”(或“右”移),另一种是“负”(或“左”移)。在测试过程中,我发现您想要“左移”数组。
接下来,我们需要我们想要转移的内容...
private String[] digits = "0123456789".split("");
private String[] characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
我在这里作弊了,你可能需要手动创建数组,但我懒得把它写出来。
请注意
String
数组而不是 char
数组,不难更改,但我很懒String
上执行此操作,使用 contains
和 split
等工具来执行移位然后旋转密码可能看起来像......
public String rotationalCipher(String input, int rotationFactor) {
int shift = rotationFactor % 26;
String[] shiftedDigits = rotate(digits, -(rotationFactor % 10));
String[] shiftCharacters = rotate(characters, -(rotationFactor % 26));
StringBuilder output = new StringBuilder();
for (char character : input.toCharArray()) {
String value = Character.toString(character);
int index = 0;
if ((index = indexOf(value, digits)) > -1) {
output.append(shiftedDigits[index]);
} else if ((index = indexOf(value, characters)) > -1) {
output.append(shiftCharacters[index]);
} else if ((index = indexOf(value.toUpperCase(), characters)) > -1) {
output.append(shiftCharacters[index].toLowerCase());
} else {
output.append(value);
}
}
return output.toString();
}
protected int indexOf(String value, String[] array) {
for (int index = 0; index < array.length; index++) {
if (array[index].equals(value)) {
return index;
}
}
return -1;
}
然后你可以像这样执行它......
System.out.println(" --> All-convoYs-9-be:Alert1.");
System.out.println(" Got " + rotationalCipher("All-convoYs-9-be:Alert1.", 4));
System.out.println("Want Epp-gsrzsCw-3-fi:Epivx5.");
System.out.println("");
System.out.println(" --> abcdZXYzxy-999.@");
System.out.println(" Got " + rotationalCipher("abcdZXYzxy-999.@", 200));
System.out.println("Want stuvRPQrpq-999.@");
哪个输出
--> All-convoYs-9-be:Alert1.
Got Epp-gsrzsCw-3-fi:Epivx5.
Want Epp-gsrzsCw-3-fi:Epivx5.
--> abcdZXYzxy-999.@
Got stuvRPQrpq-999.@
Want stuvRPQrpq-999.@
正如我上面所说,你可以只使用
String
而不是数组,在这种情况下它可能看起来更像......
private String digits = "0123456789";
private String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public String rotationalCipher(String input, int rotationFactor) {
int shift = rotationFactor % 26;
String shiftedDigits = rotate(digits, -(rotationFactor % 10));
String shiftCharacters = rotate(characters, -(rotationFactor % 26));
StringBuilder output = new StringBuilder();
for (char character : input.toCharArray()) {
String value = Character.toString(character);
int index = 0;
if ((index = digits.indexOf(value)) > -1) {
output.append(shiftedDigits.charAt(index));
} else if ((index = characters.indexOf(value)) > -1) {
output.append(shiftCharacters.charAt(index));
} else if ((index = characters.indexOf(value.toUpperCase())) > -1) {
output.append(Character.toLowerCase(shiftCharacters.charAt(index)));
} else {
output.append(value);
}
}
return output.toString();
}
public String rotate(String original, int offset) {
if (offset >= 0) {
return positiveRotate(original, offset);
}
return negativeRotate(original, Math.abs(offset));
}
public String positiveRotate(String original, int offset) {
String prefix = original.substring(original.length() - offset);
String suffix = original.substring(0, original.length() - offset);
return prefix + suffix;
}
public String negativeRotate(String original, int offset) {
String prefix = original.substring(offset);
String suffix = original.substring(0, offset);
return prefix + suffix;
}