我在JavaScript中的单行实现rot13在哪里出错?

有问题的代码在这里语法突出显示: 通过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()方法(我确信这个代码是完美的,它只是简单的迭代数组中的每个元素并应用参数中指定的函数)遍历string中的每个字符,并执行我认为是正确的计算,以将string转换为它的rot13对应的string。 我很遗憾错误。 任何人都可以发现我出错的地方吗?

你可以使用超短的:

 s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);}); 

这给出了正确的结果。

 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(''); } 

这是一个使用replaceindexOfcharAt函数的解决scheme:

 function rot13(s) { return s.replace(/[A-Za-z]/g, function (c) { return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".charAt( "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm".indexOf(c) ); } ); } 

尽pipe其他答案是“短”(即较less的字符数),我认为这个答案更容易理解。

凯文M的解决scheme是紧凑和优雅。 然而,它有一个小小的错误:与replace函数一起使用的正则expression式不会限制replace为字母字符。 [Az]字符范围包括标点符号( [ \ ] ^ _ ` ),当它们应该单独放置时,将被交换为字母。

固定版本看起来像这样:

 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个代表。)

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

 function rot13(s) { return s.replace( /[A-Za-z]/g , function(c) { return String.fromCharCode( c.charCodeAt(0) + ( c.toUpperCase() <= "M" ? 13 : -13 ) ); } ); } 
 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 

混合零基础和一个基础的指数为失败。 我怪网景。

单线程,重量为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.');

应该是%26在+ 13之后呢?

 k = ((_.toLowerCase().charCodeAt(0) - 96) + 13) % 26; 

这里有一个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]" 

还有增强的空间,检查(c <=“Z”)实际上是对码点的检查(我们稍后需要),随后这个想法给了我们一个胜利!

//对凯文·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)} 

//对比本·阿尔伯特风格: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 

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

rot是一个执行旋转字母replace的JavaScript库。 它可以用来将inputstring中的任何ASCII字母按字母表中的给定位置移位。 以ROT-13string'abc'为例,例如:

 // ROT-13 is the default rot('abc'); // → 'nop' // Or, specify `13` explicitly: rot('abc', 13); // → 'nop' 

这绝不是要在这里与优秀的东西竞争,因为你看到我不能评论,但我有我自己的新手试图写这个在JS中,并得到它的工作之前,我在这里阅读更优雅的解决scheme – 我在这里分享。

我试图用indexOf ,一个switch ,通过添加13, String.fromCharCode()CharCodeAt()来写它。 他们太长了 – 这个帮手的function是不必要的,但这是我最短的:)

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

我的高尔夫版本是82字节长(与本艾伯特,这是重35%,但启发我的):

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

区别:

  • 不区分大小写只抓英文字母。
  • 箭头function没有返回和大括号。
  • 从charCodeAt中删除参数。
  • testingstring内的代码。
  • 做+ 13-26 = -13。
  • testinguppercased( &95 )对77(78 + 13 = 91,溢出)。

Extra:如果你想在数字上执行ROT5,添加: .replace(/\d/gi,c=>(c>4?-5:5)+c*1)

虽然我非常喜欢RegEx解决scheme,但是我主要承担了这个项目,看看能否完成。 很高兴报告,我终于做到了这一点:

 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(''); } 

@ 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 

或者作为function:

 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' 

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

 rot13=s=>s.replace(/[az]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-13]));