Caesar Cipher With Space characters left unchanged - java

I'm trying to let the encryption function ignore the white spaces and the symbols between words from the UserInput. Should I use isWhitespace or what? and how to implement that?
The output for this program is totally correct, it shifts each letter to the next 7 one. but it doesn't accept shifting 2 words separated by space or coma.
I'm new into Java stunning world & I'm really enjoying it! Hence this's my 3rd week since I began.
import java.util.Scanner;
public class Test_Cipher{
public static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
public static String encrypt(String plainText, int shiftKey) {
plainText = plainText.toLowerCase();
String cipherText = "";
for (int i = 0; i < plainText.length(); i++) {
int charPosition = ALPHABET.indexOf(plainText.charAt(i));
int keyVal = (shiftKey + charPosition) % 26;
char replaceVal = ALPHABET.charAt(keyVal);
cipherText += replaceVal;
}
return cipherText;
}
}

There is two ways of doing this: either create a positive match for the character or a negative one. In the positive match variant you first check if plainText.charAt(i) is a character that you want to keep, and in that case add it to the cipherText and continue with the loop.
In the other you can check if indexOf returns -1 indicating that the alphabet doesn't contain the character. In that case you do the same thing: add it and continue. This is the common method I've seen for the classic Ceasar "play" cipher:
// introduce a local variable, you don't want to perform charAt twice
char c = plainText.charAt(i);
int charPosition = ALPHABET.indexOf(c);
// if charPositions is -1 then it is not found
if (charPosition == -1) { // or define a constant NOT_FOUND = -1
cipherText += c;
// continue with the for loop
continue;
}

Related

letter change, what am I doing wrong?

So im trying the following challenge:
Using the Java language, have the function LetterChanges(str) take the str parameter being passed andmodify it using the following algorithm. Replace every letter in the string with the letter following it in thealphabet (ie. c becomes d, z becomes a). Then capitalize every vowel in this new string (a, e, i, o, u) and finally return this modified string.
This is my code
class LetterChange {
public static String LetterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
char currentChar,letter;
int i = 0;
while (i < str.length())
{
currentChar = str.charAt(i);
for(int x = 0; x < alphabet.length(); x++)
{
letter = alphabet.charAt(x);
if (currentChar == letter){
str = str.replace(currentChar,alphabet.charAt(x+1));
i++;
}
}
}
when I run it it is returning the last char in string +1 letter in alphabet. for example if i was to run "bcd" it returns "EEE". I dont understand why its replacing all chars with the result of the loop for the last char.
When you go through the loop the first time you get
"bcd"--> "ccd"
Now, str.replace will turn this into "ddd" on next turn, then "EEE".
I.e., replace replaces every occurrence on each turn.
It is true that debugging it in the IDE will help you in the future!
Also, what if you had a lowercase vowel in your string?
public class Alphabet {
public static String LetterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
char[] string = str.toLowerCase().toCharArray();
for (int i=0; i < string.length; i++) {
char d = alphabet.charAt(((alphabet.toLowerCase().indexOf(string[i]))+1) % 26);
string[i]=d;
}
return new String(string);
}
public static void main(String[] args) {
System.out.println(Alphabet.LetterChanges("aabb"));
}
}
alphabet.charAt(
((alphabet.toLowerCase().indexOf(string[i]))
+1) % 26)
1) use toLowerCase on the input and your string map to eliminate case problems
2) find character at index+1 in string map 'alphabet', treating it as a circular buffer using a modulus that takes z to a.
index 25 (z) + 1 == 26 --> 0 (A) because 26 is 0 mod 26 while index 0(A) + 1 = 1 --> 1 mod 26. It is only necessary to wrap the z to A while not changing the other 25 indices and is more efficient than branching with an "if" statement.
Does this solution help?
public static String letterChanges(String str) {
String alphabet = "AbcdEfghIjklmnOpqrstUvwxyz";
StringBuilder stringBuilder = new StringBuilder();
for (char letter : str.toCharArray()) {
if (alphabet.contains(Character.toString(letter))) {
int index = alphabet.indexOf(letter) + 1;
if (index >= 26) {
index = 0;
}
stringBuilder.append(alphabet.charAt(index));
}
}
return stringBuilder.toString();
}
The previous solution was hard to follow, so it's difficult to explain why it wasn't working without debugging through it to see where it goes wrong. It was easier to use a for-each loop to go through the str parameter and find matches using Java's provided methods like .indexOf and .charAt.
Also, Java uses lower camel case method naming, letterChanges instead of LetterChanges :)
Let me know if you have any questions.
You are getting that result because on every replacing you are re-setting the input string. I recommend you:
Better try with two different variables: Let the input variable be unmodified, and work on the output one.
Since strings are unmodifiable -as you already know- better declare them as arrays of char.
For the shake of optimization, base your algorithm on one single loop, which will iterate over the characters of the input string. For each character, decide if it is alphabetic or not, and in case it is, what character should it be replaced with.

The Creation of The Encryption Key for a Keyword Cipher in My Code (Java)

I was just wondering if I could get some help with a question involving keyword ciphers.
The following code is supposed to create the encryption key for a keyword cipher (the key that states how your input (let's say "this is a secret message") became ("qabp bp k poynoq hoppkdo")). The key is, therefore, a String or char array. My teacher had us use a char array. For the case above, the key would {KEYWORDABCFGHIJLMNPQSTUVXZ}, and the basic alphabet would correspond to this {ABCDEFGHIJKLMNOPQRSTUVWXYZ}, therefore A would become K, I would become A, and so on and so forth.
But, anways, back to the problem at hand, when I try to create the key, the first loop that you see below works perfectly fine adding in the keyword for the first values of the array; however, after this adding in the rest of the array (the rest of the alphabet not including or skipping the letters of the keyword) doesn't seem to work in the second loop.
I don't exactly know what I am doing wrong, but I would guess it would have to do with one of the if statements, or the java keyword (continue;) that I use in the loop. Because it appears that when I print the keyword array, it comes out to {KEYWORDABCDEFGHIJKLMONPQRS} leaving out the last seven letters of the alphabet instead of the letters that already occur in the word, KEYWORD.
If you could help fix the code, or get me on the right track, that would be much appreciated. If you have an question on the question, fell free to ask in the comment section below/
Thank you so much for all your help!
public class Crytograph
{
private String in;
private String out;
//private int awayFrom;
private char [] keyword;
private String word;
public Crytograph(String input, String wordLY) // , int fromAway )
{
in = input.toLowerCase();
out = "";
awayFrom = fromAway;
word = wordLY;
keyword = new char[26];
int counter = 97;
int counter1 = 0;
for (int x = 0; x < word.length(); x++)
{
keyword[x] = word.charAt(x);
}
for (int i = word.length(); i < 26; i++)
{
if ((char)(counter) == keyword[counter1])
{
continue;
}
else
{
keyword[i] = (char)(counter);
//System.out.println(keyword[i]);
}
counter++;
counter1++;
if (counter1 == word.length())
{
counter1 = 0;
}
}
}
You're comparing each new character to a single character at index counter1. But you really need to compare it to all the characters in word. Even if you happen to find a match, continue; will still increment i, meaning your array will be missing one or more characters at the end. Try this instead:
char c = 'a' - 1;
for (int i = word.length(); i < 26; i++) {
// loop until we find a char not contained in `word`
while (word.contains(String.valueOf(++c)));
keyword[i] = c;
}

Replacing the letters of a String with blank if they are found in another

I am working on an assignment and this part is tripping me up.
Construct cipher1 by first filling in the matrix with the unique letters from the first key.
For example, if the key is “testkey”, then fill in the key with the letters T, E, S, K, Y.
Do not fill in repeated characters from the key. Then fill the matrix with the remaining characters of the alphabet (again, skipping Q).
Do not repeat any characters that appeared in the key. So, for “testkey”, cipher1 looks like this: "
The cypher is a 5 by 5 array usually filled with the letters of the alphabet minus 'q'.
So if my key is testkey, the cipher will now be filled with "TESKYABCDFGHIJLMNOPRUVWXZ" instead of "ABCDEFGHIJKLMNOPRSTUVWXYZ".
I thought something like this would work but it doesn't.
for (int i = 0; i < key.length(); i++)
{
key.toCharArray();
alphabet.replace(key[i], "");
}
The key variable being a string "TESTKEY" and the alphabet variable also being a string containing "ABCDEFGHIJKLMNOPRSTUVWXYZ".
Looking at it now that code is obviously flawed and now I'm just stuck. Please any one give the suggestion to me
Try this :
public static void main(String[] args) {
String testS = "testkey";
String key = "ABCDEFGHIJKLMNOPRSTUVWXYZ";
testS = testS.toUpperCase() + key;
testS = removeDuplicates(testS);
System.out.println(testS);
}
static String removeDuplicates(String string) {
StringBuilder noDuplicateChars = new StringBuilder();
for (int i = 0; i < string.length(); i++) {
String letter = string.substring(i, i + 1);
if (noDuplicateChars.indexOf(letter) == -1) {
noDuplicateChars.append(letter);
}
}
return noDuplicateChars.toString();
}
If from some reason you don't want to use StringBuilder, you can change the implementation of removeDuplicates to :
static String removeDuplicates(String string) {
String noDuplicates = new String("");
for (int i = 0; i < string.length(); i++) {
if (!noDuplicates.contains("" + string.charAt(i))) {
noDuplicates += "" + string.charAt(i);
}
}
return noDuplicates;
}
You can use LinkedHashSet. In for loop add key characters and in second loop add alphabet characters. Then iterate through set elements and build string.
Note that method add do not place element if it already exist in the set, hence no additional checks are needed.
You just need to use regular expression;
example: 1 - key
input: testkey
code: `String newString = input.replaceAll("(.)\\1{1,}", "$1").toUpperCase();`
output: TESKY
Example 2; Concat newString with the alphapatical string
input: testkey + "ABCDEFGHIJKLMNOPRSTUVWXYZ";
code: `String FinalString = input.replaceAll("(.)\\1{1,}", "$1").toUpperCase();`
output: TESKYABCDFGHIJLMNOPRUVWXZ

Algorithm to generate random string with harsh restrictions - Java

I'm trying to make a program to generate a random account name for the user. The user will hit a button and it will copy the account name to his clipboard. The GUI part of it is working but I just can't think of the best way to handle random generation of a String.
Allowed characters in the username: A-Z a-z _
No numbers, no other symbols, and no two of the same character in a row can occur.
Must be of length six.
My idea:
create an array of characters:
[ _, a, b, c, d ... etc ]
Generate a random integer between 0 and array.length - 1
and pick the letter in that slot.
Check the last character to be added into the output String,
and if it's the same as the one we just picked, pick again.
Otherwise, add it to the end of our String.
Stop if the String length is of length six.
Is there a better way? Perhaps with regex? I have a feeling the way I'm thinking of doing it here is really bad.
I don't see anything wrong with your proposed algorithm (except you need to handle the first character you add without checking if you've already added it). You might also extract it to a static method and use a Random like,
static Random rand = new Random();
static String getPassword(String alphabet, int len) {
StringBuilder sb = new StringBuilder(len);
while (sb.length() < len) {
char ch = alphabet.charAt(rand.nextInt(alphabet.length()));
if (sb.length() > 0) {
if (sb.charAt(sb.length() - 1) != ch) {
sb.append(ch);
}
} else {
sb.append(ch);
}
}
return sb.toString();
}
Then you could call it with something like,
public static void main(String[] args) {
StringBuilder alphabet = new StringBuilder();
for (char ch = 'a'; ch <= 'z'; ch++) {
alphabet.append(ch);
}
alphabet.append(alphabet.toString().toUpperCase()).append('_');
String pass = getPassword(alphabet.toString(), 6);
System.out.println(pass);
}

Java - Help converting letter to integer, adding 5, then converting back to letter

First off, here is my code so far
public int encrypt() {
/* This method will apply a simple encrypted algorithm to the text.
* Replace each character with the character that is five steps away from
* it in the alphabet. For instance, 'A' becomes 'F', 'Y' becomes '~' and
* so on. Builds a string with these new encrypted values and returns it.
*/
text = toLower;
encrypt = "";
int eNum = 0;
for (int i = 0; i <text.length(); i++) {
c = text.charAt(i);
if ((Character.isLetter(c))) {
eNum = (int) - (int)'a' + 5;
}
}
return eNum;
}
(text is the inputted string by the way. And toLower makes the string all lower case to make it easier converting.)
I got most of my assignment done, but one part of it is tasking me with moving every letter inputted 5 spaces over. A becomes F, B becomes G, etc.
So far from I got the letter converted to a number, but I am having trouble adding to it and then returning it back to a letter.
When I run the program and I enter my input such as "abc" I get '8'. It just adds them all up.
Any help would be much appreciated, and I can post the full code if necessary.
Few issues -
First of all - eNum = (int) - (int)'a' + 5; you do not need the first (int) - i believe, you can just do - eNum = (int)c + 5; . Your expression would always result in a negative integer.
Instead of returning eNum you should convert it to character and add it to a string and return the string at end (or you can create a character array of same length as string , keep storing the characters in the array, and return a string created from the character array).
Instead of using a in the condition , you should use c which denotes the current character at the ith index.
I am guessing not all of the variables in your code are member variables (instance variables) of the class , so you should define them with a datatype in your code.
Example changes to your code -
String text = toLower; //if toLower is not correct, use a correct variable to get the data to encrypt from.
String encrypt = "";
for (int i = 0; i <text.length(); i++) {
char c = text.charAt(i);
if ((Character.isLetter(c))) {
encrypt += (char)((int)c + 5);
}
}
return encrypt;
//Just a quick conversion for testing
String yourInput = "AbC".toLowerCase();
String convertedString = "";
for (int i = 0; i <text.length(); i++) {
char c = yourInput.charAt(i);
int num = Character.getNumericValue(c);
num = (num + 5)%128 //If you somehow manage to pass 127, to prevent errors, start at 0 again using modulus
convertedString += Integer.toString(num);
}
System.out.println(convertedString);
Hope this is what you're looking for.
Try something like this, I believe this has several advantages:
public String encrypt(String in) {
String workingCopy = in.toLowerCase();
StringBuilder out = new StringBuilder();
for (int i = 0; i < workingCopy.length(); i++) {
char c = workingCopy.charAt(i);
if ((Character.isLetter(c))) {
out.append((char)(c + 5));
}
}
return out.toString();
}
This code is a little bit verbose, but perhaps then it is easier to follow. I introduced the StringBuilder because it is more efficient than doing string = string + x

Categories