Ответ 1
Вы можете использовать супер-короткое:
s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
Данный код с подсветкой синтаксиса здесь: через 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. Я был грустно ошибался. Кто-нибудь может определить, где я ошибся?
Вы можете использовать супер-короткое:
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('');
}
alert(rot13(rot13("Mark this as accepted answer :)")));
Вот решение, использующее функции replace
и indexOf
:
function rot13(s) {
return s.replace(/[A-Z]/gi, c =>
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"[
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(c) ] )
}
Это состоит из:
/[AZ]/gi
регулярное выражение /[AZ]/gi
для сопоставления только символовreplace
используется для замены этих символовindexOf
- преобразовать символ в числовой индекс поискаПросто потому, что он еще короче, а также более понятный/логичный:
function rot13(s) {
return s.replace( /[A-Za-z]/g , function(c) {
return String.fromCharCode( c.charCodeAt(0) + ( c.toUpperCase() <= "M" ? 13 : -13 ) );
} );
}
Решение 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 представителей, чтобы опубликовать это как комментарий к Кевину.)
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.
Здесь версия, содержащая 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]"
Один вкладыш, который весит 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;
Есть еще место для улучшения, проверка (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
Моя версия для игры в гольф составляет 82 байта (против Бена Альберта, который на 35% тяжелее, но вдохновил мою):
S.replace(/[a-z]/gi,c=>String.fromCharCode((c=c.charCodeAt())+((c&95)>77?-13:13)))
Отличия:
&95
) против 77 (78 + 13 = 91, переполнение).Дополнительно: если вы хотите выполнить ROT5 на цифрах, добавьте:
.replace(/\d/gi,c=>(c>4?-5:5)+c*1)
Объединив различные методы здесь, я придумал эту 78-значную функцию JavaScript ES6, которая работает на Node:
rot13=s=>s.replace(/[a-z]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-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'
Это никоим образом не пытается конкурировать с отличным материалом здесь, поскольку вы видите, что я не могу комментировать, но у меня есть моя собственная попытка начать писать это в 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();
}
Вот современный подход к шифру замены 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.'));
В то время как мне действительно нравится решение 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('');
}
Версия 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'