I have trouble understanding this simple method for encrypting characters in a string. So here's the method:
encryptedChar = (char) (’A’ + (originalChar -’A’ + offset) % 26);
I don't understand the need for 'A' - 'A' since they just cancel out. What is the reason behind it?
Why shouldn't I just use the following method?
encryptedChar = (char) ((originalChar + offset) % 26);
Shouldn't it work exactly the same?
encryptedChar = (char) ('A' + (originalChar -'A' + offset) % 26);
The two 'A' don't cancel each other, since the second one is inside the expression that is the operand of the modulus operator.
'A' + (originalChar -'A' + offset) % 26 - here each letter is mapped to a different letter.
((originalChar + offset) % 26) - here each letter is mapped to a character whose int value is between 0 and 25.
Related
I am wondering how do you convert from a double without a fractional part to a hexaicosadecimal string? What are some methods for converting and are there short cuts?
As far as I understood it is a base 26 conversion to letters only, with a prefix "c". Not sure on the sign for a negative- number.
One "shortcut" would be to take the standard base 26 conversion.
Arguably doing the conversion oneself is just as easy, and would certainly give
a better note in homework.
static String hexaicosadecimal(double x) {
long n = (long)x;
String base26 = Long.toString(n, 26); // 0..9a.p
return "c" + base26.codePoints()
.map(cp -> '0' <= cp && cp <= '9' ? 'A' + (cp - '0')
: 'a' <= cp && cp < 'a' + 16 ? 'A' + 10 + (cp - 'a')
: cp) // '-'
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString();
}
I am Confused as to why this returns 1;
(char)('0' + 11) = ; why?
Full code below where ending = 1;
char[] ending;
char a = (char)('0' + 11/10);
ending = new char[]{a, (char)('0' + 11)};
System.out.println(ending);
Char value of '0' is 48.
48 + 11 = 59
Char value of 59 is ';'.
You can check char values in integer value in any ASCII Character Set in internet.
In Java, char can be use as a int, short, byte, long with values between 0 and 65535 without any casting.
A better explanation is found in: Java char is also an int?
You are assigning '1' to variable a. '0' + 11/10 => '0' + 1
You are assigning a two letter string to endings. Le first letter is a ('1') the second is a semi colon. ('0' + 11).
The code below encrypts a word or sentence in the way Caesar did. You put the shift value and the program takes each letter of the word/sentence and "moves" in the alphabet acoording to the shift (key) value. But this is not the problem.
I found the code on the internet and i cannot explain some of it's lines.
I know how it works but i need some specific answer about some of it's lines.
Here is the code:
import acm.program.*;
public class CaesarCipher extends ConsoleProgram {
public void run() {
println("This program implements a Caesar cipher.");
int key = readInt("Character positions to shift: ");
String plaintext = readLine("Enter a message: ");
String ciphertext = encodeCaesarCipher(plaintext, key);
println("Encoded message: " + ciphertext);
}
private String encodeCaesarCipher(String str, int key) {
if (key < 0) key = 26 - (-key % 26);
String result = "";
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (Character.isLetter(ch)) {
if (Character.isUpperCase(ch)) {
ch = (char) ('A' + (ch - 'A' + key) % 26);
}
else {
ch = (char) ('a' + (ch - 'a' + key) % 26);
}
}
result += ch;
}
return result;
}
}
What exactly do those lines mean, and how do they do what they do?
ch = (char) ('A' + (ch - 'A' + key) % 26);
and
ch = (char) ('a' + (ch - 'a' + key) % 26);
Those two lines behave identically, except for the fact that one applies to uppercase, and one to lowercase. I'll explain the uppercase operations here. Keep in mind that these char values are treated as ints until step 6 below.
ch = (char) ('A' + (ch - 'A' + key) % 26);
ch - 'A' gives the initial character's int offset from capital-A.
ch - 'A' + key increases the offset by key, creating the ciphered character's offset from capital-A.
(ch - 'A' + key) % 26: the modulo here ensures that the numeric value of the ciphered character is 0-25 (for the 26 letters in the alphabet), preventing alphabet "overflow." The value of that expression is now the normalized offset of the ciphered character from capital-A.
'A' + (ch - 'A' + key) % 26 adds the ciphered character's offset from capital-A to capital-A itself, resulting in the ciphered character's int value.
(char) ('A' + (ch - 'A' + key) % 26) casts that int to char type, resulting in the ciphered character as a char.
This code treats the beginning of the alphabet (capital-A) as the "starting point," from which each letter's offset is measured. The offset is the character's number of letters from 'A'.
Example: To cipher "E" with a key of 6:
Find the number of letters between "E" and capital-A. The ASCII code of A is 65, and the code of E is 69. To find E's offset from A, subtract 69 - 65 = 4.
Add the offset and the key: 4 + 6 = 10. This is the number of letters from A the ciphered character will be.
10 % 26 = 10 (no effect because of the small starting letter + small key)
'A' + 10 = 65 + 10 = 75 results in the ASCII code of the ciphered character, 75 ('K')
Casting 75 to char allows it to be treated as a character, rather than an int.
It is converting the character to the ASCII equivalent, as denoted by the + operator (you cannot add characters, only numbers), then changing the character by a certain number of values. The (char) is casting (converting) the result back to a character so you can assign it to ch.
'A's ASCII value is 65, and ch is the character currently being evaluated at position i in the string. ch = (char) ('A' + (ch - 'A' + key) % 26); evaluates as '65 + (character's ASCII number - 65 + key) % 26'. This result is then cast back to a character and assigned to ch. The modulo (%) operator takes a number, divides it by a second number, in this case 26, and returns the remainder (5 % 6 is 5, while 7 % 3 is 1). The second statement works the same way, but uses lowercase 'a' (97) instead of capital 'A'.
See this page for ASCII keys: http://www.asciitable.com/
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
can someone maybe tell me what this particular lines are doing the result = result line and the one after it, i need a explanation of these two lines. Dont understand it clearly. Got it from the internet.
here is the full code
static String vigencrypt(String plain, final String key)
{
String result = "";
plain = plain.toUpperCase();
int length = plain.length();
for (int i = 0, j = 0; i < length; i++)
{
char chr = plain.charAt(i);
if (chr < 'A' || chr > 'Z') continue;
result = result +(char)((chr + key.charAt(j) - 2 * 'A') % 26 + 'A');
j = ++j % key.length();
}
return result;
}
Dont understand what these two lines do is someone can help me
result = result +(char)((chr + key.charAt(j) - 2 * 'A') % 26 + 'A');
j = ++j % key.length();
Let's go through this by line:
result = result + // Concatenate the current string in result with
(char)((chr + key.charAt(j) - 2 * (65)) % 26 + 'A'); // this guy
Let's break down that part, starting with turning A into its decimal representation of 65 (these operations will convert the chars to ints - see this answer):
(char)((chr + key.charAt(j) - 2 * (65)) % 26 + (65));
Becomes
(char)((plain.charAt(i) + key.charAt(j) - 130) % 26 + 65);
So, it's adding the value of the current plain text character to the value of the current key character. Let's say the characters are both z - this gives us
(char)((z + z - 130) % 26 + 65)
Now replace the zs with their decimal representations
(char)((122 + 122 - 130) % 26 + 65)
(char)(114 % 26 + 65)
(char)(10 + 65)
(char)(75)
'K'
What if it happens to be the other end of the letter range ( 'A' == 65 again)?
(char)((65 + 65 - 130) % 26 + 65)
(char)(0 % 26 + 65)
(char)(0 + 65)
(char)(65)
'A'
Other character combinations will encode as other characters.
(char)(('z' + 'A' - 130) % 26 + 65)
(char)((122 + 65 - 130) % 26 + 65)
(char)(57 % 26 + 65)
(char)(5 + 65)
(char)(70)
'F'
So, the first line in question is adding the next plain text character (at index i) to the next key character (at index j, which loops if there is more plaintext than key chars). It subtracts 130 (I'm not sure why - maybe to ensure it's on the standard ASCIIcode page?), then does modulo 26 and adds 65 to ensure it will output a character from A-Z, caps only. This result is appended to the previous results.
As for the second line, that's where we determine the index of the next key character. It will move up one character, while the modulo ensures that the index will loop back to the beginning rather than going beyond the key length. It might be easier to think of it as
j = (1 + j);
if (j >= key.length()) {
j = 0;
}
I've reading this question, and I was wondering if Is there any way to consider the whole range of characters? For example, "á", "é", "ö", "ñ", and not consider " " (the [Space])? (For example, my String is "Hello World", and the standard result is "Khoor#Zruog"; I want to erase that "#", so the result would be "KhoorZruog")
I'm sure my answer is in this piece of code:
if (c >= 32 && c <= 127)
{
// Change base to make life easier, and use an
// int explicitly to avoid worrying... cast later
int x = c - 32;
x = (x + shift) % 96;
chars[i] = (char) (x + 32);
}
But I've tried some things, and it didn't work.
See this pseudocode - should be trivially implementable:
// you need to define your own range, obviously - it's not at all obvious whether
// e.g. "ź" should be included and that it should come after "z"
array char_range = ['a','á','b','c','č', (...), 'z','ź','ž']
// the text to encode
string plaintext = 'some text here'
// this will contain encoded text
stringbuilder ciphertext = ''
// the classic Caesar Cipher shifts by 3 chars to the right
// to decipher, reverse the sign
int shift_by = 3
// note: character != byte, esp. not in UTF-8 (1 char could be 1 or more bytes)
for each character in plaintext
get character_position of character in char_range // e.g. "a" would return 0
if not in char_range // e.g. spaces and other non-letters
do nothing // drop character
// alternately, you can append it to ciphertext unmodified
continue with next character
add shift_by to character_position
if character_position > char_range.length
character_position modulo char_range.length
if character_position < 0 // useful for decoding
add char_range.length to character_position
get new_character at character_position
append new_character to ciphertext
done
The Space as the ASCII Code 32 which you don't filter out. You could try:
if (c >= 33 && c <= 127)
{
// Change base to make life easier, and use an
// int explicitly to avoid worrying... cast later
int x = c - 32;
x = (x + shift) % 96;
chars[i] = (char) (x + 32);
}
I just changed the 32 with a 33 in your if-Clause so that the spaces are simply ignored.
You could use this. It will check for you it the given int value represents a literal.
Character
So your function could look like this:
if (Character.isLiteral(c) )
{
// Change base to make life easier, and use an
// int explicitly to avoid worrying... cast later
int x = c - Character.MIN_VALUE;
x = (x + shift) % Character.MAX_VALUE;
chars[i] = (char) (x + Character.MIN_VALUE);
}