28

有问题的代码在此处突出显示语法:通过 Friendpaste

rot13.js:

错误

<script>
String.prototype.rot13 = rot13 = function(s)
 {
    return (s = (s) ? s : this).split('').map(function(_)
     {
        if (!_.match(/[A-Za-z]/)) return _;
        c = Math.floor(_.charCodeAt(0) / 97);
        k = (_.toLowerCase().charCodeAt(0) - 96) % 26 + 13;
        return String.fromCharCode(k + ((c == 0) ? 64 : 96));
     }).join('');
 };
</script>

正如您所看到的,使用非常简单的一行将一个方法附加到 String 对象(一个原型设计),我有一个我之前设置的 map() 方法(我确信该代码可以完美运行;它只是遍历数组中的每个元素并应用参数中指定的函数)遍历字符串中的每个字符并执行我认为正确的计算以将字符串转换为它的 rot13'd 对应物。可悲的是,我错了。谁能发现我哪里出错了?

4

17 回答 17

77

您可以使用超短:

s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
于 2009-03-06T04:32:26.870 回答
20

这是使用replaceindexOf功能的解决方案:

function rot13(s) {
  return s.replace(/[A-Z]/gi, c =>
    "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"[
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(c) ] )
}

这由以下部分组成:

  • /[A-Z]/gi仅匹配字符的正则表达式
  • replace用于替换那些字符
  • 一个写成箭头函数的替换函数
  • indexOf是将字符转换为数字查找索引
  • 我们在替换数组中查找索引,我们就完成了
于 2015-02-13T00:04:39.607 回答
16

这给出了正确的结果。

function rot13(s)
 {
    return (s ? s : this).split('').map(function(_)
     {
        if (!_.match(/[A-Za-z]/)) return _;
        c = Math.floor(_.charCodeAt(0) / 97);
        k = (_.toLowerCase().charCodeAt(0) - 83) % 26 || 26;
        return String.fromCharCode(k + ((c == 0) ? 64 : 96));
     }).join('');
 }
 
 alert(rot13(rot13("Mark this as accepted answer :)")));

于 2013-04-01T17:06:07.437 回答
12

仅仅因为它更短,也更容易理解/合乎逻辑:

function rot13(s) {
  return s.replace( /[A-Za-z]/g , function(c) {
    return String.fromCharCode( c.charCodeAt(0) + ( c.toUpperCase() <= "M" ? 13 : -13 ) );
  } );
}
于 2013-01-27T22:47:11.623 回答
10

Kevin M 的解决方案紧凑而优雅。但是,它有一个小错误:与替换函数一起使用的正则表达式不会将替换限制为字母字符。[A-z]字符范围包括标点符号 ( ),当[\] ^ _ `它们应该单独放置时,它们将被交换为字母。

固定版本如下所示:

function r(a,b){return++b?String.fromCharCode((a<"["?91:123)>(a=a.charCodeAt()+13)?a:a-26):a.replace(/[a-zA-Z]/g,r)}

它仍然只有 116 个字节。非常小而且非常聪明。

(很抱歉发布完整的答案;我仍然缺少 50 个代表来发布此作为对凯文出色答案的评论。)

于 2014-04-26T22:05:11.603 回答
5
var rot13 = String.prototype.rot13 = function(s)
{
  return (s = (s) ? s : this).split('').map(function(_)
  {
    if (!_.match(/[A-Za-z]/)) return _;
    c = _.charCodeAt(0)>=96;
    k = (_.toLowerCase().charCodeAt(0) - 96 + 12) % 26 + 1;
    return String.fromCharCode(k + (c ? 96 : 64));
  }
  ).join('');
};

alert('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.rot13());
yields nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM

混合从零开始和从一开始的指数损失。我责怪网景。

于 2009-03-06T04:31:25.810 回答
5

这是一个 80 列的版本,不更新 string.prototype,缩进良好且相当短。

function rot13(str) {
  return str.replace(/[a-zA-Z]/g, function(chr) {
    var start = chr <= 'Z' ? 65 : 97;
    return String.fromCharCode(start + (chr.charCodeAt(0) - start + 13) % 26);
  });
}

还有一个例子表明它正在工作:

rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]')
"[nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM]"
rot13(rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]'))
"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]"
于 2014-03-13T01:07:13.290 回答
4

116 字节的单行:

function r(a,b){return++b?String.fromCharCode((a<"["?91:123)>(a=a.charCodeAt()+13)?a:a-26):a.replace(/[a-zA-Z]/g,r)}

用法:

r('The Quick Brown Fox Jumps Over The Lazy Dog.');

于 2014-01-05T05:09:35.373 回答
2

仍有改进的空间,检查 (c<="Z") 实际上是对代码点的检查(我们稍后需要),遵循这个想法给了我们胜利!

//与 Kevin M 的风格相比:115 个字符(对 116 个)
//102 个字符与 nodejs 缓冲区(见下文)

function r(a,b){return++b?String.fromCharCode(((a=a.charCodeAt())<91?78:110)>a?a+13:a-13):a.replace(/[a-zA-Z]/g,r)}
//nodejs style
function r(a,b){return++b?Buffer([((a=Buffer(a)[0])<91?78:110)>a?a+13:a-13]):a.replace(/[a-zA-Z]/g,r)}

//与 Ben Alpert 风格相比:107 个字符(对 112 个)
//93 个字符与 nodejs 缓冲区(见下文)

s.replace(/[a-zA-Z]/g,function(a){return String.fromCharCode(((a=a.charCodeAt())<91?78:110)>a?a+13:a-13)});
//nodejs style
s.replace(/[a-zA-Z]/g,function(a){return Buffer([((a=Buffer(a)[0])<91?78:110)>a?a+13:a-13])})

// 相同的代码,为生产而格式化

String.prototype.rot13 = function() {
  return this.replace(/[a-zA-Z]/g, function(a){
    return String.fromCharCode(((a=a.charCodeAt())<91?78:110)>a?a+13:a-13);
  });
}

在 nodejs 中,您可以使用 Buffer 来转换/序列化代码点,例如:

var a=65;
""+Buffer([a])           == "A" // note that the cast is done automatically if needed
String.fromCharCode(a)   == "A"

var b="A";
Buffer(a)[0]             == 65
a.charCodeAt()           == 65
于 2015-01-31T15:23:28.377 回答
2

我打高尔夫球的版本是 82 字节长(与 Ben Albert 相比,它重 35%,但启发了我的):

S.replace(/[a-z]/gi,c=>String.fromCharCode((c=c.charCodeAt())+((c&95)>77?-13:13)))

差异:

  • 不区分大小写以仅捕获英文字母。
  • 没有返回和大括号的箭头函数。
  • 从 charCodeAt 中删除参数。
  • 针对插入字符串的代码进行测试。
  • 做+13-26=-13。
  • 针对 77(78+13=91,溢出)测试大写 ( &95)。

额外:如果要对数字执行 ROT5,请添加: .replace(/\d/gi,c=>(c>4?-5:5)+c*1)

于 2017-01-03T03:03:47.537 回答
2

在这里结合各种技术,我想出了这个 78 个字符的 JavaScript ES6 函数,它适用于 Node:

rot13=s=>s.replace(/[a-z]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-13]));
于 2017-01-13T05:11:54.257 回答
1

这是一个执行 ROT-n 字母替换的 JavaScript 库:https ://github.com/mathiasbynens/rot

rot是一个执行旋转字母替换的 JavaScript 库。它可用于将输入字符串中的任何 ASCII 字母移动字母表中给定数量的位置。对于 ROT-13 字符串'abc',例如:

// ROT-13 is the default
rot('abc');
// → 'nop'

// Or, specify `13` explicitly:
rot('abc', 13);
// → 'nop'
于 2014-06-16T10:39:18.360 回答
1

这绝不是试图与这里的优秀东西竞争,正如你所见,我无法发表评论,但我有自己的新手尝试用 JS 编写它并在我在这里阅读更优雅的解决方案之前让它工作 - 我是将在这里分享。

我试着用indexOf, a switch, 加上 13,String.fromCharCode()和来写它CharCodeAt()。他们变得太长了——这个中的辅助函数是不必要的,但这是我最短的:)

function rot13(string) { 
  var result = '', 
      store,
      str = string.toLowerCase();  

  //helper function
  function strgBreak(a){
    var result = [];
    return result = a.split('');
  }

  //rot13 arrays
  var alphArr = strgBreak('abcdefghijklmnopqrstuvwxyz');
  var inverseArr = strgBreak('nopqrstuvwxyzabcdefghijklm');

 for ( var i = 0; i < str.length; i++ ) {
     if (alphArr.indexOf( str[i] ) !== -1) {
        result += inverseArr[ alphArr.indexOf( str[i] ) ];
    } else result += str[i];
  }
 return result.toUpperCase(); 
}
于 2016-05-26T00:12:29.593 回答
1

这是 ROT13 替换密码的现代方法:

const ROT13 = s =>
  s.replace(/[a-z]/gi, c =>
    String.fromCharCode(c.charCodeAt() + 13 - 26 * /[n-z]/i.test(c)));

console.log(ROT13('The quick brown fox jumps over 13 lazy dogs.'));


上面测试用例的结果是:

Gur dhvpx oebja sbk whzcf bire 13 ynml qbtf。

于 2018-10-25T02:43:37.287 回答
0

虽然我真的很喜欢 RegEx 解决方案,但我主要负责这个项目,看看我是否能完成它。很高兴地报告我终于做到了:

String.prototype.rot13 = rot13 = function(s)
 {
    return (s ? s : this).split('').map(function(_)
     {
        if (!_.match(/[A-za-z]/)) return _;
        c = Math.floor(_.charCodeAt(0) / 97);
        k = (_.toLowerCase().charCodeAt(0) - 83) % 26 || 26;
        return String.fromCharCode(k + ((c == 0) ? 64 : 96));
     }).join('');
 }
于 2009-03-06T16:06:37.013 回答
0

@ben-alpert答案的 CoffeeScript 版本:

string.replace /[a-zA-Z]/g, (c) -> String.fromCharCode if (if c <= 'Z' then 90 else 122) >= (c = c.charCodeAt(0) + 13) then c else c - 26

或作为函数:

ROT13 = (string) -> string.replace /[a-zA-Z]/g, (c) -> String.fromCharCode if (if c <= 'Z' then 90 else 122) >= (c = c.charCodeAt(0) + 13) then c else c - 26
ROT13('asd') # Returns: 'nfq'
于 2015-09-28T19:58:14.760 回答
0

我最喜欢且易于理解的决策 ROT13 版本

function rot13(message) {
  var a = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  var b = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"
  return message.replace(/[a-z]/gi, c => b[a.indexOf(c)])
}

a- 经典字母表,b- 带有第 13 个替换的字典,return简单的 RegEx 替换结果

于 2020-04-15T06:12:28.730 回答