凯撒密码从输入案例中获得错误的输出

问题描述 投票:0回答:1

我正在使用 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);
java
1个回答
1
投票

检查你的数学

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("");

我在这里作弊了,你可能需要手动创建数组,但我懒得把它写出来。


请注意

  1. 我使用的是
    String
    数组而不是
    char
    数组,不难更改,但我很懒
  2. 实际上,您可以直接在
    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;
}
© www.soinside.com 2019 - 2024. All rights reserved.