Проблемы с декодированием азбуки Морзе с использованием HashMaps.

Мой код отлично работает при кодировании обычного текста в азбуку Морзе, но когда я пытаюсь перевести другим способом, я получаю ошибку индекса за пределами границ. Не знаю, почему?

import java.util.HashMap;
public class MorseCode {
private final String alphabet = "abcdefghijklmnopqrstuvwxyz0123456789 ";
private final String[] morse = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
        ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....",
        "-....", "--...", "---..", "----.", "-----", "|"};
private HashMap<String, String> toText;
private HashMap<String, String> toCode;

public MorseCode() {
    toText = new HashMap<>();
    toCode = new HashMap<>();
    char[] alphaArray = alphabet.toCharArray();
    for(int i = 0; i < morse.length; i++) {
        toCode.put(morse[i], String.valueOf(alphaArray[i]));
        toText.put(String.valueOf(alphaArray[i]), morse[i]);
    }

}

public String encode(String s) {
    s = s.toLowerCase();
    String encoded = "";
    char[] chars = s.toCharArray();
    for(int i = 0; i < s.length(); i++) {
        for (HashMap.Entry<String, String> entry : toCode.entrySet()) {
            if (String.valueOf(chars[i]).equals(entry.getValue())) {
                encoded += entry.getKey() + " ";
            }
        }
    }

    return encoded;
}

public String decode(String s) {
    s = s.toLowerCase();
    String decoded = "";
    for(int i = 0; i < s.length(); i++) {
        for (HashMap.Entry<String, String> entry : toText.entrySet()) {
            if (morse[i].equals(entry.getValue())) {
                decoded += entry.getKey();
            }
        }
    }

    return decoded;
}

}

Пытаясь найти решение, которое работает в обоих направлениях, любая помощь/совет будут оценены!


person Ridge Haven    schedule 14.12.2016    source источник
comment
Вы должны заменить morse[i] на s.charAt(i) в своем методе декодирования.   -  person Erwin Bolwidt    schedule 14.12.2016
comment
Попытка применить одну и ту же логику в обоих направлениях не сработает. т.е. почему вы называете s.toLowerCase() азбукой Морзе для расшифровки? Вы добавляете пробелы в закодированный вывод, как вы удаляете эти пробелы? Пробовали ли вы писать какой-нибудь псевдокод, чтобы направлять ваши шаги?   -  person rafaelbattesti    schedule 14.12.2016


Ответы (1)


Я протестировал этот код, и он работает. Имейте в виду, что это очень рудиментарная реализация, но она правильно использует некоторые удобства класса HashMap. Настоятельно советую запускать в режиме отладки и отслеживать значения переменных.

import java.util.HashMap;

public class MorseCode {

    //Constants hold the accepted characters
    private final String alphabet = "abcdefghijklmnopqrstuvwxyz0123456789 ";
    private final String[] morse = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---",
        ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", ".----", "..---", "...--", "....-", ".....",
        "-....", "--...", "---..", "----.", "-----", "|"};

    //Maps map the code to text and text to code
    private HashMap<String, String> toText;
    private HashMap<String, String> toCode;

    //Problem: toText had text as keys. Keys should be used to identify the value your want to get.
    //Solution: swapped toText logic to toCode logic
    public MorseCode() {
        toText = new HashMap<>();
        toCode = new HashMap<>();
        char[] alphaArray = alphabet.toCharArray();
        for(int i = 0; i < morse.length; i++) {
            toText.put(morse[i], String.valueOf(alphaArray[i]));
            toCode.put(String.valueOf(alphaArray[i]), morse[i]);
        }
    }

    //Problem: kind of complicated logic. Was working, but did not need all that truncation
    //Solution: HashMap contains neat methods to work with keys - get(key) and containsKey(key)
    //In this solution, if the key is not found, we print the plain text character
    public String encode(String s) {
        s = s.toLowerCase();
        String encoded = "";
        for(int i = 0; i < s.length(); i++) {
            String c = String.valueOf(s.charAt(i));
            if (toCode.containsKey(c)) {
                encoded += toCode.get(c) + " ";
            } else {
                encoded += c;
            }
        }
        return encoded;
    }

    //Problem: logic was broken. Again, you are mapping the key to the value you want in toText, so use it.
    //Solution: Same logic than the encode method, but we had to strip off the spaces
    public String decode(String s) {
        String[] code = s.split(" ");
        String decoded = "";
        for(int i = 0; i < code.length; i++) {
            if (toText.containsKey(code[i])) {
                decoded += toText.get(code[i]);
            } else {
                decoded += "?";
            }
        }
        return decoded;
    }
}

Тестовый код в основном методе. Этот тест действительно должен учитывать все граничные случаи (специальные символы, несколько пробелов, пустые строки и т. д.) и сравнивать ввод с ожидаемым выводом. Но уже слишком поздно для этого. :-)

public class Main {
    public static void main(String[] args) {
        MorseCode m = new MorseCode();
        String encoded = m.encode("Unencoded Text");
        String decoded = m.decode("..- -. . -. -.-. --- -.. . -.. | - . -..- - ");
        System.out.println(encoded);
        System.out.println(decoded);

    }
}

Ваше здоровье.

person rafaelbattesti    schedule 14.12.2016