Подтвердить что ты не робот

Где моя реализация rot13 в JavaScript идет неправильно?

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

4b9b3361

Ответ 1

Вы можете использовать супер-короткое:

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

Ответ 2

Это дает правильные результаты.

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 :)")));

Ответ 3

Вот решение, использующее функции replace и indexOf:

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

Это состоит из:

  • /[AZ]/gi регулярное выражение /[AZ]/gi для сопоставления только символов
  • replace используется для замены этих символов
  • функция заменителя, написанная как функция стрелки
  • indexOf - преобразовать символ в числовой индекс поиска
  • мы ищем индекс в массиве замены, и мы сделали

Ответ 4

Просто потому, что он еще короче, а также более понятный/логичный:

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

Ответ 5

Решение 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 представителей, чтобы опубликовать это как комментарий к Кевину.)

Ответ 6

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.

Ответ 7

Здесь версия, содержащая 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]"

Ответ 8

Один вкладыш, который весит 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.');

Ответ 9

если% 26 появится после + 13?

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

Ответ 10

Есть еще место для улучшения, проверка (c <= "Z" ) на самом деле является проверкой кода (что нам нужно в дальнейшем), следуя этой идее, дает нам выигрыш!

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

Ответ 11

Моя версия для игры в гольф составляет 82 байта (против Бена Альберта, который на 35% тяжелее, но вдохновил мою):

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

Отличия:

  • нечувствительность к регистру, чтобы уловить только английский алфавит.
  • arrow функции без возврата и фигурных скобок.
  • удалить параметры из charCodeAt.
  • проверить код с строкой.
  • Выполнение + 13-26 = -13.
  • test uppercased (&95) против 77 (78 + 13 = 91, переполнение).

Дополнительно: если вы хотите выполнить ROT5 на цифрах, добавьте: .replace(/\d/gi,c=>(c>4?-5:5)+c*1)

Ответ 12

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

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

Ответ 13

Вот библиотека 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'

Ответ 14

Это никоим образом не пытается конкурировать с отличным материалом здесь, поскольку вы видите, что я не могу комментировать, но у меня есть моя собственная попытка начать писать это в 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(); 
}

Ответ 15

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

Ответ 16

В то время как мне действительно нравится решение 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

Версия CoffeeScript @ben-alpert answer:

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'