我在JavaScript中实现rot13的错误在哪里?

时间:2009-03-06 03:58:20

标签: javascript algorithm rot13

有问题的代码,语法高亮显示在这里:via 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对应物。我很遗憾地错了。任何人都可以找到我出错的地方吗?

18 个答案:

答案 0 :(得分:70)

您可以使用超级短片:

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

答案 1 :(得分: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 :)")));

答案 2 :(得分:15)

以下是使用replaceindexOfcharAt函数的解决方案:

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

尽管其他答案越来越短&#39; (即较低的字符数),我认为这个答案更容易理解。

答案 3 :(得分:11)

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

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

答案 4 :(得分:9)

Kevin M的解决方案紧凑而优雅。但是它有一个小错误:与replace函数一起使用的正则表达式不会将替换限制为字母字符。 [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个代表发布此评论作为Kevin的优秀答案。)

答案 5 :(得分: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

为输入混合零基和一基指数。我责怪Netscape。

答案 6 :(得分: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]"

答案 7 :(得分: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.');

答案 8 :(得分:3)

%26应该在+ 13之后吗?

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

答案 9 :(得分:2)

仍然有增强的空间,检查(c&lt; =“Z”)实际上是对码点的检查(我们稍后需要),遵循这个想法让我们获胜!

//与Kevin M的风格:115个字符(vs 116)
//带有nodejs缓冲区的102个字符(见下文)

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个字符(vs 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

答案 10 :(得分:2)

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

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

答案 11 :(得分: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。
  • 测试大写(&95)对77(78 + 13 = 91,溢出)。

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

答案 12 :(得分: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'

答案 13 :(得分: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。

答案 14 :(得分:1)

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

我尝试使用indexOfswitchString.fromCharCode()CharCodeAt()添加13。它们太长了 - 这个中的辅助函数是不必要的,但这是我最短的:)

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

答案 15 :(得分:0)

@ ben-alpert的answer的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'

答案 16 :(得分: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('');
 }

答案 17 :(得分: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替换符