I'am trying to decipher Vigenere_Cipher
when i enter BEXR TKGKTRQFARI the output is JAVAPROGRAMMING But i want
to put space like JAVA PROGRAMMING.
My Code
public static String VigenereDecipher(String text) {
String keyword = "SECRET";
String decipheredText = "";
text = text.toUpperCase();
for (int i = 0, j = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c < 'A' || c > 'Z') continue;
decipheredText += (char)((c - keyword.charAt(j) + 26) % 26 + 'A');
j = ++j % keyword.length();
}
return decipheredText;
}
You're explicitly ignoring the spaces. You simply need to add this line:
if (c == ' ') {
decipheredText += ' ';
}
Make sure to put it right before this line:
if (c < 'A' || c > 'Z') continue;
You are ignoring the space. Check for space as you are checking for character range 'A' to 'Z' and add it to decipheredText as space only as you don't want space to treated as another character.
Related
I'm trying to solve Caesar's Cipher in Java but there's a twist to it. The input string has alphanumeric values and I am unable to solve. Here's what I've attempted so far:
String rotationalCipher(String input, int rotationFactor) {
// Write your code here
StringBuilder sb = new StringBuilder();
for(int i = 0; i < input.length(); i++) {
if(Character.isLowerCase(input.charAt(i))) {
char ch = (char)(((int)input.charAt(i) + rotationFactor - 97) % 26 + 97);
} else if (Character.isUpperCase(input.charAt(i))) {
char ch = (char)(((int)input.charAt(i) + rotationFactor - 65) % 26 + 65);
sb.append(ch);
} else {
char ch = (char)(((int)input.charAt(i) + rotationFactor - 48) % 10 + 48);
sb.append(ch);
}
}
return sb.toString();
}
What I'm trying to do is evaluate each case using its ASCII values but I don't seem to get the desired output. Am I using ASCII wrong? Thanks for your help!
Sample input/output:
input = Zebra-493?
rotationFactor = 3
output = Cheud-726?
You have two major problems.
You did not update StringBuilder with an append for lowercase transitions.
You need to handle digits specially using isDigit just like upper and lower case so that you can then ignore characters like - and ?
A couple of suggestions.
just assign ch when you first enter the loop and then use it throughout the loop. No need to keep typing in all the input stuff.
only append ch to the StringBuilder once near the end when you exit the if/else blocks.
Instead of numbers like 97 and 65 use 'a' and 'A'. Less likely to make mistakes that way.
Once you make those changes, your code works just fine.
Below code works for me-
String rotationalCipher(String input, int rotationFactor) {
// Write your code here
StringBuffer sb = new StringBuffer();
for (int i = 0; i < input.length(); i++) {
char x = input.charAt(i);
if (Character.isLowerCase(x)) {
char ch = (char) ((x + rotationFactor - 97) % 26 + 97);
sb.append(ch);
} else if (Character.isUpperCase(x)) {
char ch = (char) ((x + rotationFactor - 65) % 26 + 65);
sb.append(ch);
} else if (Character.isDigit(x)) {
char ch = (char) ((x + rotationFactor - 48) % 10 + 48);
sb.append(ch);
} else {
sb.append(x);
}
}
return sb.toString();
}
String rotationalCipher(String input, int rotationFactor) {
String output = "";
for(char a: input.toCharArray()){
if(Character.isAlphabetic(a)){
char startLetter = Character.isUpperCase(a) ? 'A' : 'a';
output += (char) ((a- startLetter + rotationFactor) % 26 + startLetter);
}
else if(Character.isDigit(a)){
output += (char) ((a + rotationFactor - 48) % 10 + 48);
}
else{
output += a;
}
}
return output;}
Take as input S, a string. Write a function that replaces every odd character with the character having just higher ASCII code and every even character with the character having just lower ASCII code. Print the value returned.
package assignments;
import java.util.Scanner;
public class strings_odd_even_char {
static Scanner scn = new Scanner(System.in);
public static void main(String[] args) {
String str = scn.nextLine();
for (int i = 0; i < str.length(); i = i + 2) {
char ch = str.charAt(i);
ch = (char)((ch + 1));
System.out.println(ch);
}
for (int j = 1; j < str.length(); j = j + 2) {
char ch = str.charAt(j);
ch = (char)((ch - 1));
System.out.print(ch);
}
}
}
The problem with my code is that it is first printing the values for all the odd characters and then for even characters but what I want is that they get printed in proper sequence like for input --> abcg , the output should be --> badf .
I'd hold the "incremenet" value in a variable and alternate it between +1 and -1 as I go voer the characters:
private static String change(String s) {
StringBuilder sb = new StringBuilder(s.length());
int increment = 1;
for (int i = 0; i < s.length(); ++i) {
sb.append((char)(s.charAt(i) + increment));
increment *= -1;
}
return sb.toString();
}
Just use one loop that handles both characters:
for (int i = 0; i < str.length(); i = i + 2) {
char ch = str.charAt(i);
ch = (char) (ch + 1);
System.out.print(ch);
if (i + 1 < str.length()) {
ch = str.charAt(i + 1);
ch = (char) (ch - 1);
System.out.print(ch);
}
}
You only need to iterate one time but do different operation (char+1) or (char-1) depending on the i:
public static void main(String[] args) {
String str = scn.nextLine();
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i % 2 == 0) { // even
ch += 1;
} else { // odd
ch -= 1;
}
System.out.print(ch);
}
}
You are using two loops, but you only need one. You can use the % operator to tell if i is even or odd, and then either subtract or add accordingly:
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i % 2 == 0) {
ch = (char)((ch + 1));
System.out.println(ch);
} else {
ch = (char)((ch - 1));
System.out.print(ch);
}
}
You can do it in one for loop, to do that you will need to check whether the current index is even or odd. if current index is even you will increment char and print, if it is odd you will decrement char and print. to check if even or odd using % operator
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if(i%2 == 0) {
ch = ch + 1;
System.out.println(ch);
continue;
}
ch = ch - 1;
System.out.println(ch);
}
Here's my code that I've written :
public String binary(String s)
{
String[] a = {
"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"
};
String k = "";
for(int i = 0; i <= s.length() - 1; i++)
{
if (s.charAt(i) == 'a') { k += a[10]; }
else if (s.charAt(i) == 'b') { k += a[11]; }
else if (s.charAt(i) == 'c') { k += a[12]; }
else if (s.charAt(i) == 'd') { k += a[13]; }
else if (s.charAt(i) == 'e') { k += a[14]; }
else if (s.charAt(i) == 'f') { k += a[15]; }
else { k += a[i]; }
}
return k;
}
I am getting output as a[0-9] = 0000. How can I fix this? What am I doing wrong?
The problem is with use of a[i]. It is a logical error. Because i is loop variable which indicates the current index in s String. But you are using it to indexing it in variable a. So, i variable is use incorrectly here.
Following is corrected (and a bit optimized) code. See it working here:
public class HexaDecimal
{
public String binary(String s)
{
String[] a= {"0000","0001","0010","0011","0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111"};
String k="";
for(int i=0;i<s.length();i++)
{
char ch = Character.toUpperCase(s.charAt(i));
if(ch>='A' && ch <= 'F') k+= a[ch - 'A' + 10];
else k+= a[ch - '0'];
}
return k;
}
}
Replace k+=a[i]; with k+=a[s.charAt(i) - '0'];
You're using your string index loop variable as an index into a rather than the character at that location in the string.
You need to do - '0' to convert from unicode codepoint to the value it represents as an ASCII digit (which I assume you want to use here)
Your last else does the incorrect calculation. It does not take into consideration what is inputted, only the position. You want it to be
else {
k += a[s.charAt(i) - '0'];
}
There are easier ways to get the binary representation of hexadecimals, and you probably also want to check the input that it does not contain anything else than 0-9 or a-f.
You can change the for loop to this:
for(int i=0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c >= '0' && c <= '9') k += a[c - '0'];
else if (c >= 'a' && c <= 'f') k += a[c - 'a' + 10];
else if (c >= 'A' && c <= 'F') k += a[c - 'A' + 10];
else throw new InvalidArgumentException(s);
}
This is a lot simpler and self-explanatory, at least in my opinion. Handles digits, uppercase and lowercase letters, and fails in an expected way on bad input.
I'm trying to create a loop which only returns letters. In my code, I get symbols that I don't want. How do I fix my loop so that when my integer is +3, it only gives me letters?
public static String caesarDecrypt(String encoded, int shift){
String decrypted = "";
for (int i = 0; i < encoded.length(); i++) {
char t = encoded.charAt(i);
if ((t <= 'a') && (t >= 'z')) {
t -= shift;
}
if (t > 'z') {
t += 26;
} else if ((t >= 'A') && (t <= 'Z')) {
t -= shift;
if (t > 'Z')
t += 26;
} else {
}
decrypted = decrypted + t;
}
}
You are subtracting the shift value from the letters. Therefore, the new letter can never be > 'z'. You should check if the it is < 'a' (or 'A', respectively).
StringBuilder decrypted = new StringBuilder(encoded.length());
for (int i = 0; i < encoded.length(); i++)
{
char t = encoded.charAt(i);
if ((t >= 'a') && (t <= 'z'))
{
t -= shift;
while (t < 'a')
{
t += 26;
}
}
else if ((t >= 'A') && (t <= 'Z'))
{
t -= shift;
while (t < 'A')
{
t += 26;
}
}
decrypted.append(t);
}
return decrypted.toString();
Also, you shouldn't be using String concatenation to generate the result. Learn about StringBuilder instead.
EDIT: To make sure the new letter is in the range 'a' .. 'z' for an arbitrary (positive) shift, you should use while instead of if.
I am not giving you exact code. But I can help you in logic:
Check whether you are reaching end points (a, A, z, Z) due to the shift.
If you exceed the end points either way, then compute the distance between end points and shifted t. Add/subtract/modulus (based on the end point) this distance to the other endpoint to get the exact letter.
Something like this? (Warning, untested)
public static String caesarDecrypt(String encoded, int shift) {
String decrypted = "";
for (int i = 0; i < encoded.length(); i++) {
char t = encoded.charAt(i).ToUpper();
decrypted = decrypted + decode(t, shift);
}
}
// call with uppercase ASCII letters, and a positive shift
function decode(char n, int shift)
{
if ((n < 'A') || (n > 'Z')) return ('-');
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var s = str.charAt(((n - 'A') + shift)%26);
return(s);
}
As you are naming your method caesarDecrypt (I assume you mean encrypt), I think you want a shift in the alphabet including wrapping around.
This code will do that for you:
public class Snippet {
public static void main(String[] args) {
System.out.println(caesarShift("This is a Fizzy test.", 5));
System.out.println(caesarShift("Ymnx nx f Kneed yjxy.", -5));
}
public static String caesarShift(String input, int shift) {
// making sure that shift is positive so that modulo works correctly
while (shift < 0)
shift += 26;
int l = input.length();
StringBuffer output = new StringBuffer();
for (int i = 0; i < l; i++) {
char c = input.charAt(i);
char newLetter = c;
if (c >= 'a' && c <= 'z') { // lowercase
newLetter = (char) ((c - 'a' + shift) % 26 + 'a'); // shift, wrap it and convert it back to char
} else if (c >= 'A' && c <= 'Z') { // uppercase
newLetter = (char) ((c - 'A' + shift) % 26 + 'A'); // shift, wrap it and convert it back to char
}
output.append(newLetter);
}
return output.toString();
}
}
This will handle lowercase and uppercase letters. Everything else will be left as it is (like spaces, punctuations, etc).
Please take some time to look at this code to understand how it works. I have put some comments to make it clearer. From your code I think you were a bit confused, so it is important that you understand this code very well. If you have questions, feel free to ask them.
This code
String start = "abcdefghijklmnopqrstuvwxyz";
String encrypted = caesarShift(start, 3);
String decrypted = caesarShift(encrypted, -3);
System.out.println("Start : " + start);
System.out.println("Encrypted : " + encrypted);
System.out.println("Decrypted : " + decrypted);
will give this result
Start : abcdefghijklmnopqrstuvwxyz
Encrypted : defghijklmnopqrstuvwxyzabc
Decrypted : abcdefghijklmnopqrstuvwxyz
String word = "ABCD";
StringBuffer str = new StringBuffer (word);
int counter = 0;
for (int ch = 0; ch < word.length(); ch ++)
{
int number = word.charAt(ch)- 'A' + 1;
str.setCharAt(counter, (char) number);
if (ch != word.length ()-1)
str.insert(counter +1, '-');
counter += 2;
}
System.out.println (str);
}
I want my output to be 1-2-3-4, so A = 1 and B= 2.... etc. We can assume that all the input are in upper case. But the my code produce random symbols. So how do I fix the code to produce 1-2-3-4 without re writing the whole thing?
You're only missing the conversion from int back to char. The line
str.setCharAt(counter, (char) number);
should be
str.setCharAt(counter, (char) ('0' + number));