explanation what code are doing [closed] - java

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

Related

Difference between these two "methods" for simple character encryption

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.

Matrix encoding implementation in the F5 steganography algorithm is unclear

I need to implement my own F5 algorithm. I have read the F5 documentation and the paper can be found here.
In the section 6.2 Matrix Encoding of the paper, equations 16-18 define the change density, D(k), the embedding rate, R(k) and the efficiency rate, W(k), as follows:
D(k) = 1 / (n + 1) = 1 / 2**k
R(k) = k / n = k / (2**k - 1)
W(k) = R(k) / D(k) = k * 2**k / (2**k - 1)
Where n is the number of modifiable places in a code word and k the number of embedding bits. W(k) indicats the average number of bits we can embed per change.
In the source code we find the number of bits as stated below. Can someome please explain why usable and changed are calculated this way? I simply don't understand the logic.
int _changed = 0;
int _expected = 0;
int _one = 0;
int _large = 0;
int _zero = 0;
for (i = 0; i < coeffCount; i++) {
if (i % 64 == 0) {
continue;
}
if (coeff[i] == 1) {
_one++;
}
if (coeff[i] == -1) {
_one++;
}
if (coeff[i] == 0) {
_zero++;
}
}
_large = coeffCount - _zero - _one - coeffCount / 64;
_expected = _large + (int) (0.49 * _one);
for (i = 1; i < 8; i++) {
int usable, changed, n;
n = (1 << i) - 1;
usable = _expected * i / n - _expected * i / n % n;
changed = coeffCount - _zero - coeffCount / 64;
changed = changed * i / n - changed * i / n % n;
changed = n * changed / (n + 1) / i;
//
changed = _large - _large % (n + 1);
changed = (changed + _one + _one / 2 - _one / (n + 1)) / (n + 1);
usable /= 8;
if (usable == 0) {
break;
}
if (i == 1) {
System.out.print("default");
} else {
System.out.print("(1, " + n + ", " + i + ")");
}
System.out.println(" code: " + usable + " bytes (efficiency: " + usable * 8 / changed + "." + usable * 8
/ changed % 10 + " bits per change)");
}
coeff is an array that holds the DCT coefficients,coeffCount is the number of DCT coefficients,_large is the teoretical number of bits from the image that can be encoded and expected is the expected capacity of the image(with shrinkage).I don't understand what is the logic behind usable and changed variables
The last paragraph of the section 6.2 in the paper says the following and I quote:
We can find an optimal parameter k for every message to embed and every
carrier medium providing sufficient capacity, so that the message just fits into the
carrier medium. For instance, if we want to embed a message with 1000 bits into
a carrier medium with a capacity of 50000 bits, then the necessary embedding
rate is R = 1000 : 50000 = 2 %. This value is between R(k = 8) and R(k = 9) in
Table 1. We choose k = 8, and are able to embed 50000 : 255 = 196 code words
with a length n = 255. The (1, 255, 8) code could embed 196 · 8 = 1568 bits. If
we chose k = 9 instead, we could not embed the message completely.
I believe this should be straightforward. If you can understand this, you can follow the steps below.
One more preliminary thing is the expression result = var - var % n; throughout the code. This means you make var exactly divisible by n by removing the remainder (modulo operation). Now onto the loop block.
n = 1 << i - 1
This is the code word length, as defined in the paper.
usable = _expected * i / n - _expected * i / n % n;
To understand this line, remember that i / n is the embedding rate, R(i). In simple words, the number of possibly available bits (_expected) times the embedding rate (i / n), gives the number of bit we can encode. In the example from the quote that's 50000 / 255 * 8 = 1568 bits.
changed = coeffCount - _zero - coeffCount / 64;
changed = changed * i / n - changed * i / n % n;
changed = n * changed / (n + 1) / i;
The first line says that the number of bits that we can go through (call this total) is the number of coefficients (coeffCount), while skipping any zeros and the DC component of each 8x8 block (coeffCount / 64). Each 8x8 block has 64 coefficients, but only one is the DC coefficient, so every 64 coefficients you have one more DC coefficient to skip.
The second and third lines go together. Notice than in the second line you multiply by the embedding rate and you make that result perfectly divisible by the code word length. In the third line you divide by the embedding rate, thereby cancelling the previous step, and then you multiply by the change density, 1 / (n + 1), to find the number of bits to be changed on average.
The reason you go through this whole process is because the order of divisions and multiplications matter. As a straightforward example, consider you have 150 bits and 7 items that you want to distribute evenly into as many bits as possible. How many bits will you need overall?
7 * (150 / 7) = 7 * 21 = 147
Note: The following lines overwrite the currently computed value of changed. The previous 3 lines and the following 2 independently tend to give similar answers when I make up my own _one, _zero, coeffCount values. One of these two versions may be old code which was not removed. Regardless, the logic is the following.
changed = _large - _large % (n + 1);
changed = (changed + _one + _one / 2 - _one / (n + 1)) / (n + 1);
The first line has to do with the change density, D(i), since you make the expression perfectly divisible by n + 1. Because of how _large is defined, this is similar to how changed is computed in the previous version.
_large = coeffCount - _zero - _one - coeffCount / 64;
Which bears close resemblance to this
changed = coeffCount - _zero - coeffCount / 64;
The next line is a little bit hazy to me, but this is what it seems to achieve. It reintroduces back the _one it substracted in _large and one half of the ones. This is due to shrinkage, since it replicates the idea in _expected = _large + int(0.49*_ones). I don't quite understand why you would substract ones / (n + 1), but multiplying this whole expression by the change density, 1 / (n + 1), you get the number of bits you expect to change.
Conclusion
The two ways for calculating the expected number of bits to change are not exact and it has to do with not knowing in advance exactly how many will be changed. They both seem to give similar results for given values of _zero, _one and coeffCount. None of this is really necessary as it just estimates the efficiency for different k as in the quote. You just need to find the maximum k for which you use as much of the carrier medium to embed your information. This is done by just calculating usable and breaking the loop as soon as you don't have enough bits to embed your message. And this exact thing is done a bit further down in the source code.

Caeasar Cipher with java's acm

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/

Hex to Decimal Conversion Issue

first post here. I have an assignment to convert from hex to decimal, including other conversions but this one has me stumped...
So the hex values I need to convert are 12345678, 2A3DF8A7, 00FF00FF. 00FF00FF works fine, it's the number values that are giving me trouble.
I know you're supposed to multiply the digit by 16^n, but for some reason I'm getting values that are way too high even though I think I am doing it right. Obviously not since it's not working. Help would be greatly appreciated!
My code has changed throughout the last hour messing with it, but it's the last "else" now that is the problem.
public void toDec()
{
dec = 0;
for (int j = 0, i = 7; j < hex.length(); j++){
if (hex.charAt(j) == 'A') {
dec += (10 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == 'B') {
dec += (11 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == 'C') {
dec += (12 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == 'D') {
dec += (13 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == 'E') {
dec += (14 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == 'F') {
dec += (15 * (int)Math.pow(16, i));
}
else if (hex.charAt(j) == '0') {
dec = dec;
}
else {
dec += ((int)hex.charAt(j)) * ((int)Math.pow(16, i));
}
i--;
}
}
Casting char to an int is the problem here - instead of int value, representing specific digit, you get char code.
Just give it a try: System.out.println((int) '5');
The easiest way to solve that would be (hex.charAt(j) - '0').
Your problem is in your else clause, handling the digits 1 to 9.
The problem is that you're confusing the digits with the characters representing them. For example, the digit 1 is represented by the character '1', which has a character code of 49. So, when you cast a '1' character to int in your else clause (i.e. (int)hex.charAt(j)), what you get back is it's character code of 49, not 1.
Now, the easy (and idiomatic) way to fix this is to use integer math on your characters. For example, use hex.charAt(j) - '0' instead of (int)hex.charAt(j). This works because the characters '0' through '9' are assigned consecutive character codes 48 through 57, so (for example) subtracting the character code for '0' (which is 48) from the character code for '1' (which is 49) returns the actual digit value, since 49 - 48 = 1. The same works for the other digits, too: '5' - '0' is equivalent to 53 - 48, which is (of course) equal to 5.
Even better, the same approach also works for your other hexadecimal characters too! For example, if you do 'C' - 'A' + 10, you'll get the result 12 (which is the hexadecimal value of the letter C).

Check if string is following ISBN-13 in Java

Im trying to check if a string (important that it is a string) that im reading is correct accoring to the rules of ISBN-13. I found a formula
For example, the ISBN-13 check digit of 978-0-306-40615-?
is calculated as follows:
s = 9×1 + 7×3 + 8×1 + 0×3 + 3×1 + 0×3 + 6×1 + 4×3 + 0×1 + 6×3 + 1×1 + 5×3
= 9 + 21 + 8 + 0 + 3 + 0 + 6 + 12 + 0 + 18 + 1 + 15
= 93
93 / 10 = 9 remainder 3
10 – 3 = 7`
My problem is i don't know how to multiply one number with 1 and every other with 3 ? Im guessing a for-loop but i don't know how to start.
You could "simply" use regular expressions:
ISBN(-1(?:(0)|3))?:?\x20+(?(1)(?(2)(?:(?=.{13}$)\d{1,5}([ -])\d{1,7}\3\d{1,6}\3(?:\d|x)$)|(?:(?=.{17}$)97(?:8|9)([ -])\d{1,5}\4\d{1,7}\4\d{1,6}\4\d$))|(?(.{13}$)(?:\d{1,5}([ -])\d{1,7}\5\d{1,6}\5(?:\d|x)$)|(?:(?=.{17}$)97(?:8|9)([ -])\d{1,5}\6\d{1,7}\6\d{1,6}\6\d$)))
You have 6 pairs of (even,odd) numbers, so go through them pairwise.
for (i = 0; i < 6; i++) {
even += array[2*i];
odd += array[2*i+1]*3;
}
checkbit = 10 - (even+odd)%10;
assuming your inputString is ascii:
int odd = 0;
int even = 0;
char[] c = (inputString + "00").replaceAll("[\\-]", "").toCharArray();
for (int i = 0; i < (c.length - 1) / 2; ++i) {
odd += c[2 * i] - 48;
even += c[2 * i + 1] - 48;
}
int result = 10 - (odd + 3 * even) % 10;
This seems to work effectively and is clear.
// Calculates the isbn13 check digit for the 1st 12 digits in the string.
private char isbn13CheckDigit(String str) {
// Sum of the 12 digits.
int sum = 0;
// Digits counted.
int digits = 0;
// Start multiplier at 1. Alternates between 1 and 3.
int multiplier = 1;
// Treat just the 1st 12 digits of the string.
for (int i = 0; i < str.length() && digits < 12; i++) {
// Pull out that character.
char c = str.charAt(i);
// Is it a digit?
if ('0' <= c && c <= '9') {
// Keep the sum.
sum += multiplier * (c - '0');
// Flip multiplier between 1 and 3 by flipping the 2^1 bit.
multiplier ^= 2;
// Count the digits.
digits += 1;
}
}
// What is the check digit?
int checkDigit = (10 - (sum % 10)) % 10;
// Give it back to them in character form.
return (char) (checkDigit + '0');
}
NB: Edited to correctly handle the 0 check digit. See Wikipedia International Standard Book Number for example isbn with check digit of 0.
Paul
Similar, with loop and awful char-to-string-to-int conversions ;]
boolean isISBN13(String s){
String ss = s.replaceAll("[^\\d]", "");
if(ss.length()!=13)
return false;
int sum=0, multi=1;
for(int i=0; i<ss.length()-1; ++i){
sum += multi * Integer.parseInt(String.valueOf(ss.charAt(i)));
multi = (multi+2)%4; //1 or 3
}
return (Integer.parseInt(String.valueOf(ss.charAt(ss.length()))) == (10 - sum%10));
}

Categories