Create a secret encoder and decoder program. The program should function as follows: Begin by presenting a menu of options to the user. The user should be able to elect to encode a message, decode a message or quit. Repeatedly prompt the user with these options and end the program when the user elects to quit.
User Interface: Top Secret word Encrypt / Decrypt Enter an option: (1) to encrypt a word (2) to decrypt a word (0) to exit Option: Input: The user should only enter lowercase letters without any spaces. If the user enters an invalid string (i.e. “bob123”), they should be notified that this is an invalid string and be re-prompted for a new string. Hint: A method would be useful to handle this validation as you’ll need to do the same thing in the next step. Encryption Key: This key will also be a String of lowercase characters without any spaces. Make sure the encryption key is valid before continuing. The encryption key is used to encode/decode the word. It is used to create a “shift index” (i.e. every character is shifted X characters to the right). For example and encryption key of “ab” would shift the characters by 3 (a + b = 1 + 2 = 3) Here’s an example of how your shift index should work: // original alphabet a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z // Shift Index = 1 z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y // Shift Index = 2 y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x
Trying to figure out how to get the shift index to work. I'm thinking it might involve taking the length of the array and and subtracting by the number of shifts or something along that line?
mhm.. this type of encryption is kinda like a caesar cypher. Can be hacked within 26 attempts. Think of it like this.. if you shift your secret message "hello world" by 23 characters with password "sh", you can decode it with "shz" password, or "shmm" password -- or even "shzzzz" which would shift it left (26*4)+23 times, (each 26 long shift will bring it back to where it originally was) ie: encoding something to the password "z" or "zz" will become encoded to the same string that you wanted to be hidden.
"hello world" encoded to "z" encodes to "hello world"
So how would I go about shifting the string with a corresponding encryption key Here is some sample input/output: Top Secret word Encrypt / Decrypt Enter an option: (1) to encrypt a word (2) to decrypt a word (0) to exit Option: 1 Enter an unencrypted word: craig Enter an encryption key: abc Encoded Word: wluca
For the actual shifting of the characters.... assuming you already calculated how many characters you're going to shift (resulting in a number between 0-25) (this is just how I would do it -- but let's say the characters in the password add up to 265, we can then do 265%26 to get a number of 5 (shifting 5 and 265 result in the same end product) not necessary for my algorithm.. but might look a bit neater) --- You can turn all of the lower case letters into a char array, and an int array (the int array would hold all of the unicode equivalents of the char array) (and if all lowercase values, the int array will hold all values between 97-122 inclusive), we can then subtract 97 from all of them to have the new values of 0-25. Now we add the int value of how much we should shift to each element in the int array, and to make sure that any ints surpassing 25 go to where they should, we use the % modulus operator again on the int array to mod 26.. so if it was all shifted 2 characters, z, a value of 25, would become 27. and after doing 27%2, we get 1 remainder. With this scale, 0 = a, and 1 = b, so the math works out. Then at this point, we can add 97 back to all the int array elements, and then all the values will be between 97-122 inclusive again. We can then turn that int array into a char array, turn that char array into a string, and print it to a .txt document. Then to decode, we do almost the exact same thing.. except we now shift left instead of right, and when an int variable hits -1, set it equal to 25, then add 97 back to the int array, turn to char array, display string.
Let me know how it goes.
yea @woodrow73 is pretty right on it
@woodrow73, just working on breaking this problem into smaller pieces right now, and doing some exercises to get used to working with strings and arrays. I have the following problem: Write a method called isHeteroPair that has two String parameters, wordA and wordB. The method should return a Boolean value: true if wordA and wordB form a hetero-literal word pair and false if they do not. You may assume that all characters are uppercase letters. How do I get user input to assign to a string. Would I just declare the string as a variable and then assign the vale that the user inputs to that variable?
There are a few ways to get user input as a string.. doing JOptionPane via window: ``` import javax.swing.JOptionPane; String userInput = JOptionPane.showInputDialog("User, enter string here:"); ``` or scanner via console by doing: ``` import java.util.Scanner; Scanner scan = new Scanner(System.in); System.out.print("Enter string here: "); String input = scan.nextLine(); ```
Ok got that. Thanks. Also, how would I go about comparing the two strings to see if they share any of the same characters? I think this would involve using charAt or maybe indexOf, but which "char" would I be looking for ex: charAt.[]?
What are you interested in? comparing a couple random characters in both the strings -- or comparing 2 different substrings of them, or comparing both strings in entirety -- or do you mean to check what characters are shared by both strings?
I want to compare the strings in their entirety to see if they share any of the same characters.
ok, you'll like the simple .equals method then, it returns a boolean. Here's an example: ``` String str1 = "match"; String str2 = "match"; String str33 = "hOP"; String str44 = Hop"; if(str1.equals(str2)) System.out.println("str1 equals str2, and they are all the same case"); if(str33.equals(str44)) System.out.println("This will not print because one is uppercase and the other is lower"); if(str33.equalsIgnoreCase(str44)) System.out.println("This will print, because ignoring case, the 2 strings r the same); ```
So if I were to try to test and see not if the strings were equal but just if they had a least one of the same character: for instance fun and find both have an f and an n, it would return true, but for hi and bye it would return false, because they don't share any of the same characters, how would I be able to check all the characters in each string to see if any were the same.
you can use a nested for loop -- turn one of the strings into a char array, and have the outer loop iterate as many times as there are char arrays, and the inner loop iterate as many times as there is of char length in the second string you're testing, you can use the outer loop's iteration value to get the right element of the array, and the inner loops value to decide what to put in str.charAt(ii); and before the for loops, initialize a boolean flag variable to false-- and if a letter in the char array is ever equal to a letter in the string you're testing it against, assign that boolean to true-- now you know whether they share a character or not summed up in that boolean variable. If you want it to be case insensitive, you'd have to modify temporarily- both strings to be either upper or lower case.
thanks! Another interesting thing that I am looking into is how to determine which array value in an array is closest to 0. Any interesting ways of doing this? I'm thinking Math.abs but not sure how to sort the array and then compare them individually.
Sure man! You can iterate in a for loop as many elements as there are in a for loop - and for each number, test whether it is the smallest so far ``` import java.util.Random; public class sort{ public static void main(String[] args){ int x = 2000000000; //this will end up holding the smallest value int[] array = new int[50]; //will hold 50 random values Random rand = new Random(); //will call forth rand for random values for(int i = 0; i < 50; i++){ array[i] = rand.nextInt(); //returns random value -2billion to 2 billion } for(int i = 0; i < 50; i++){ if(x > array[i]) x = array[i]; //x stores the lowest value in the array } // } } ``` Though if you were to see how many duplicates of that smallest value there are, I'm sure you could scan an array for like values, and for all the similar ones, add their indices to an arraylist.
I never memorize algorithms or ways of doing things -- most of this stuff is intuitive to me because of practice -- if you're interested in honing that skill, I'd strongly recommend giving some problems @ projecteuler.net a try.
Except for syntax.. gotta memorize that :p
' ' ' import java.util.*; class SecretCoder { public static void main (String [] args) { System.out.println("Welcome to the Top Secret Encoder Program! Enter an option: 1 to encrypt a word, 2 to decrypt a word, or 0 to exit."); int option = In.getInt(); char [] array = new char [25]; array[0] = 1; public void shiftChars { char[] oldChar = newStr.toCharArray(); char[] newChar = new char[oldChar.length]; newChar[0] = oldChar[oldChar.length-1]; for(int i = 1; i < oldChar.length; i++){ newChar[i] = oldChar[i-1]; } newStr = String.valueOf(newChar); } char [] alphabet = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); ' ' '
got here, stuck on the approach from here. I am trying to understand what you were explaining to me before about how to shift the index. Would it be possible to do this using substring?
the thing for making this happen; ``` this ``` is the button on the keyboard in the top leftish section -- not the similar looking button next to the enter key.
The best way to manage code is organization -- I'll make it look a bit nicer; and don't forget to initialize the Scanner class. Here's your program cleaned up a bit; http://pastebin.com/W8LrXCQy doing 'a', 'b' is too tedious, so I made this; ``` public class Serve { public static void main(String[] args) { int[] v = new int[26]; for(int i = 97, z = 0; i < 123; i++, z++) { v[z] = i; } StringBuilder make = new StringBuilder(); for(int i = 0; i < 26; i++) { make.append("'"); make.append((char)v[i]); make.append("'"); if(i != 25) make.append(","); } System.out.println(make.toString()); } } ``` Anyway, the reason why I pointed out that you should use static, is so that you can call the method directly from the main method like callMethod(); however, if the method is not static, you could not call it from the main method. Not using static is useful for when you are creating 'secondary' classes that hold objects. So you'll need an encrypt() and a decrypt() method.. for the encrypt method, get the user to input a secret message, then get the user to input a password. Once you have both, devide them up into char arrays. This can best be done using the toCharArray() method. example: ``` String str = "woodrow wilson for president"; char[] array = str.toCharArray(); for(int i = 0; i < array.length; i++) { System.out.printf("%c", array[i]); } ``` The above will print out the string to the letter.
Once you add up the password to a number (using this number x, you will shift each character in the secret message string x times to the right). I was saying to first convert the char array into an int array; using this concept ``` char ch = 'a'; int hold = (int)ch; System.out.println(hold); ``` the above will print out 97, which is 'a' unicode equivalent. You can use the same idea to copy the char array into an int array. Once you have the int array, you can make an algorithm to make it switch forward x amount of times, and when it hits 'z', push the value back to 'a' (like your assignment says). aka when it hits 123 (z == 122 in unicode) set the int back equal to 97.
oh ok so what you're saying is, I need to convert my char array into an array of ints which I can use to get the key ex key ab (1 + 2 = 3) and then make an algorithm to make it switch forward x times?
also, how do I shift everything in array? I think it may have to do with manipulating charAt and the length of the array, but how would you get the alphabet to shift depending on the sum for key? Not really clear how the shift would work, but I'm working on it.
``` oh ok so what you're saying is, I need to convert my char array into an array of ints which I can use to get the key ex key ab (1 + 2 = 3) and then make an algorithm to make it switch forward x times? ``` Correct -- and don't forget to include this in your algorithm: that when one of those ints hit 27, you have to send it back to 1. ``` also, how do I shift everything in array? I think it may have to do with manipulating charAt and the length of the array, but how would you get the alphabet to shift depending on the sum for key? Not really clear how the shift would work, but I'm working on it. ``` You start by creating a for loop that iterates as many times as there are elements in the array. Like; ``` int q = { 1, 2, 3 }; for(int i = 0; i < q.length; i++) System.out.println(q + " "); ``` will print out ``` 1 2 3 ``` and within that array, you can make an algorithm that shifts each number x times.. you can do that however you want; one way would be a nested for loop that iterates as many times as you're supposed to shift the number -- that way you can catch the specific time that a number hits '27', and can send it back to equalling 1.
Edit: ``` int q = { 1, 2, 3 }; for(int i = 0; i < q.length; i++) System.out.println(q[i] + " "); ```
within the last paragraph-- I meant to say; ``` String str = "and within that array"; str = str.replace("and within that array", "and within the for loop that iterates as many times as there are elements in the array"); ```
``` import java.util.*; class SecretCoder { public static void main (String [] args) { System.out.println("Welcome to the Top Secret Encoder Program! Enter an option: 1 to encrypt a word, 2 to decrypt a word, or 0 to exit."); int option = In.getInt(); char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; array = int [] v; for (int i = 0; i < arraytwo.length; i++) { sum += array [i]; for (arraytwo[i]) { return arraytwo[i+1]; } ```
``` import java.util.*; class SecretCoder { public static void main (String [] args) { System.out.println("Welcome to the Top Secret Encoder Program! Enter an option: 1 to encrypt a word, 2 to decrypt a word, or 0 to exit."); int option = In.getInt(); char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; array = int [] v; for (int i = 0; i < arraytwo.length; i++) { sum += array [i]; for (arraytwo[i]) { return arraytwo[i+1]; } ```
so, I am not sure if this is right in any way. I seem to be at a bit of a road block as far as figuring out how to convert my char array to int array, which is what I attempted above, and getting the program to sum the key based on each letter of the alphabet representing a number (1, 2, 3, etc) and adding that and then shifting. I think my attempt at the multiple for loops is messy
To convert your char array to an int array, you should use a for loop, converting the char array to an int array one element at a time-- I don't think it's something that can be done in one line; ``` char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ int[i] = (int)arraytwo[i]; } ``` I'm handling each array element like it's a normal variable -- the same as ``` char ch = 'a'; int i = (int)ch; System.out.print(i); //prints out 97 ``` but on a bigger scale.
Note the (int) cast operator that converts the char to an int -- and how I use the loops iteration count (i) to specify which element I want to convert at which time.
ohh ok and i don't think I did the shifting right did I?
Not really.. if you have any trouble with your shifting algorithm (probably using nested for loops) let me know.
``` public static void shiftRight( char [] alphabet ) { char alphabet = alphabet[alphabet.length-1]; for( int index =alphabet.length-2; index >= 0 ; index-- ) alphabet[index+1] = alphabet[index]; } ``` I'm havling some issues with the shifting algorithm, and am having problems figuring out how to do the shifting algorithm after I have converted the char array to an int array.
what's that code snippet you posted supposed to do? Also, if you pass the char array alphabet into your method ``` public static void shiftRight( char [] alphabet ) ``` don't make another variable in that method called alphabet: ``` char alphabet = alphabet[alphabet.length-1]; ``` and when you create an array, don't forget the [] at the beginning; make it: ``` char[] alphabet2 = alphabet[alphabet.length-1]; ```
Yeah disregard that, I tried it out and it really doesn't work. What I am trying to do is find a way to get the char that the user enters ex ab = 1 + 2= 3 and get the program to translate that to shift everything along by three (get the last char to go back to the beginning) but am not really getting it right.
Ok, have you found out how to turn the user's secret message into a char array - then into an int array?
This is what I have from before which is what you helped me with ``` char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ int[i] = (int)arraytwo[i]; } ```
``` char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ int[i] = (int)arraytwo[i]; } ```
Is you're char array missing 'w', 'x', 'y', 'z'? Also, you don't distinguish individual arrays by their data type.. if I had this: ``` int[] birthYears = new int[5]; int[] weight = new int[5]; int[0] = 144; //error! what does int refer to? gotta do vvvv weight[0] = 144; ``` gotta know how to identify the proper array.
yes oops those letters were missing. oh ok so ``` int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ arraytwo[i] = (int)arraytwo[i]; ``` is this how it would be then?
pretty much.. looks like you accidentally changed the name of your char array in the for loop; ``` arraytwo[i] = (int)arraytwo[i]; ```
oh yeah, I'll be changing that. So then once I have the alphabet in a char array, the tricky part is converting the letters to their number values (1 - 26, summing them) and then shifting the alphabet by that number
after you make the char array of the alphabet into an int array, -- the int values will have a 26 long range of 97-122 inclusive. So if you were to put them in the 1-26 scale, you simply have to subtract each array element by 96. If you want to add up the int array, I'm sure you can make a for loop that adds each element in the array to an int variable (let's call that variable 'accumulator'). then you shift everything in the secret message to the right to the value of accumulator (it's optional, but you can do accumulator = accumulator%26; first). Try making a for loop that shifts each element in the int array accumulator amount of times. Are you sure you want to shift the secret message by the alphabet? You're no longer shifting it according to a password that the user enters?
@theEric
This key will also be a String of lowercase characters without any spaces. Make sure the encryption key is valid before continuing. The encryption key is used to encode/decode the word. It is used to create a “shift index” (i.e. every character is shifted X characters to the right). For example and encryption key of “ab” would shift the characters by 3 (a + b = 1 + 2 = 3) Here’s an example of how your shift index should work: // original alphabet a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z // Shift Index = 1 z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y // Shift Index = 2 y,z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,
Note: the encrypted string that you generate should only contain lower case letters. Present the encrypted version of the message to the user. Here’s a sample running of this part of the program: Top Secret word Encrypt / Decrypt Enter an option: (1) to encrypt a word (2) to decrypt a word (0) to exit Option: 1 Enter an unencrypted word: craig Enter an encryption key: abc Encoded Word: wluca
Yes, I understand how craig would get to wluca theoretically if that's what you mean
Yep!
And like you said I am trying to break down the puzzle into smaller pieces. So as you could probably see before when woodrow was helping me, I was trying to first initialize an array and then convert that array (of the alphabet) so that each letter of the alphabet represents the integers 1-26 because in order to figure out by how much I need to shift to get the encrypted word, the user will enter a code of lowercase chars for ex: abc which should translate to 1, 2, 3 and then sum that so that everything shifts along by 6
Okay! So, your talking about getting a numerical value from the key, right?
right!
Okay! So are you planning on making a function just for that? It would certainly make the the code more readable, and that would work very well with designing one piece at a time. The one downside to this method that I didn't mention in the email is that you can't test the method without writing specific code to do that. That will be easy enough, though!
Yes, you're right but like you said, I think making a method specifically to do this would be a good place to start.
So I guess I should start with making a char array like what I did above ``` char [] array = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ int[i] = (int)arraytwo[i]; } int [] arraytwo = new int[26]; for(int i = 0; i < array.length; i++){ arraytwo[i] = (int)arraytwo[i]; ```
and oops the alphabet is missing w x y and z
Okay! So, I'm guessing that you didn't mean to repeat the declaration for arraytwo, right?
So, you have an array of the alphabet, and you then make an array of numbers?
Well what I am trying to do is have an array of the alphabet and then make an int array so that when the user is prompted for input and enters ab for instance, it recognizes ab as 1+2
Don't know if this is exactly the right way to go about it.
But essentially what I'm doing is getting the user input to be translated into the amount that I want to shift the alphabet.
Okay! So, it would help if you could go from a letter in the alphabet to a numerical value for that, right?
yes
so that whatever letters the user enters gets translated into how much the alphabet needs to be shifted by
Okay! So, you know you can get the alphabet into an array very easily. Then each letter has an index number. Can we somehow get this index number to BE the number that the given letter would add to the total shift number?
That would make a really quick conversion.
We would look up a 'b', for example and get '2'.
I would say, maybe arrange that array differently, if you want to go with an array. It takes out that one extra calculation. I mean, you have an 'a' at index '0', but 'a' will shift the text by 1.
And lets get this straight: Each letter has a number associated with it as to how much it contributes to shifting the text. Examples, a = 1, b = 2, y= 25, z = 0. The total shift, is the sum of all of those numbers, but wrapped around (and so z = 0, and a + y = 1 + 25 = 0). Note: this is "modular behavior". That's like how the ones digit in any number is from 0 to 9, and it resets every ten increments.
oh ok so what does the coding look like for making an array where the index is equal to the shift value plus 1 (because the index starts at 0). ```
``` int shift; char arrray = new char {a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v}; for (int i = 0; i < array.length; i++) { (array.indexOf[i]) + 1 = shift; ```
would this work? And also, how would I get the user input to be read using the char array?
Do arrays have an "indexOf [ int ]" operation?
Sorry, you replied right after I left the room!
yes
So array.indexOf
and then the index number in square brackets like what I pasted above.
I think you'll have to \(make\) an "indexOf ( int )" if you're working with an array! Is that okay?
Do you use a program to write code?
I mean, and "IDE," which helps you write code.
an*
yes, I am using Dr. Java which is a third party IDE
Okay! Are you testing as you go? Some of the code seems incorrect, so far. Unless that was just pseudocode! It's fine for that.
I am not testing it yet, I'm just trying to do the pieces first and then put them all together to try them (so I'd have to add in the main methods etc in order for it to work if I was going to test it now)
and also, I don]t think my code is actually right yet/ It makes a char array but how do I get it to take into account the actual user input and compare the user input to the char array?
That's fine! Get the ideas now, and troubleshoot code later. You'll only get into trouble if it turns out to be more difficult to implement than you thought. For example, you'll need a slight workaround to get the index of a character in a character array. There's an "indexOf ( char )" for String objects, but you'll have to make one for your array.
So you have a good idea! You have the alphabet in an array, so you can get the shift amount from it. Looks clean!
Did you want to code and test that? Or move on to the rest of the rest of this shift number calculation, where you have to make sure you shift it by a number from 0-25 (not 800, for example).
Do you know how to translate user input (ex: a) to be taken and then recognized as a in the char array by any chance?
Maybe! Let me just get this straight: You want to have the user type \(\text a\) and take the input to be an char type?
a char type*
Or, user inputs a word or so, and then you want to use it as a char array?
I'm guessing that you want the latter. I looked here: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html and found that there is a "getChars ( int, int, char [], int)" method that might be useful. After a scanner gives you a String, you can copy it into a char array. It seems a little messy, though.
Join our real-time social learning platform and learn together with your friends!