1

我尝试实现 Rot13 并使其尽可能小,这是我迄今为止的结果:

    if ( (c >= 'A') && (c <= 'Z') ) 
        c=((c-'A'+13)%26)+'A';

    if ( (c >= 'a') && (c <= 'z') )
        c=((c-'a'+13)%26)+'a';

    return c;

我把这个给我的教授看了,他说可以分两行。我不知道如何进一步缩小此代码而不产生错误的输出。

谢谢你的帮助

编辑:如果没有任何改变(外部范围 ascii),它应该只返回 c。也许解决方案是第二个答案 + 返回行 c 以防万一没有返回。

4

6 回答 6

3

你不需要更新c;只需返回:

if ((c >= 'A') && (c <= 'Z')) {
    return ((c - 'A' + 13) % 26) + 'A';
}

if ((c >= 'a') && (c <= 'z')) {
    return ((c - 'a' + 13) % 26) + 'a';
}

我还使代码更具可读性。

这可以很容易地分成两行:

if ((c >= 'A') && (c <= 'Z')) return ((c - 'A' + 13) % 26) + 'A';
if ((c >= 'a') && (c <= 'z')) return ((c - 'a' + 13) % 26) + 'a';

或者一个:

if ((c >= 'A') && (c <= 'Z')) return ((c - 'A' + 13) % 26) + 'A'; if ((c >= 'a') && (c <= 'z')) return ((c - 'a' + 13) % 26) + 'a';

但当然,这可读性要差得多,而且不是一个好主意。

于 2014-01-02T16:48:42.383 回答
3

一条线:

return (c < 'a') ? ((c - 'A' + 13) % 26) + 'A' : ((c - 'a' + 13) % 26) + 'a';

这只是利用了在 ASCII 和 UTF-8 中小写字母在大写字母之后的事实。当然,它不会以任何方式验证输入。

于 2014-01-02T16:50:45.773 回答
3

使用 ASCII 表有一个小技巧。大写和小写字符仅相差一位。所以你可以一次处理它们。看看这个:

A = 0100 0001     M = 0100 1101
a = 0110 0001     m = 0110 1101

所以,我认为这应该有效:

if (Character.isLetter(c))
   return (char) ((((c & 0b01011111) - 'A' + 13) % 26 + 'A') | (c & 0b00100000));
return c;

解释:

  1. c & 0b01011111把 char 变成大写。
  2. - 'A' + 13转换为基于 0 的 int 并应用偏移量。
  3. % 26 + 'A'取模并使其返回一个字符。
  4. (c & 0b00100000)获取指示 char 是否为小写的位。
  5. |将该位添加回结果以使其小写(如果是)。

您可以在此处使用条件运算符使其成为单行符:

return Character.isLetter(c) ? (char) ((((c & 0b01011111) - 'A' + 13) % 26 + 'A') | (c & 0b00100000)) : c;

用十进制 int 文字替换 binary 和 char 文字后,您会得到:

return Character.isLetter(c) ? (char) ((((c & 95) - 52) % 26 + 65) | (c & 32)) : c;

消除空格和一些额外的括号给出:(65个字符

return Character.isLetter(c)?(char)((((c&95)-52)%26+65)|c&32):c;

恕我直言,如果涉及打高尔夫球,这是一场胜利。这当然是不可读的。


演示:是的,已确认。它有效:http: //ideone.com/l6xYy6

输出摘录:

= -> =
> -> >
? -> ?
@ -> @
A -> N
B -> O
C -> P
D -> Q

更进一步:

W -> J
X -> K
Y -> L
Z -> M
[ -> [
\ -> \
] -> ]
^ -> ^
_ -> _
` -> `
a -> n
b -> o
c -> p
d -> q
于 2014-01-02T16:56:55.833 回答
2

比 Sibbo 的回答更正确。如果 c 不在这两个范围内,则返回原样。并在 1 行。

return ((c >= 'A') && (c <= 'Z')) ? ((c-'A'+13)%26)+'A'
                                 :((c >= 'a') && (c <= 'z') ? ((c-'a'+13)%26)+'a'
                                                                  : c);
于 2014-01-02T16:54:22.617 回答
1

更短并且(也许)更容易阅读的是

char a = c < 'a' ? 'A' : 'a';
return (c - a + 13) % 26 + a;

请注意,此解决方案与之前的一些答案一样,不检查输入。此外,在 Java 中,此代码返回一个 int,而不是 char,因此如果包含它的方法返回一个 char,则需要进行强制转换。

如前所述,我还想强调最短的不一定是最好的。编写可读的代码。

于 2019-08-01T13:59:43.653 回答
0

好吧,如果我们要简短易读;

return (c&~32) >= 'A' && (c&~32) <= 'Z' ? ((c&31) + 12) % 26 + (c&~31) + 1 : c;
于 2014-01-02T18:19:33.637 回答