Codewars 문제풀기 (04/13)

Decode the Morse code

  • 모스 부호로 이루어진 String을 인자로 받는다.
  • 모스 부호를 영문자로 바꾸는 메서드를 구현한다.
  • decode(“…. . -.– .— ..- -.. .”) –> “HEY JUDE”
  • 출력문자는 대문자로 가정한다.
  • 모스 부호는 문자간 space 1개 단어간 space 3개로 구분한다.

1. Test와 리팩토링

  • 테스트 1 - 입력 인자가 1개의 문자를 나타내는 모스 부호일 경우 문자 하나만 리턴한다. (A, B, C, 1, 2 등..)

    • 테스트 코드

      @Test
      public void testShouldDecodeAlphabet() {
        // Given: Set String one character
        String given = ".-";
        // When: Call decode method
        String actual = MorseCodeDecoder.decode(given);
        // Then: Should Return A
        assertEquals("A", actual);
      }
      
    • 실제 코드

      import java.util.HashMap;
      import java.util.Map;
          
      public class MorseCodeDecoder {
          
        static Map<String, String> morseCodeMap = new HashMap<>();
          
        public static String decode(String morseCode) {
          makeMorseCodeMap();
          return morseCodeMap.get(morseCode);
        }
          
        private static void makeMorseCodeMap() {
          morseCodeMap.put(".-", "A");
          morseCodeMap.put("-...", "B");
          morseCodeMap.put("-.-.", "C");
          morseCodeMap.put("-..", "D");
          morseCodeMap.put(".", "E");
          morseCodeMap.put("..-.", "F");
          morseCodeMap.put("--.", "G");
          morseCodeMap.put("....", "H");
          morseCodeMap.put("..", "I");
          morseCodeMap.put(".---", "J");
          morseCodeMap.put("-.-", "K");
          morseCodeMap.put(".-..", "L");
          morseCodeMap.put("--", "M");
          morseCodeMap.put("-.", "N");
          morseCodeMap.put("---", "O");
          morseCodeMap.put(".--.", "P");
          morseCodeMap.put("--.-", "Q");
          morseCodeMap.put(".-.", "R");
          morseCodeMap.put("...", "S");
          morseCodeMap.put("-", "T");
          morseCodeMap.put("..-", "U");
          morseCodeMap.put("...-", "V");
          morseCodeMap.put(".--", "W");
          morseCodeMap.put("-..-", "X");
          morseCodeMap.put("-.--", "Y");
          morseCodeMap.put("--..", "Z");
          morseCodeMap.put(".----", "1");
          morseCodeMap.put("..---", "2");
          morseCodeMap.put("...--", "3");
          morseCodeMap.put("....-", "4");
          morseCodeMap.put(".....", "5");
          morseCodeMap.put("-....", "6");
          morseCodeMap.put("--...", "7");
          morseCodeMap.put("---..", "8");
          morseCodeMap.put("----.", "9");
          morseCodeMap.put("-----", "0");
        }
      }
          
      
      • 위키피디아를 보고 모스부호 맵을 만들었다. 알파벳에 대한 테스트 때문에 A~Z, 0~9까지 추가했다.
  • 테스트 2 - 입력인자가 1개의 단어를 나타내는 모스부호일 경우 복호한 단어를 리턴해야한다.

    • 테스트 코드

      @Test
      public void testShouldDecodeMoreThan2Words() {
        // Given: Set String one word
        String given = ".--- .. -. .... --- ....-   -... .- -... ---";
        // When: Call decode method
        String actual = MorseCodeDecoder.decode(given);
        // Then: Should Return JINHO4 BABO
        assertEquals("JINHO4 BABO", actual);
      }
      
    • 실제 코드

      import java.util.HashMap;
      import java.util.Map;
          
      public class MorseCodeDecoder {
          
        static Map<String, String> morseCodeMap = new HashMap<>();
          
        public static String decode(String morseCode) {
          makeMorseCodeMap();
          String[] eachCharacter = morseCode.split(" ");
          String result = "";
          for(String character : eachCharacter) {
            result += morseCodeMap.get(character);
          }
          return result;
        }
      }
      
      • 모스부호 문자간 1개의 space로 구분되어있기 때문에 split(“ “)으로 각 문자를 추출 후 result에 붙였다.
  • 테스트 3 - 입력인자가 2개이상의 단어를 나타내는 모스부호일 경우, 단어들을 복호하여 리턴한다.

    • 테스트 코드

      @Test
      public void testShouldDecodeOneWord() {
        // Given: Set String one word
        String given = ".--- .. -. .... --- ....-";
        // When: Call decode method
        String actual = MorseCodeDecoder.decode(given);
        // Then: Should Return JINHO4
        assertEquals("JINHO4", actual);
      }
      
    • 실제 코드

      import java.util.HashMap;
      import java.util.Map;
          
      public class MorseCodeDecoder {
          
        static Map<String, String> morseCodeMap = new HashMap<>();
          
        public static String decode(String morseCode) {
          makeMorseCodeMap();
          String[] morseWords = morseCode.split("   ");
          String result = "";
          for (String morseWord : morseWords) {
            String[] morseChars = morseWord.split(" ");
            for (String morseChar : morseChars) {
              result += morseCodeMap.get(morseChar);
            }
            result += " ";
          }
          return result.trim();
        }
      }
          
      
      • 모스부호 단어간 space 3개로 구분지어져있기 때문에 split(“ “)으로 각 모스부호 단어를 추출 후 단어마다 다시 문자를 추출하여 result에 붙였다.
    • 리팩토링 - 각 문자 복호는 함수로 추출, String대신 StringBuilder 사용

      import java.util.HashMap;
      import java.util.Map;
          
      public class MorseCodeDecoder {
          
        static Map<String, String> morseCodeMap = new HashMap<>();
          
        public static String decode(String morseCode) {
          makeMorseCodeMap();
          String[] morseWords = morseCode.trim().split("   ");
          StringBuilder result = new StringBuilder();
          for (String morseWord : morseWords) {
            result.append(decodeMorseWord(morseWord)).append(" ");
          }
          return result.toString().trim();
        }
        private static String decodeMorseWord(String morseWord) {
          StringBuilder result = new StringBuilder();
          String[] morseCharacters = morseWord.split(" ");
          for (String morseCharacter : morseCharacters) {
            result.append(morseCodeMap.get(morseCharacter));
          }
          return result.toString();
        }
      }
      
      • 제출(리팩토링 제외 약 30분 소요)

2. 답 비교, 느낀점

Best Practice 가장 많이 받은 코드

public class MorseCodeDecoder {
    public static String decode(String morseCode) {
      String result = "";
      for(String word : morseCode.trim().split("   ")) {
        for(String letter : word.split("\\s+")) {
          result += MorseCode.get(letter);
        }
        result += ' ';
      }
      return result.trim();
    }
}
  • 문제 자체는 같은 방식으로 해결했는데 split()메서드에서 space를 기준으로 문자들을 쪼갠것이 아니고 “\s+”로 공백이 없는 문자열 기준으로 쪼갰다.

댓글남기기