凯撒密码移位字母问题

huangapple go评论58阅读模式
英文:

Caesar Cipher Shift Letters Issue

问题

I was trying to program a caesar cipher using the technique of converting letter by letter with an ASCII Converter then shift the numbers and convert them again in text but it works only if the letters don't go over the z with the shift.

const checkPunctuation = (text) => {
  return /[.,#!$%^&*;:{}=\-_`~()]/g.test(text);
};

const ASCIIConverter = (text) => {
  return text.split("").map((char) => {
    return checkPunctuation(char) ? char : char.charCodeAt();
  });
};

const caesarCipher = (text, shift) => {
  return ASCIIConverter(text)
    .map((code) => (code + shift) % 26)
    .map((charCode) => String.fromCharCode(charCode))
    .join("");
};
console.log(caesarCipher("pizza!", 2));

Expected: wpggh!

Received: (Box Characters with a mark)

英文:

I was trying to program a caesar cipher using the technique of converting letter by letter with an ASCII Converter then shift the numbers and convert them again in text but it works only if the letters don't go over the z with the shift.

const checkPunctuation = (text) => {
  return /[.,#!$%^&*;:{}=\-_`~()]/g.test(text);
};

const ASCIIConverter = (text) => {
  return text.split("").map((char) => {
    return checkPunctuation(char) ? char : char.charCodeAt();
  });
};

const caesarCipher = (text, shift) => {
  return ASCIIConverter(text)
    .map((code) => (code + shift) % 26)
    .map((charCode) => String.fromCharCode(charCode))
    .join("");
};
console.log(caesarCipher("pizza!", 2));

Expected: wpggh!

Received: (Box Characters with a mark)

答案1

得分: 0

charCodeAt 可能只是返回 ASCII 码中的索引。你需要的是在区间 [0..n) 中的索引,其中 n 在这种情况下是 26。fromCharCode 也有同样的问题,它接收应用 %26 后的小值。通常,你可以通过减去或加上 Aa 的值来将数值转换为正确的范围内。

一般我建议添加方法来将 ASCII 索引转换为字母表中的索引,然后再转回去。这些方法可以单独进行测试。这种高度简洁的代码的问题在于调试困难;在映射“流”中发生了太多事情。

英文:

charCodeAt probably simply returns the index in ASCII. What you need is the index in the range [0..n), where n in this case is 26. Same problem with fromCharCode of course, which receives the tiny values after the %26 is applied. Generally you can subtract / add the value of A or a to get the values into the correct range.

Generally I propose to add methods to convert the ASCII index into the index of the alphabet and back again. Those can be tested separately. The problem with this highly concise code is that it is horrid to debug; too much happens when mapping the values in the "stream".

答案2

得分: 0

代码中的一个问题是不正确地减小了数值。
例如,A的字符代码是65,但变成了20。
如果大小写不重要,您可以使用

String.fromCharCode((charCode - 65)%26 + 65)

这将使数值位于大写字母的正确范围内。

英文:

One problem is that the code is decreasing values incorrectly.
For example, the char code of A is 65 but becomes 20.
If capitalization doesn't matter, you could use

String.fromCharCode((charCode - 65)%26 + 65)

This puts values in the correct range for upper-case letters.

答案3

得分: 0

以下是您要翻译的部分:

  • There are thousands of characters that are not letters and are not in your punctuation regex. It is better to do a check for letters: if it is not a character from the English alphabet, then leave it unaltered.

  • return checkPunctuation(char) ? char : char.charCodeAt() is a bad idea: this means that the mapping is to a mixed type: either string (the original character) or a number (it's code point). This affects the further processing of these values. See next point

  • .map((code) => (code + shift) % 26) expects code to be a number, but it can also be a character (punctuation, see previous point), and then + shift will perform string concatenation and % 26 will produce NaN in that case. This obviously is not what is intended.

  • .map((code) => (code + shift) % 26) results in numbers between 0 and 25 (and NaN), which are not the ASCII codes of letters but of control characters.

  • .map((charCode) => String.fromCharCode(charCode)) will convert control codes (and NaN) to their character representations, which are those boxes you see. You need to add the ASCII code of the letter 'a' back to it before converting to a string.

  • The example call is wrong. A shift of 2 would not give "wpggh!" as result. For that you would need to use a shift of 7 (as "w" occurs 7 letters after the letter "p" in the alphabet).

Here is the proposed correction:

const convertRange = (text, regex, a, shift) =>
  text.replace(regex, letter => 
    String.fromCharCode(
      (letter.charCodeAt() - a.charCodeAt() + shift) % 26 + a.charCodeAt()
    )
  );

const caesarCipher = (text, shift) => {
  text = convertRange(text, /[A-Z]/g, 'A', shift); // Cypher uppercase
  return convertRange(text, /[a-z]/g, 'a', shift); // Cypher lowercase
};

console.log(caesarCipher("pizza!", 7));
英文:

Some issues:

  • There are thousands of characters that are not letters and are not in your punctuation regex. It is better to do a check for letters: if it is not a character from the English alphabet, then leave it unaltered.

  • return checkPunctuation(char) ? char : char.charCodeAt() is a bad idea: this means that the mapping is to a mixed type: either string (the original character) or a number (it's code point). This affects the further processing of these values. See next point

  • .map((code) => (code + shift) % 26) expects code to be a number, but it can also be a character (punctuation, see previous point), and then + shift will perform string concatenation and % 26 will produce NaN in that case. This obviously is not what is intended.

  • .map((code) => (code + shift) % 26) results in numbers between 0 and 25 (and NaN), which are not the ASCII codes of letters but of control characters.

  • .map((charCode) => String.fromCharCode(charCode)) will convert control codes (and NaN) to their character representations, which are those boxes you see. You need to add the ASCII code of the letter 'a' back to it before converting to a string.

  • The example call is wrong. A shift of 2 would not give "wpggh!" as result. For that you would need to use a shift of 7 (as "w" occurs 7 letters after the letter "p" in the alphabet).

Here is the proposed correction:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const convertRange = (text, regex, a, shift) =&gt;
  text.replace(regex, letter =&gt; 
    String.fromCharCode(
      (letter.charCodeAt() - a.charCodeAt() + shift) % 26 + a.charCodeAt()
    )
  );

const caesarCipher = (text, shift) =&gt; {
  text = convertRange(text, /[A-Z]/g, &#39;A&#39;, shift); // Cypher uppercase
  return convertRange(text, /[a-z]/g, &#39;a&#39;, shift); // Cypher lowercase
};

console.log(caesarCipher(&quot;pizza!&quot;, 7));

<!-- end snippet -->

答案4

得分: 0

以下是已翻译的内容:

这是一个工作的凯撒密码函数它只会旋转ASCII字符[A-Z][a-z]

function cc(str,n){
 return str.split("").map(c=>{
  let a=c.charCodeAt(0)-1
  if (a>63&&a<90||a>95&&a<122)
   a=(a%32+n)%26+64+(a>95?32:0)
  return String.fromCharCode(a+1);
 }).join("");
}

console.log(cc("Most fabulous - our Pizzas!",7));
英文:

Here is a working Caesar's Cypher function that will rotate only the ASCII characters [A-Z] and [a-z]:

<!-- begin snippet:js console:true -->
<!-- language:lang-js -->

function cc(str,n){
return str.split("").map(c=>{
let a=c.charCodeAt(0)-1
if (a>63&&a<90||a>95&&a<122)
a=(a%32+n)%26+64+(a>95?32:0)
return String.fromCharCode(a+1);
}).join("");
}

console.log(cc("Most fabulous - our Pizzas!",7));
<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月19日 05:54:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496629.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定