Где моя реализация rot13 в JavaScript идет неправильно? - PullRequest
24 голосов
/ 06 марта 2009

Код с подсветкой синтаксиса здесь: через 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. Я был грустно ошибался. Кто-нибудь может определить, где я ошибся?

Ответы [ 17 ]

2 голосов
/ 13 января 2017

Комбинируя здесь различные приемы, я создал 78-символьную функцию JavaScript ES6, которая работает на Node:

rot13=s=>s.replace(/[a-z]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-13]));
2 голосов
/ 31 января 2015

Есть еще возможности для улучшения, проверка (c

// против стиля Кевина М: 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
1 голос
/ 25 октября 2018

Вот современный подход к шифру замены 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.'));

Результат теста выше:

Гур dhvpx oebja sbk whzcf bire 13 год qbtf.

1 голос
/ 26 мая 2016

Это ни в коем случае не является попыткой конкурировать с превосходными вещами здесь, как вы видите, я не могу комментировать, но у меня есть собственная попытка новичка написать это в JS и заставить ее работать, прежде чем я прочитаю более элегантные решения здесь - Я собираюсь поделиться этим здесь.

Я пытался написать это с indexOf, 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(); 
}
1 голос
/ 16 июня 2014

Вот библиотека JavaScript, которая выполняет замену букв ROT-n: 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'
0 голосов
/ 28 сентября 2015

CoffeeScript-версия @ ben-alpert 's ответа :

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'
0 голосов
/ 06 марта 2009

Хотя мне действительно нравится решение 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('');
 }
...