Videos
What languages does Code Translator support?
Can Code Translator handle complex code structures?
Is the converted Java code accurate?
Here is an example implementation:
import java.io.*;
import java.util.*;
public class Translator {
public enum Language {
EN, ES
}
private static final String TRANSLATION_TEMPLATE = "translation_%s_%s.properties";
private final Properties translations = new Properties();
public Translator(Language from, Language to) {
String translationFile = String.format(TRANSLATION_TEMPLATE, from, to);
try (InputStream is = getClass().getResourceAsStream(translationFile)) {
translations.load(is);
} catch (final IOException e) {
throw new RuntimeException("Could not read: " + translationFile, e);
}
}
private String[] translate(String text) {
String[] source = normalizeText(text);
List<String> translation = new ArrayList<>();
for (String sourceWord : source) {
translation.add(translateWord(sourceWord));
}
return translation.toArray(new String[source.length]);
}
private String translateWord(String sourceWord) {
Object value = translations.get(sourceWord);
String translatedWord;
if (value != null) {
translatedWord = String.valueOf(value);
}
else {
// if no translation is found, add the source word with a question mark
translatedWord = sourceWord + "?";
}
return translatedWord;
}
private String[] normalizeText(String text) {
String alphaText = text.replaceAll("[^A-Za-z]", " ");
return alphaText.split("\\s+");
}
public static void main(final String[] args) {
final Translator translator = new Translator(Language.EN, Language.ES);
System.out.println(Arrays.toString(translator.translate("hello world!")));
}
}
And put a file called 'translation_EN_ES.properties' on your classpath (e.g. src/main/resources) with:
hello=holla
world=mundo
If you know all the words before hand you could easily create a Regex Trie.
Then at runtime, compile the regex once. Then you are good to go.
To create the regex, download and install RegexFormat 5 here.
From the main menu, select Tools -> Strings to Regex - Ternary Tree
paste the list in the input box, then press the Generate button.
It spits out a full regex Trie that is as fast as any hash lookup there is.
Copy the compressed output from that dialog into Rxform tab (mdi) window.
Right click window to get the Context menu, select Misc Utilities -> Line Wrap
set it for about a 60 character width, press ok.
Next press the C++ button from the windows toolbar to bring up the MegaString
dialog. Click make C-style strings Lines Catenated-1 press OK.
Copy and paste the result into your Java source.
Use the regex in a Replace-All with callback.
In the callback use the match as a key into your hash table to return the
translation to replace.
Its simple, one pass and oh so fast.
For a more extreme example of the tool see this regex of a 130,000 word dictionary.
Sample of the letter X
"(?:x(?:anth(?:a(?:m|n|te(?:s)?)|e(?:in|ne)|i(?:an|"
"c|n(?:e)?|um)|o(?:ma(?:s|ta)?|psia|us|xyl))|e(?:be"
"c(?:s)?|n(?:arthral|i(?:a(?:l)?|um)|o(?:biotic|cry"
"st(?:s)?|g(?:amy|enous|raft(?:s)?)|lith(?:s)?|mani"
"a|n|ph(?:ile(?:s)?|ob(?:e(?:s)?|ia|y)|ya)|time))|r"
"(?:a(?:fin(?:s)?|n(?:sis|tic)|rch|sia)|ic|o(?:derm"
"(?:a|i(?:a|c))|graphy|m(?:a(?:s|ta)?|orph(?:s)?)|p"
"h(?:agy|ily|yt(?:e(?:s)?|ic))|s(?:is|tom(?:a|ia))|"
"t(?:es|ic))))|i(?:pho(?:id(?:al)?|pag(?:ic|us)|sur"
"an))?|oan(?:a|on)|u|y(?:l(?:e(?:m|n(?:e(?:s)?|ol(?"
":s)?))|i(?:c|tol)|o(?:carp(?:s)?|g(?:en(?:ous)?|ra"
"ph(?:s|y)?)|id(?:in)?|l(?:ogy|s)?|m(?:a(?:s)?|eter"
"(?:s)?)|nic|ph(?:ag(?:an|e(?:s)?)|on(?:e(?:s)?|ic)"
")|rimba(?:s)?|se|tomous)|yl(?:s)?)|st(?:er(?:s)?|i"
"|o(?:i|s)|s|us)?)))"
You've got a couple things here that need to be addressed, so lets take a look:
Input
Scanner.next() is only going to give only the next token. In your case, you want the entire string. Try using Scanner.nextLine() instead.
Translator Logic
The way your code exists currently, you are stepping through the input (correct), but for each character in the input, you're not fetching the equivalent in Morse Code! You're instead comparing the entire input to the single English character at english[index]. See below for a suggestion to fix your logic.
Output
Also notice that you are printing out a translated String after each character, which I don't think you want to do.
Suggestions
Couple of suggestions for you:
- If you want to handle a space character in the input, add that to your arrays!
I would highly suggest storing your English and Morse characters in a Map. This way, you can very easily look up the Morse equivalent to an English character. Your arrays are ok still if you would like, but perhaps add the following after they're initialized:
final Map<String, String> mapping = new HashMap<String, String>(); for (int i = 0; i < english.length; ++i) { mapping.put(english[i], morse[i]); }Now with this, you can look up the Morse character in your loop using
mapping.get(String.valueOf(userInput.charAt(index))).To build up your output, I would recommend using StringBuilder. So for each iteration in your loop,
builder.append(...), and when you're ready to print it out, you can usebuilder.toString()
This was definitely an answer better-suited for a code review, but hey, it answered your logic issue. Hope this helps!
Here is the Optimized Code of your Given Solution
public class MorseCode {
public static Scanner sc;
public static void main(String args[]) throws IOException //Input Output Exception is added to cover the BufferedReader
{
int option = 0;
String sentence = "",answer = "",answer1 = "";
char[] english = { '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',
',', '.', '?' }; //Defining a Character Array of the English Letters numbers and Symbols so that we can compare and convert later
String[] morse = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",
".---", "-.-", ".-..", "--", "-.", "---", ".---.", "--.-", ".-.",
"...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----",
"..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.",
"-----", "--..--", ".-.-.-", "..--.." }; //Defining an Array of String to hold the Morse Code value of Every English Letter,Number and Symbol in the same order as that of the character Array
sc = new Scanner(System.in);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(">>>>Welcome to MorseCode Software<<<<");
System.out.println("");
do
{
System.out.println("-->Enter the Option Corresponding to the Task you want to Perform ");
System.out.println("->1.Generate Morse Code<- OR ->2.Generate English Language<- OR ->3.Exit ");
System.out.print("->");
while(!sc.hasNextInt()) //Repeat Until the next Item is an Integer i.e Until the Next Item is an Integer Keep on Repeating it
{//NOTE- The hasnext() function is also used when we are using the Iterator where the next input is always checked and then if it is valid it is allowed to be entered
System.out.println("");
System.err.println("-->ERROR<-->Enter Digits Only<--");
System.out.print("->");
sc.next(); //Repeat and Discard the previous Inputs which are not valid
}
option = sc.nextInt();
switch(option)
{
case 1:
{
System.out.println("");
System.out.println("-->Enter the Sentence that you want to Transmit Using the Morse Code ");
System.out.print("->");
sentence = br.readLine();
System.out.println("");
sentence = sentence.toLowerCase(); //Because morse code is defined only for the lower case letters and the numbers and the Symbols will remain the Same
char[] morsec = sentence.toCharArray();
for(int i = 0; i < morsec.length;i++) //The loop will run till i is less than the number of characters in the Sentence because Every Character needs to Be Converted into the Respective Morse Code
{//For Every Letter in the User Input Sentence
for(int j = 0;j<english.length;j++) //For Every Character in the morsec array we will have to traverse the entire English Array and find the match so that it can be represented
{
if(english[j] == morsec[i]) //If the Character Present in English array is equal to the character present in the Morsec array then Only Execute
{//Always remember that the condition in the Inner loop will be the first to be Equated in the If Statement because that will change until the characters match
answer = answer + morse[j] + " "; //After Every Letter is generated in the Morse Code we will give a Space
} //Since the Letters in the English char and the symbols present in the morse array are at the Same Index
}
}
System.out.println("-->The Morse Code Translation is:- ");
System.out.print(">> ");
System.out.println(answer);
System.out.println("");
break;
}
case 2:
{
System.out.println("");
System.out.println("-->Enter the Morse Code and After Every Letter add Space in Between ");
System.out.print("-> ");
sentence = br.readLine();
System.out.println("");
String[] morsec = sentence.split(" "); //To use the split function to Convert Every Morse Code String as a Separate Entry in the STring array
for(int i = 0;i < morsec.length;i++)
{//For Every morse code Letter Entered
//Remember - We are Splitting on the Basis of the space
for(int j = 0;j < morse.length;j++)
{
if(morse[j].equals(morsec[i])) //When you are comparing the String you have to Do this and not ==
{
answer1 = answer1 + english[j]; //Since the characters in the Morse array and the English Array are in the Same Index
}
}
}
System.out.println("-->The English Language Translation is:- ");
System.out.print(">> ");
System.out.println(answer1);
System.out.println("");
break;
}
case 3:
{
System.out.println("");
System.out.println(">>Thank you For Using this Service<<");
System.out.println("");
break;
}
default:
{
System.err.println("-->ERROR<-->Invalid Option Entered<--");
System.out.println("");
break;
}
}
}
while(option!=3);
}
}