2009-03-06 22 views
18

Mã trong câu hỏi với cú pháp nổi bật ở đây: via FriendpasteViệc triển khai một dòng rot13 trong JavaScript của tôi ở đâu sai?

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> 

Như bạn thấy, sử dụng theo đúng nghĩa đen một dòng duy nhất để đính kèm một phương pháp để String đối tượng tạo mẫu la, tôi có phương thức map() mà trước đây tôi đã thiết lập (tôi biết chắc chắn rằng mã đó hoạt động hoàn hảo; nó đơn giản lặp qua từng phần tử trong mảng và áp dụng hàm được chỉ định trong tham số) đi qua từng ký tự trong một chuỗi và làm những gì tôi nghĩ là những tính toán thích hợp để biến chuỗi thành rot13'd. Tôi đã nhầm lẫn. Ai có thể phát hiện ra nơi tôi đã đi sai?

+0

Kết quả không chính xác mà bạn đang nhận được là gì? – Triptych

+0

Ví dụ: 'Bacon'.rot13() sắp ra' Onp | {'khi nó là' Onpba '... –

+0

Vậy làm cách nào để bạn chắc chắn rằng hàm bên trong hoạt động hoàn hảo? – Triptych

Trả lời

3

nên% 26 đến sau + 13?

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

Erm ... hoán đổi chúng xung quanh không thay đổi bất cứ điều gì ... –

+1

thay đổi này chắc chắn sửa chữa một phần của vấn đề – Sparr

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 

Trộn zero-based và các chỉ số cho mất một-based. Tôi đổ lỗi cho Netscape.

64

Bạn có thể sử dụng siêu ngắn:

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

Sửa đổi để kiểm tra tất cả các thối # thối - http://jsfiddle.net/ledlogic/tC7qe/ – ledlogic

+0

@ledlogic Một bảng trông đẹp hơn ;-) http://jsfiddle.net/tC7qe/19/ –

+1

Chỉ cần phát hiện ra rằng mã của bạn đang được sử dụng trên rot13.com bây giờ – Howard

0

Trong khi tôi thực sự như giải pháp RegEx, tôi chủ yếu tiến hành dự án để xem nếu tôi có thể làm cho nó thực hiện. Vui mừng khi thông báo rằng tôi cuối cùng đã quản lý để làm như vậy:

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

Chỉ vì nó thậm chí còn ngắn hơn và cũng dễ hiểu hơn/logic:

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

Điều này là sai. rot13 (rot13 ("messages")) trả về "' essages " – Zibri

+0

Ouch! Cảm thấy xấu hổ, tôi nên làm bài kiểm tra đơn giản này. Chỉ cần chỉnh sửa nhỏ: '<=' thay vì '<'. Bây giờ nó hoạt động tốt! – Herman

+0

'/ [A-z] /' cũng trông giống cá đối với tôi. –

14

này cho kết quả chính xác.

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

@ Hexagon - không có câu trả lời nào được chấp nhận? [Zibri ở đây dường như hoạt động] (http://jsfiddle.net/rufwork/NBUn9/). – ruffin

+0

Từ nhiều câu trả lời ở đây, tôi đã thử cái này đầu tiên và nó hoạt động tốt, nó cũng hoạt động tốt khi kết hợp với 'str_rot13()' của PHP. – DanFromGermany

+0

@ruffin - Điều này không thành công trên chuỗi bao gồm dấu gạch dưới '_' –

4

One-liner nặng trong lúc 116 byte:

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

Cách sử dụng:

r('The Quick Brown Fox Jumps Over The Lazy Dog.');

+0

Mọi thứ trong JavaScript là một lớp lót .... cho đến khi bạn định dạng nó theo cách phù hợp với con người. –

4

Dưới đây là một phiên bản đó là 80 cột, không cập nhật string.prototype , thụt vào và ngắn gọn một cách hợp lý.

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

Và một ví dụ cho thấy nó đang làm việc: giải pháp

rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]') 
"[nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM]" 
rot13(rot13('[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]')) 
"[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]" 
9

Kevin M là nhỏ gọn và thanh lịch. Tuy nhiên, nó có một lỗi nhỏ: biểu thức chính quy được sử dụng với hàm thay thế không giới hạn sự thay thế thành các ký tự chữ cái. Phạm vi ký tự [A-z] bao gồm các ký tự dấu chấm câu ([\]^_ `), sẽ được đổi chỗ cho các chữ cái khi chúng được để một mình.

Phiên bản cố định như sau:

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

Nó vẫn chỉ 116 byte. Đáng chú ý nhỏ và khá thông minh.

(Xin lỗi cho đăng tải câu trả lời đầy đủ, tôi vẫn đang thiếu 50 đại diện cần thiết để đăng bài này như một bình luận cho câu trả lời xuất sắc của Kevin.)

+0

+1 Bắt tuyệt vời Lonnon! Tôi sẽ cập nhật câu trả lời của tôi để phản ánh những thay đổi của bạn. –

1

Dưới đây là một thư viện JavaScript thực hiện thay thư ROT-n: https://github.com/mathiasbynens/rot

thối là thư viện JavaScript thực hiện thay thế chữ quay. Nó có thể được sử dụng để thay đổi bất kỳ chữ cái ASCII nào trong chuỗi đầu vào bởi một số vị trí nhất định trong bảng chữ cái. Để Rot-13 chuỗi 'abc', ví dụ:

// ROT-13 is the default 
rot('abc'); 
// → 'nop' 

// Or, specify `13` explicitly: 
rot('abc', 13); 
// → 'nop' 
2

Vẫn còn chỗ cho tăng cường, kiểm tra (c < = "Z") thực sự là một tấm séc với các điểm mã (mà chúng ta cần sau này) , theo ý tưởng đó cho chúng ta một chiến thắng!

// so với phong cách Kevin M: 115 ký tự (vs 116)
// 102 ký tự với Buffer nodejs (xem dưới đây)

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

// so với phong cách Ben Alpert: 107 ký tự (vs 112)
// 93 chars với Buffer nodejs (xem dưới đây)

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])}) 

// Cùng mã, formated phục vụ sản xuất

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

Trong nút js, bạn có thể sử dụng Bộ đệm để truyền/mã hóa các điểm mã hóa, ví dụ: :

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 
+0

Sử dụng nút bộ đệm Buffer là tổng số WIN 'hàm r (a, b) {return ++ b? Bộ đệm ([((a = Bộ đệm (a) [0]) <91?78:110)> a? A + 13: a-13]) : a.replace (/ [a-zA-Z]/g, r)} ' – 131

+0

Ý tưởng tuyệt vời để sử dụng bộ đệm! –

+0

+1 trên phong cách Ben Alpert cho Nodej. Tôi đã làm một số thử nghiệm hiệu suất nặng trong nodejs và Ben's là rất nhanh và tốt hơn một chút so với phong cách Kevin M. Ngoài ra, không có đệ quy với thuật toán của Ben. –

10

Dưới đây là một giải pháp sử dụng replace, indexOfcharAt chức năng:

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

Mặc dù câu trả lời khác là 'ngắn' (tức là thấp hơn số ký tự), tôi nghĩ rằng câu trả lời này là dễ hiểu .

0

CoffeeScript phiên bản của @ ben-Alpert 's 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 

Hoặc như chức năng:

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' 
1

Đây là không có cách nào cố gắng để cạnh tranh với các công cụ tuyệt vời ở đây, như bạn thấy Tôi không thể bình luận nhưng tôi có nỗ lực mới của riêng tôi để viết điều này trong JS và làm cho nó hoạt động trước khi tôi đọc các giải pháp thanh lịch hơn ở đây - Tôi sẽ chia sẻ nó ở đây.

Tôi đã cố gắng viết nó với indexOf, một switch, bằng cách thêm 13, bởi String.fromCharCode()CharCodeAt(). Họ đã trở nên quá dài - chức năng helper trong vụ việc này là không cần thiết nhưng điều này là ngắn nhất của tôi:)

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

phiên bản golfed của tôi là dài 82 byte (vs.Ben Albert, mà là nặng hơn 35%, nhưng tôi cảm hứng):

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

Sự khác biệt:

  • case-insensitive để bắt chỉ bảng chữ cái tiếng Anh.
  • các chức năng mũi tên mà không cần trả lại và mắc cài.
  • xóa tham số khỏi charCodeAt.
  • kiểm tra mã được mã hóa bằng chuỗi.
  • đang thực hiện + 13-26 = -13.
  • kiểm tra phần trên (&95) so với 77 (78 + 13 = 91, tràn).

tắm: Nếu bạn muốn thực hiện ROT5 trên chữ số, thêm: .replace(/\d/gi,c=>(c>4?-5:5)+c*1)

2

Kết hợp kỹ thuật khác nhau ở đây, tôi đã đưa ra 78 nhân vật hoạt Javascript ES6 chức năng này, trong đó hoạt động trên Node:

rot13=s=>s.replace(/[a-z]/ig,c=>Buffer([((d=Buffer(c)[0])&95)<78?d+13:d-13])); 
Các vấn đề liên quan