Où est-ce que mon implémentation en une seule ligne de rot13 en JavaScript va mal?
Code en question avec la syntaxe surlignée ici:par 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>
comme vous pouvez le voir, en utilisant littéralement une seule ligne pour attacher une méthode à L'objet String a la prototyping, j'ai une méthode map() que j'ai déjà mise en place (je sais avec certitude que ce code fonctionne parfaitement; c'est simplement itérer sur chaque élément du tableau et appliquer la fonction spécifiée dans le paramètre) passer sur chaque caractère dans une chaîne et faire ce que je pensais être les bons calculs pour transformer la chaîne en son pendant rot13. J'ai été malheureusement erronée. Quelqu'un peut-il endroit où je suis allé mal?
16 réponses
Vous pouvez utiliser le super-court:
s.replace(/[a-zA-Z]/g,function(c){return String.fromCharCode((c<="Z"?90:122)>=(c=c.charCodeAt(0)+13)?c:c-26);});
Cela donne des résultats corrects.
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('');
}
Voici une solution en utilisant replace
,indexOf
et charAt
fonctions:
function rot13(s) {
return s.replace(/[A-Za-z]/g, function (c) {
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".charAt(
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm".indexOf(c)
);
} );
}
bien que d'autres réponses soient "plus courtes" (c.-à-d. moins de caractères), je pense que cette réponse est plus facile à comprendre.
la solution de Kevin M est compacte et élégante. Il a une petite erreur: l'expression régulière utilisée avec la fonction replace ne limite pas la substitution de caractères alphabétiques. [A-z]
la plage de caractères comprend les caractères de ponctuation ([
\
] ^ _ `
), qui seront échangées contre des lettres alors qu'elles devraient être laissées seules.
la version corrigée ressemble à ceci:
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)}
il ne reste que 116 octets. Remarquablement petit et tout à fait intelligent.
(Désolé pour la réponse complète de la mutation; je suis toujours en manque de la de 50 répétitions nécessaires à la poste comme un commentaire de Kevin excellente réponse.)
Juste parce que c'est encore plus court et plus compréhensible/logique:
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
Mélange de base zéro et les indices pour le perdre. Je blâme Netscape.
Voici une version de 80 colonnes, qui ne met pas à jour la chaîne de caractères.prototype, bien dentelé et assez court.
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);
});
}
Et un exemple montrant qu'il est de travail:
rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]')
"[nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM]"
rot13(rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]'))
"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]"
One-liner qui pèse 116 octets:
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)}
Utilisation:
r('The Quick Brown Fox Jumps Over The Lazy Dog.');
le % 26 devrait-il venir après le + 13?
k = ((_.toLowerCase().charCodeAt(0) - 96) + 13) % 26;
il y a encore de la place pour l'amélioration, la vérification (c< = "Z") est en fait une vérification par rapport au codepoint (que nous aurons besoin plus tard), suite à cette idée nous donne une victoire !
//versus Kevin M style : 115 caractères (vs 116)
// 102 caractères Avec tampon nodejs (voir ci-dessous)
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)}
//versus Ben Alpert style: 107 chars (vs 112)
// 93 caractères Avec tampon nodejs (voir ci-dessous)
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])})
/ même code, formaté pour la production
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);
});
}
dans nodejs, vous pouvez utiliser Buffer pour lancer/sérialiser les codépoints, par exemple:
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
Mon ont joué au golf version est de 82 octets de long (contre Ben Albert, qui est 35% plus lourd, mais qui l'a inspiré le mien):
S.replace(/[a-z]/gi,c=>String.fromCharCode((c=c.charCodeAt())+((c&95)>77?-13:13)))
Différences:
- casse à attraper alphabet anglais.
- fonctions flèche sans retour et Attelles.
- supprimer les paramètres de charCodeAt.
- test contre code insté de chaîne.
- faire + 13-26=-13.
- test en majuscules (
&95
) contre 77 (78+13=91, débordement).
Extra: si vous voulez effectuer ROT5 sur les chiffres, ajouter:
.replace(/\d/gi,c=>(c>4?-5:5)+c*1)
en combinant différentes techniques ici, j'ai créé cette fonction ES6 JavaScript de 78 caractères, qui fonctionne sur Node:
rot13=s=>s.replace(/[a-z]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-13]));
rot est une bibliothèque JavaScript qui effectue la substitution de lettres par rotation. Il peut être utilisé pour déplacer n'importe quelles lettres ASCII dans la chaîne de caractères d'entrée par un nombre donné de positions dans l'alphabet. À ROT-13, la chaîne
'abc'
par exemple:// ROT-13 is the default rot('abc'); // → 'nop' // Or, specify `13` explicitly: rot('abc', 13); // → 'nop'
ce n'est en aucun cas essayer de rivaliser avec l'excellent truc ici, comme vous voyez, je ne peux pas commenter, mais j'ai ma propre tentative novice d'écrire ceci dans JS et de le faire fonctionner avant que je lise des solutions plus élégantes ici - je vais le partager ici.
j'ai essayé de l'écrire avec indexOf
, un switch
, en ajoutant 13, par String.fromCharCode()
et CharCodeAt()
. Ils ont été trop longtemps - la fonction d'assistance de celui-ci est inutile, mais c'était mon plus court : )
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();
}
Tandis Que I vraiment comme la solution RegEx, j'ai principalement entrepris le projet pour voir si je pouvais le faire. Heureux d'annoncer que j'ai enfin réussit à le faire:
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('');
}
version CoffeeScript de @ben-alpert 's réponse:
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
Ou comme fonction:
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'