I'm making a program that will take an input string and decode it using the Rot13 encryption method. This takes the alphabet, and rotates it by 13.
I'm having a hard time getting the index of a letter in the list, and every time I run it it gives me -1 as if the item is not in the list. I looked in the java documentation, and indexOf() asks for an object. I tried explicitly typing my input as an object but that didn't work either.
This is the code I have so far:
package rot13;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
/**
*
* #author andrewjohnson
*/
public class CipherKey {
List<String> alpha = Arrays.asList("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", " ");
List<String> alphaRev = Arrays.asList("Z", "Y", "X", "W", "V", "U", "T", "S", "R", "Q", "P", "O", "N", "M", "L", "K", "J", "I", "H", "G", "F", "E", "D", "C", "B", "A", " ");
public String codeDecode(String s) {
System.out.println(s);
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
//System.out.println(ch);
int x = alpha.indexOf(ch);
//System.out.println(x);
String y = alphaRev.get(x);
System.out.print(y);
}
return null;
}
public static String readInput() throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter message to be encoded or decoded");
String s = br.readLine().toUpperCase();
//System.out.println(s);
return s;
}
}
And my main():
/**
*
* #author andrewjohnson
*/
public class Rot13 {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
CipherKey x = new CipherKey();
x.codeDecode(x.readInput());
}
}
I'm not sure why it is not working, but I've narrowed it down to the line:
int x = alpha.indexOf(ch);
Not being able to find ch in alpha. I'm new to Java and I've tried everything that I can think of. Thanks for your suggestions!
The problem is here:
char ch = s.charAt(i);
int x = alpha.indexOf(ch); // <-------- HERE
You are searching for a char in a String array. Which of course doesn't exist. Hense the -1
Change it to int x = alpha.indexOf("" + ch);
or int x = alpha.indexOf(Character.toString(ch));
or int x = alpha.indexOf(String.valueOf(ch));
Any of these will do.
ch is of type char and your list contains String. List may accept Object for indexOf, but the type still counts.
Change int x = alpha.indexOf(ch); to int x = alpha.indexOf(String.valueOf(ch)); to fix it.
Example:
System.out.println(alpha.indexOf('D'));
System.out.println(alpha.indexOf(String.valueOf('D')));
will print
-1
3
That is not the rot13 algorithm - you just appear to be reversing the alphabet. rot13 maps the range A - M to N - Z, and vice versa. Two invocations of rot13 give you back the original text.
ASCII letters follow a numerical sequence. Instead of performing a linear search through a list to find the matching index, it's far faster to just calculate the difference between the current letter and A, and then use that difference to offset into a second array of characters (or a string).
i.e.
static String map = "NOPQRSTUVWXYZABCDEFGHIJKLM"; // for rot13
function rot13(String input) {
StringBuffer output;
for (char ch : input) {
int index = ch - 'A';
if (ch >= 0 && ch < 26) {
output.append(map.charAt(index));
} else {
output.append(ch);
}
}
return output.toString();
}
NB: untested, may not compile, E&OE etc
Related
This question already has answers here:
How to join Array to String (Java)?
(6 answers)
Closed 3 months ago.
I was working on a project, and thought, Couldn't there be an easier way to write a list without having to waste 3 minutes and one line of code? I'm probably wasting even more time here, but suppose I want to spell out "Hello, world!":
class Main {
public static void main(String[] args) {
String[] array = {"H", "E", "L", "L", "O", ", ", "W", "O", "R", "L", "D", "!"};
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + "-"); // prints "H-E-L-L-O-, -W-O-R-L-D-!-"
}
}
}
As you can see there's a nagging dash hanging over the edge at the end of the line. One idea I had was doing this:
class Main {
public static void main(String[] args) {
String[] array = {"H", "E", "L", "L", "O", ", ", "W", "O", "R", "L", "D", "!"};
System.out.print(array[0]); // enter "H" early
for (int i = 1; i < array.length; i++) { // int i = 0 -> int i = 1
System.out.print("-" + array[i]); // switched order, prints "H-E-L-L-O-, -W-O-R-L-D-!"
}
}
}
Yes, this does complete the job, but I feel like the extra line is clunky and awkward in my code. Also, I don't feel it's exactly flexible?
If there's something inside the documentary junk or a trick I need, please let me know. :)
You can print the dash before the list element and if the list element is the first one, you don't print anything.
class Main {
public static void main(String[] args) {
String[] array = {"H", "E", "L", "L", "O", ", ", "W", "O", "R", "L", "D", "!"};
for (int i = 0; i < array.length; i++) {
System.out.print((i == 0 ? "" : "-") + array[i]); // prints "H-E-L-L-O-, -W-O-R-L-D-!"
}
}
}
You can use the iterator i in a ternary expression (i == array.length - 1 ? "" : "-") as a substitute for the constant "-". This way, whether or not there is a dash is dynamic, based on whatever you want. This is adaptable to lots of different scenarios.
I am writing a program to check wether the given sentence is a panagram or not, but I am not able to compare each character with the characters in a string.
Can anyone suggest me a method to get the desired output?
Scanner scan = new Scanner(System.in);
String panagram = scan.nextLine();
String word = panagram.toLowerCase();
System.out.println(word);
String a[] = { "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" };
int count = 1;
System.out.println("a=" + a.length);
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < word.length(); j++) {
if ((a[i]).equals(word.charAt(j)))// problem occurs here {
count++;
break;
}
}
}
if (count == 26) {
System.out.println("pangram");
} else {
System.out.println("not pangram");
}
You can use:
(a[i]).equals(String.valueOf(word.charAt(j)))
or change your a array from String[] to char[] and compare the character using the == operator.
You can convert it to a String and then compare it.
String s = Character.toString('c');
if(s.equals(s2)){..}
Or you could make it a String by adding it to an empty string.
String s = 'c' + "";
if(s.equals(s2)){..}
Or you could compare it's ascii value.
As there are only single characters, why don't you use a character array.
char []a = {'a', 'b', 'c'....};
if(a[i] == 'a')//you could use == in this case.
{..}
Also you don't need to check it that way.
You could create a boolean array of 26 size, as there are only 26 characters and check if every character is present atleast once or not
boolean []arr = new boolean[26];
for(int i = 0; i < word.length(); ++i)
{
arr[word.charAt(i) - 'a'] = true;
}
isPan(arr);
public boolean isPan(boolean[] arr)
{
for(int i = 0; i < arr.length; ++i)
if(!arr[i])
return false;
return true;
}
A simple O(n) solution.
Or you could use a Set and check it's size.
HashSet<Character> set = new HashSet();
for(int i = 0; i < word.length(); ++i)
set.add(word.charAt(i));
System.out.println(set.size() == 26 ? "Pangram" : "Not Pangram");
//A 2 liner would be
HashSet<Character> set = new HashSet<Character>(Arrays.asList(word.toCharArray()));
System.out.println(set.size() == 26 ? "Pangram" : "Not Pangram");
A point added by spookieCookie. These approaches apply only when the string has only lower case alphabets.
String s = "sdgosdgoih3208ABDDu23pouqwpofjew##$%^&".repalceAll("[^A-Za-z]+", "");
String s = s.toLowerCase();
//do the computation then
Convert the array into an arraylist
List<Character> alphabet = Arrays.asList(a);
Make a list to hold the characters that are read:
Set<Character> chars = new HashSet<>();
Then check whether every character in the sentence is part of the alphabet. Duplicates are not added due to the characteristics of Set
for (Character c : word.toCharArray()) {
chars.add(c);
}
Then check whether the size of the Set is equal to the given alphabet:
return (chars.size() == alphabet.size());
Try this instead:
public void checkPanagram() {
boolean isPanagram = false;
String word = "The quick brown fox jumps over the lazy dog";
String a[] = { "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" };
for (int i = 0; i < a.length; i++) {
if (word.toLowerCase().contains(a[i])) {
isPanagram = true;
} else {
isPanagram = false;
break;
}
}
if (isPanagram) System.out.println("Yes, panagram");
else System.out.println("No, not panagram");
}
You can use String.contains(String) as every letter in a already is a String.
for (int i = 0; i < a.length; i++) {
if (word.contains(a[i])) {
count++;
// } else { break;
}
}
A remark: better use String[] a which is a more regular syntax instead of String a[] whose Syntax was added for C/C++ compatibility.
To check equality of a string with a char you could change your code minimally
if ((a[i]).equals(word.charAt(j)) to if ((a[i]).equals("" + word.charAt(j))
This gives you an equality check between two strings.
Alternatively you can change the line if ((a[i]).equals(word.charAt(j))
to if ((a[i]).equals(word.substring(j,j+1))
I am doing a project for my high school computer science class and I am running into some confusion. I am instructed to write a program which translates a user-inputted message from English to Morse code. I have completed the bulk of the assignment, but I can't seem to figure out how exactly to go about actually converting the user's message to Morse code.
import java.util.*;
import java.io.File;
import java.io.IOException;
public class MorseCode
{
public MorseCode()
{
}
//Reads in file containing Morse code and stores into an array of Strings
public static String [] readFile() throws IOException
{
String [] codes = new String[36];
int index = 0;
Scanner fileScanner = new Scanner(new File("morsecode.txt"));
while( fileScanner.hasNextLine() )
{
codes[index] = fileScanner.nextLine();
index++;
}
return codes;
}
//Converts the array of morse codes to an array of its corresponding letter
public static String [] findChars(String [] morseCode)
{
String [] 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",
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"};
for( int index = 0; index < morseCode.length; index++)
{
morseCode[index] = alphabet[index];
}
return morseCode;
}
}
Main
As of right now just used to test to make sure everything works as intended. Both the Morse code and its alphabetical and numeric equivalent outputs correctly.
import java.util.*;
import java.io.File;
import java.io.IOException;
public class MorseCodeTester
{
public static void main(String [] args) throws IOException
{
Scanner in = new Scanner(System.in);
//Original Morse Code
String [] morseCode = MorseCode.readFile();
//Conversion to standard english letters
String [] toConvert = MorseCode.readFile();
String [] codeToLetters = MorseCode.findChars(toConvert);
for( int index = 0; index < morseCode.length; index++)
{
System.out.println(morseCode[index]);
}
System.out.println();
for( int index = 0; index < morseCode.length; index++)
{
System.out.println(codeToLetters[index]);
}
}
}
As stated previously, my confusion is coming from the actual conversion of English to Morse code, after the user inputs the desired message. If anybody could point me in the right direction it would be very appreciated.
You could store each character in a Map along with its corresponding morse code string. e.g.
HashMap<String, String> codes = new HashMap<String, String>();
codes.put("a", ".-");
codes.put("b", "-...");
Then when converting a string, you could use the map to find the corresponding morse code string for each character of the string to be converted.
For example:
String str = "To be converted to morse";
StringBuilder morseSB = new StringBuilder();
for(int i=0; i< str.length(); i++)
{
morseSB.append(codes.get(Character.toString(str.charAt(i)).toLowerCase()));
}
String morseResult = morseSB.toString();
Note: you will need to add some precautionary checks. e.g. checking if the result of codes.get() is null and you may need to handle other characters like spaces and periods.
this function convert "Hello world" to Morse code
public static String charToMorse( String s ){
if( s.equals( "H" ) || s.equals("h"))
return "....";
else if ( s.equals( "E" ) || s.equals("e"))
return "."
// other alphabet will placed here
}
and write another method to traverse string's character
public static void showMorse( String s ){
for( int i=0 ; i < s.length() ; i++ )
System.out.printf( "%s " , charToMorse( s[i] ) );
System.out.println();
}
this image show Morse code you need
I am trying to write a piece of code that produces a letter frequency using arrays. I am getting a bit stuck on how to compare a letter in a string to a letter in an array. my basic pseudo code is as follows.
import java.util.Scanner;
public class test {
public static void main (String[]args){
Scanner sc = new Scanner (System.in);
System.out.print ("Please enter a sentence: ");
String str = sc.nextLine();
String [] let = {"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"};
Float [] freq = new Float [25];
int x,a = 0,b = 0, strCount = 0;
String str1;
str1 = str.replaceAll(" ", "");
for (x = 0; x < str1.length(); x++)
{
strCount++;
}
System.out.println("The number of Characters in the string is :" + strCount);
System.out.println();
And now I'm stuck on how to compare the str1 to the let array. I have tried the following but it has a problem with the comparing.
while (b < strCount)
{
while (a < let.length)
{
if (let[a] == str1.charAt(b))
{
freq[a] = freq[a]++ ;
}
if(let[a] != str1.charAt(b))
{
a = a++;
}
}
b = b++;
}
Any help would be much appreciated.
Thank you.
Well, I see a number of other issues but the one you're asking about is simple enough.
if (let[a].charAt(0) == str1.charAt(b)) // <-- one letter
{
freq[a]++ ;
}
else
{
a++;
}
Also, strCount = str1.length(); with no need for a loop.
You might want to get rid of the risk of eternal loops by replacing your while loops with
for
loops.
Also,
a = a++;
is incorrect, while
a++;
or
a = a+1;
is correct.
Fix those two, and you will have fixed your problem.
Let me address some of the problems that seem to stand out. First of all, you might want to enlarge your Float[] since it has a size of 25 and there are 26 letters in the alphabet, meaning you would want to do Float[] freq = new Float[26]instead. Also, you use str.replaceAll(), but str.replace() will suffice - they both replace all matches in the string.
To count the number of occurrences, you may want to use str.charAt(index) or break it up into a char array (str.toCharArray()) to compare the character with the values stored in the array. Since they are all single characters, you might also want to store the values as the primitive char instead of as a String.
The two while loops are completely unnecessary, as it can be done with the one forloop. Also, use str.length() instead of creating your own variable and using a for loop to increment strCount, especially when you specify to loop through it str.length() times...
I want to create method thath generate numbering for Database record in the future.
My rules like this :
[start] - [end]
0001-
9999
A001-
A999
AA01-
AA99
AB01-
AB99
AC01-
AC99
etc...
......
......
ZZZZ
Its look similar using Excel column numbering.
How to create like that, using Java?
Here is my code :
But i confuse in how to check if in the last number like 9999 , A999 etc
public static void main(String [] args) {
String lastSchCode = "9999";
System.out.println(generateSchCode(lastSchCode));
}
public static String generateNextNum(String number) {
int nextNum = Integer.parseInt(number);
String padNextNum = lPadZero(nextNum+1, 4);
return padNextNum;
}
public static String generateSchCode(String lastSchCode) {
String nextSchCode = null;
String [] alphabets = {"A", "B", "C", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
int counter = 0;
for (int i = 0; i < lastSchCode.length(); i++) {
if (lastSchCode.charAt(i) == '9') {
counter++;
}
}
if (generateNextNum(lastSchCode).equals("10000")) {
int num = 9999;
} else {
}
return nextSchCode;
}
Please help. Thank you.
Have a look at this snippet. You have to convert the number based on radix 36.
int[] ints = { 0, 1, 10, 35, 36, 46, 36*36-1, 36*36*36-1, 36*36*36*36-1};
for (int i : ints) {
System.out.printf("int: %7d string: %4s%n", i, Integer.toString(i, 36));
}
output
int: 0 string: 0
int: 1 string: 1
int: 10 string: a
int: 35 string: z
int: 36 string: 10
int: 46 string: 1a
int: 1295 string: zz
int: 46655 string: zzz
int: 1679615 string: zzzz
public static void main(String [] args) {
String lastSchCode = "9999";
System.out.println(generateSchCode(lastSchCode));
}
public static String generateNextNum(String number) {
int nextNum = Integer.parseInt(number);
String padNextNum = lPadZero(nextNum+1, 4);
return padNextNum;
}
public static String generateSchCode(String lastSchCode) {
String nextSchCode = null;
String [] alphabets = {"0","1","2","3","4","5","6","7","8","9","A", "B", "C", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
List<String> alphabetsAsList = Arrays.asList(alphabets);
int counter = 0;
for (int i = lastSchCode.length(); i > 0; --i) {
if(lastSchCode.charAt(i) == '9'){
incrementWith9(lastSchCode,i);
}
else{
String s = lastSchCode.substring(index,index+1);
String incrementedString = alphabetsAsList.get(alphabetsAsList.indexOf(s) + 1);
char[] charArr = lastSchCode.toCharArray();
charArr[index] = incrementedString.charAt(0);
nextSchCode = charArr.toString();
}
}
return nextSchCode ;
}
public String incrementWith9(String input, int index){
char[] ca = input.toCharArray();
ca[index] = '0';
if( index != 0 && input.charAt(index -1 ) == '9'){
incrementWith9(ca.toString(),index -1);
}
elseif(index == 0 ){
return "A000";
}
else{
String [] alphabets = {"0","1","2","3","4","5","6","7","8","9","A", "B", "C", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
List<String> alphabetsAsList = Arrays.asList(alphabets);
String s = input.substring(i,i+1);
String incrementedString = alphabetsAsList.get(alphabetsAsList.indexOf(s) + 1);
char[] charArr = input.toCharArray();
charArr[i] = incrementedString.charAt(0);
nextSchCode = charArr.toString();
}
return nextSchCode;
}
This should work. Or atleast you get the idea right.. ;)