3

I want to build a program that translates English to Morse code and visa versa, I have decided to use hash maps to do this, but I'm unsure as to how I could run the string through the hash map and get the translation out at the end. Here is my code at the moment:

import java.util.HashMap;
import java.util.Map;

public class MorseCodeTranslator{

public static String translateToMorseCode() {
    String englishtoMorse = "";
    String translation = null;

    Map<Character, String> morse = new HashMap<Character, String>();
    morse.put('a', "._");
    morse.put('b', "_...");
    morse.put('c',  "_._");
    morse.put('d',  "_..");
    morse.put('e',    ".");
    morse.put('f', ".._.");
    morse.put('g',  "__.");
    morse.put('h', "....");
    morse.put('i',   "..");
    morse.put('j', ".___");
    morse.put('k',   "_.");
    morse.put('l', "._..");
    morse.put('m',   "__");
    morse.put('n',   "_.");
    morse.put('o',  "___");
    morse.put('p', ".__.");
    morse.put('q', "__._");
    morse.put('r', "._.");
    morse.put('s',  "...");
    morse.put('t',   "_");
    morse.put('u',  ".._");
    morse.put('v', "..._");
    morse.put('w',  ".__");
    morse.put('x', "_.._");
    morse.put('y', "_.__");
    morse.put('z', "__..");

    return translation;
}    

public static String translateFromMorseCode() {
    String morsetoEnglish = "";
    String translation = null;

    Map<Character, String> morse = new HashMap<Character, String>();
    morse.put('a', "._");
    morse.put('b', "_...");
    morse.put('c',  "_._");
    morse.put('d',  "_..");
    morse.put('e',    ".");
    morse.put('f', ".._.");
    morse.put('g',  "__.");
    morse.put('h', "....");
    morse.put('i',   "..");
    morse.put('j', ".___");
    morse.put('k',   "_.");
    morse.put('l', "._..");
    morse.put('m',   "__");
    morse.put('n',   "_.");
    morse.put('o',  "___");
    morse.put('p', ".__.");
    morse.put('q', "__._");
    morse.put('r', "._.");
    morse.put('s',  "...");
    morse.put('t',   "_");
    morse.put('u',  ".._");
    morse.put('v', "..._");
    morse.put('w',  ".__");
    morse.put('x', "_.._");
    morse.put('y', "_.__");
    morse.put('z', "__..");  

    return translation;
}
}  

I want to be able to run whatever is in englishtoMorse or morsetoEnglish through the hash map and convert the characters to the value they are associated with in the hash map then output them in translation.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Sinn0n
  • 61
  • 2
  • 1
    Switch the key-value pairs in the `translateFromMorseCode`. If you want to use this approach, move the HashMap initialization to outside the methods. – Maroun Nov 20 '15 at 13:07
  • Other than you want the map to be the other way round for `translateFromMorseCode`, sounds reasonable. Are you encountering a specific problem? – Andy Turner Nov 20 '15 at 13:07
  • That's not enough, since the morse codes are not of equal length. – BetaRide Nov 20 '15 at 13:07
  • Yes that would be a good idea thanks – Sinn0n Nov 20 '15 at 13:08
  • 1
    Also, if you can use Guava, consider putting your mapping in an ImmutableBiMap, so you don't have to maintain both mappings, and build it once-and-for-all and reuse the same map instance. – Andy Turner Nov 20 '15 at 13:08
  • This is the first time I've used hash maps so I'm just unsure how to do it. – Sinn0n Nov 20 '15 at 13:08
  • "I'm just unsure how to do it." What is "it"? – Andy Turner Nov 20 '15 at 13:09
  • A String is basically an array of characters. For each character, you have the morse translation in the map. So all you need is to loop through the characters of the string, get the corresponding morse translation for each character, and concatenate the translations. For morse to english, you need some way to know where the letters start and end, so you need some separator in the string of dots and bars, but the principle is the same. For example 'SOS' could be `.../___/...` – JB Nizet Nov 20 '15 at 13:09
  • I want to be able to run whatever is in "englishtoMorse" or "morsetoEnglish" through the hash map and convert the characters to the value they are associated with in the hash map then output them in "translation" – Sinn0n Nov 20 '15 at 13:10

6 Answers6

3

Create the map as static field. Add the morse alphabet. Then create a method which gets as parameter the text to translate. Then iterate the text to translate every char and create with the translated chars the string which will be returned.

I have made an example with your code and my explanations. The code works only for english text in morse. You must add the other direction.

import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{

    private static final Map<Character, String> morse = new HashMap<Character, String>();
    static {
    morse.put('a', "._");
    morse.put('b', "_...");
    morse.put('c',  "_._");
    morse.put('d',  "_..");
    morse.put('e',    ".");
    morse.put('f', ".._.");
    morse.put('g',  "__.");
    morse.put('h', "....");
    morse.put('i',   "..");
    morse.put('j', ".___");
    morse.put('k',   "_.");
    morse.put('l', "._..");
    morse.put('m',   "__");
    morse.put('n',   "_.");
    morse.put('o',  "___");
    morse.put('p', ".__.");
    morse.put('q', "__._");
    morse.put('r', "._.");
    morse.put('s',  "...");
    morse.put('t',   "_");
    morse.put('u',  ".._");
    morse.put('v', "..._");
    morse.put('w',  ".__");
    morse.put('x', "_.._");
    morse.put('y', "_.__");
    morse.put('z', "__..");
    morse.put(' ', " ");
    }
    public static void main (String[] args) throws java.lang.Exception
    {
        String str = "Hello World";
        System.out.println(translate(str));
    }



    public static String translate(String text) {
        StringBuilder builder = new StringBuilder();
        String lower = text.toLowerCase();
        for (int i = 0; i < text.length(); i++) {
            builder.append(morse.get(lower.charAt(i)));
        }
        return builder.toString();
    }    

}

Output:

......_..._..___ ._____._.._.._..

Working Example:

http://ideone.com/uWGAtU

Zelldon
  • 5,396
  • 3
  • 34
  • 46
1

As for the "English to Morse" use case, use a for loop like this:

StringBuilder sb = new StringBuilder();
for ( int i = 0; i < englishtoMorse.length(); i++) {
    char c = englishtoMorse.charAt(i);
    sb.append(morse.get(c));
}
translate = sb.toString();

As for the "Morse to English" use case, you need some sort of separator between the morse characters. Otherwise you will end up with a translation consisting only of 'e' and 't'. Let's suppose, your morseToEnglish String uses spaces as separator in between the characters. Then you can do the translation like this:

StringTokenizer st = new StringTokenizer(morseToEnglish);
StringBuilder result = new StringBuilder();
while( st.hasMoreTokens()) {
    result.append(morse.findKey(st.nextToken()));
}
translation = sb.toString();

I hope this helped.

inedible
  • 374
  • 3
  • 15
1

You should initialize the map once (e.g., in a static data member, like Zelldon suggested). Once you have done that, a string can be translated from English to morse quite elegantly by using Java 8's streaming APIs:

public static String translateToMorseCode(String english) {
    return english.chars()
                  .boxed()
                  .map(c -> morse.get((char) c.intValue()))
                  .collect(Collectors.joining());
}

EDIT:
As JB Nizet commented, using mapToObj would be more elegant (and efficient, presumably):

public static String translateToMorseCode(String english) {
    return english.chars()
                  .mapToObj(c -> morse.get((char) c))
                  .collect(Collectors.joining());
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • The boxed() call is useless: you unbox the Integer in the following step. – JB Nizet Nov 20 '15 at 13:25
  • @JBNizet without the `boxed()` call you'd have an `IntStream` and the labmda expression would give a compilation error "bad return type in labmda expression: String cannot be converted to an int" . – Mureinik Nov 20 '15 at 13:34
  • https://docs.oracle.com/javase/8/docs/api/java/util/stream/IntStream.html#mapToObj-java.util.function.IntFunction- – JB Nizet Nov 20 '15 at 13:36
  • @JBNizet much more elegant, I concur. The cast to `char` still annoys me, but I'm guessing there's no way to avoid that? – Mureinik Nov 20 '15 at 13:38
0

You may use a BiMap here. I think it is more suitable for your case.

BiMap<Character, String> biMap = HashBiMap.create();

biMap.put('a', "._");
biMap.put('b', "_..");

System.out.println("morse code = " + biMap.get('a'));
System.out.println("alphabet = " + biMap.inverse().get("._"));

You may use guava.Visit the link

Razib
  • 10,965
  • 11
  • 53
  • 80
0

You can use HashMap as you wish:

    import java.util.HashMap;
    import java.util.Map;

    public class MorseCodeTranslator{
    public static Map<Character, String> morse = new HashMap<Character, String>();
    public static Map<String, Character> english = new HashMap<>();
    public MorseCodeTranslator(){
    morse.put('a', "._");
    morse.put('b', "_...");
    morse.put('c',  "_._");
    morse.put('d',  "_..");
    morse.put('e',    ".");
    morse.put('f', ".._.");
    morse.put('g',  "__.");
    morse.put('h', "....");
    morse.put('i',   "..");
    morse.put('j', ".___");
    morse.put('k',   "_.");
    morse.put('l', "._..");
    morse.put('m',   "__");
    morse.put('n',   "_.");
    morse.put('o',  "___");
    morse.put('p', ".__.");
    morse.put('q', "__._");
    morse.put('r', "._.");
    morse.put('s',  "...");
    morse.put('t',   "_");
    morse.put('u',  ".._");
    morse.put('v', "..._");
    morse.put('w',  ".__");
    morse.put('x', "_.._");
    morse.put('y', "_.__");
    morse.put('z', "__..");
    morse.forEach( (c,s) -> english.put(s, c));
    }


    public static String translateToMorseCode(final String english) {
    char[] data = english.toCharArray();
    StringBuilder result = new StringBuilder();
    for(char c: data) result.append(morse.get(new Character(c)));
    return result.toString();
    }

    public static String translateFromMorseCode(final String morseCode) {
    String[] data = morseCode.split(" ");
    StringBuilder result = new StringBuilder();
    for(String s:data) result.append(english.get(s));
    return result.toString();
    }
    }
SalaryNotFound
  • 224
  • 1
  • 8
0

Use one table and do a backward search with Map.entrySet(). And don't forget a separator token.

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

public class MorseCodeTranslator{
    public static Map<Character, String> getMorseTable(){
        Map<Character, String> morse = new HashMap<Character, String>();
        morse.put('a', "._");
        morse.put('b', "_...");
        morse.put('c',  "_._");
        morse.put('d',  "_..");
        morse.put('e',    ".");
        morse.put('f', ".._.");
        morse.put('g',  "__.");
        morse.put('h', "....");
        morse.put('i',   "..");
        morse.put('j', ".___");
        morse.put('k',   "_.");
        morse.put('l', "._..");
        morse.put('m',   "__");
        morse.put('n',   "_.");
        morse.put('o',  "___");
        morse.put('p', ".__.");
        morse.put('q', "__._");
        morse.put('r', "._.");
        morse.put('s',  "...");
        morse.put('t',   "_");
        morse.put('u',  ".._");
        morse.put('v', "..._");
        morse.put('w',  ".__");
        morse.put('x', "_.._");
        morse.put('y', "_.__");
        morse.put('z', "__..");
        return morse;
    }
    public static String toMorse(String text){      
        Map<Character, String> table  = getMorseTable();
        StringBuilder result = new StringBuilder();
        // get every char in text
        for(int i = 0; i < text.length(); i++){
            char c = text.charAt(i);
            // and add morse character from table
            result.append(table.get(c));
            // put character separator
            result.append("|");
        }
        // delete last character separator
        result.deleteCharAt(result.length() - 1);
        return result.toString();
    }

    public static String fromMorse(String morse){
        Map<Character, String> table  = getMorseTable();
        // use string tokenizer to separate morse characters
        StringTokenizer st = new StringTokenizer(morse,"|");
        StringBuilder result = new StringBuilder();
        // get every morse character
        while( st.hasMoreTokens()) {
            String morseChar = st.nextToken();
            // and find equivalent letter in morse table
            for (Entry<Character, String> entry : table.entrySet()) {
                if (entry.getValue().equals(morseChar)) {
                   result.append(entry.getKey());
                   break;
                }
            }
        }
        return result.toString();
    }

    public static void main(String[] args){
        String text = "abcxyz";
        System.out.println(text);
        String morse = toMorse(text);
        System.out.println(morse);
        String back = fromMorse(morse);
        System.out.println(back);
    }
}

Output:

abcxyz
._|_...|_._|_.._|_.__|__..
abcxyz
ArcticLord
  • 3,999
  • 3
  • 27
  • 47