220826 코딩테스트-숫자 문자열과 영단어

샨티(shanti)·2022년 8월 26일
0

TIL

목록 보기
83/145

하루를 마무리 하기 전, 오늘 있었던 일들을 잔잔히 되짚어봅니다.
성공과 실패의 모든 요소에서 '배울 점'을 찾아내어 기록하고,
더 성장하는 내일의 나를 위해 'action plan'을 세웁니다.

음. 오늘 뽀모도로 시트는 정말 차마 올릴 수 없는 상태라 패스 ㅎ.ㅎ
일부러 적지 않은 건 아닌데 거의 적은 것이 없어서 올리기가 좀 민망타. 굳이 하얀 종이 얹어서 자리 채울 필요는 없겠으니 패스.

데일리 코딩 도장! 오늘은 프로그래머스에서 제공된 '숫자 문자열과 영단어' 라는 문제를 풀어보았다.
어제 로지님과 근 2시간 함께 이야기를 나누면서 내가 '작업단위'를 아주 잘게 쪼개지 못한다는 사실을 다시한번 확인했다.

아이가 30분 넘게 울고 있는 바람에 노아님과의 면담을 중간에 일방적으로 끊고 아이를 달래러 갈수밖에 없었는데.. 그 때도 여러 이야기를 나누면서 결국 작은 단위로 해보는 것의 중요함을 다시한번 꺠달았다.

결국 해보지 않으면 안될 일. 오늘 코딩도장을 할 때부터 예전에는 했었지만 지금은 하지 않는 '주석 달기'를 실천했다.

우선 카카오 채용연계형 인턴십 기출문제라는 것이 헉~ 스러웠지만
사실 따지고보면 내 코드가 좋건, 좋지 않건 풀어낼 수 있다면야 풀어낼 수 있는 문제겠지.
나는 '완벽한' 그린을 보는 것을 포기하고 작은 단위로 빠르게 그린을 본 뒤 리팩터링을 하는 방향성을 추구해야한다는 사실을 계속 리마인드 했다.

그렇게 시작된 오늘의 코딩도장.
결론적으론 '자바스크립트'로는 풀지 못했고 '자바'로만 풀었는데, 작업단위를 잘게 쪼개고 또 테스트코드를 작성하다보니 문제를 풀어내긴 풀어냈다.
사실 풀어내고도 신기했다. 아하.. 이걸 할 수 있구나. 이런 너낌.

우선 달아놓은 주석을 아래와 같이 첨부한다.

정말 많이 쪼개려고 노력해봤다.
중간에 생각이 자꾸 스-윽 넘어가려 할때면 어제 로지님이 팝에서 보여준 const rosieNumber=6을 떠올렸다.

사실 보면서도 '이렇게까지 하는게 말이 되나?' 싶을 만큼 당황스러운 변수 선언이었는데 작업단위를 쪼갠다는 건, 그리고 아주 작은 것을 성공시킨다는 것은 지금 내가 하는 방식과는 완전히 역행해야 하는 것이었기에 조급한 마음을 내려놓았다.

그리고 생각할 수 있는 경우의 수를 굉장히 잘게 나누었다.
특히 문자+숫자로 구성된 문자열이 제시되는 경우의수는 생각할 것이 많기 때문에 그 경우의 수 역시 제외하고 내가 가장 빠르게 할 수 있는 최소한의 작업단위, 해결할 수 있는 문제의 단위는 무엇이 있을까를 고민했다.

그렇게 탄생한 첫 번째 코드뭉터기.ㅎ

한 자리 숫자가 입력될 때 그 숫자가 문자열이라면 문자에 해당하는 숫자를 반환하고, 그렇지 않은 경우. 즉 한 자리 숫자가 문자가 아니라는 말은 결국엔 숫자로 반환될 수 있다는 이야기이니 바로 형변환을 하여 리턴할 수 있도록 만들었다.

계속 테스트 코드도 돌리고, 또 주석에도 써놓기는 했지만 자바에서 형변환을 할 때 어떤 오류를 뱉어내는지도 궁금해서 테스트코드로 돌려봤다.

자바스크립트는 자바보다는 (내 생각에) 약간은 덜 strict한 부분이 있어서 형 변환이나 또는 잘못된 명령을 실행할 때 다짜고짜 프로그램을 죽이는(;;) 일은 덜한 것 같다.

뭐 예를들어, 숫자가 아닌데 숫자로 뱉어내게 하려고 시도한다면 NaN을 뱉어낸다던지.. 여튼 프로그램이 돌아가게는 만들어주는데, 혹시나 자바도 그런 마음의 여유가 있는지(?) 물어보았더니. 그런거 없댄다.

NumberFormat Exception같은 메시지를 뱉어낸 걸로 기억한다.

뭐 쨌든, 강제 형변환은 불가능한걸로 판별되었으니 한자리 수가 입력되었을 때의 문제는 스위치로 해결했는데...
이제는 4가지 경우의 수를 가진 두자리 숫자 입력을 받았을 때!! 나는 어떻게 해야할 것인가...

  • 2개의 숫자로만 구성된 문자열
  • 숫자 + 문자열로 구성된 문자열
  • 문자열 + 숫자로 구성된 문자열
  • 문자열 + 문자열로 구성된 문자열

이리저리 고민하다가 잘 써보지 않은 '아스키코드'를 활용해봐야겠다 싶어서 주섬 주섬 구글을 켜고 아스키코드 테이블을 봤다.
이 때 약간 졸려서 ;; 테이블을 해석하는데 시간이 좀 걸렸지만 그래도 어떻게든 어제 배운대로 작업 단위를 쪼개고, 테스트를 돌리며 연습해봐야겠다는 생각에 꾸역 꾸역 문제를 풀었다.

마음의 허들을 계속 낮춰야 해서.. 우선 가장 쉬워보이는 첫번째 경우의 수를 해결하고 또 생각을 거듭하다가 어차피 숫자가 10개밖에 되지 않으니 하드코딩에 중복되는 코드가 많더라도 경우의 수를 나눠서 생각해보기로 했다.

각 숫자의 영문 첫번째 글자가 unique한 몇 개의 수(ex. zero, one 등), 그리고 그렇지 않은 수들로 나누어 또다시 경우의 수를 만들었다.

결국 경우의 수가 많아져서 내 코드는 if 파티가 되었지만 놀랍게도 문제를 풀 수 있었다. 막판에 계속 테스트가 터져서 왜그런가? 고민하고 있었는데, 어쩌면 continue가 빠져서 그럴수도 있겠다는 생각에 모든 if문이 끝나는 시점에 발생할 수 있는 에러차단용으로 continue까지 선물로 드림.

시간이 약간 지나긴 했지만 다 풀고나서 동료 코드를 봤는데 더욱더 놀랍게도 replace()라는 멋진 함수가 있더라. 정말 나는 1시간 30분을 개 똥 삽질을 했구나(ㅋㅋ) 할만큼 벙 쪘는데.
역시 아는것이 힘이구나. 시간도 노력도 아주아주 줄일 수 있는.

하지만 지금 내게 필요한 건 라이브러리, 메소드 관련 지식이기도 하지만, 결국 '작업단위를 쪼개는 생각의 근육'이 강화되는 것, 그리고 코딩에 대한 심리적 허들을 지속적으로 낮추는 것이 아닐까 싶다.

경험이 쌓이는 것은 결국 '해보고' '지속하여' '시간을 보내야' 하는 것을 전제로 하기에. 오늘부터 많은 부분에서 작업단위를 쪼개는 연습을 지속하고자 한다.

코딩도장을 코딩도장답게 풀기. 잊지말자.

위에 넣은 '주석'을 제외하고 오늘 풀어본 문제에 대한 코드를 아래에 첨부한다.

제출한 답안

class Solution {
  public int solution(String s) {
    int answer = 0;

    String tempNumber = "";

    for (int i = 0; i < s.length(); i += 1) {
      int asciiCodeNumber = s.charAt(i);

      if (asciiCodeNumber >= 48 && asciiCodeNumber <= 57) {
        tempNumber += s.charAt(i) + "";
      }

      if (asciiCodeNumber == 122) {     // zero는 유니크
        tempNumber += "0";
        i += 3;
        continue;
      }

      if (asciiCodeNumber == 111) {     // one 유니크
        tempNumber += "1";
        i += 2;
        continue;
      }

      if (asciiCodeNumber == 101) {     // eight 유니크
        tempNumber += "8";
        i += 4;
        continue;
      }

      if (asciiCodeNumber == 110) {     // nine 유니크
        tempNumber += "9";
        i += 3;
        continue;
      }

      if (asciiCodeNumber == 116) {     // 2와 3의 구별
        if (s.charAt(i + 1) == 119) {
          tempNumber += "2";
          i += 2;
          continue;
        }

        if (s.charAt(i + 1) == 104) {
          tempNumber += "3";
          i += 4;
          continue;
        }
      }

      if (asciiCodeNumber == 102) {     // 4와 5의 구별
        if (s.charAt(i + 1) == 105) {
          tempNumber += "5";
          i += 3;
          continue;
        }

        if (s.charAt(i + 1) == 111) {
          tempNumber += "4";
          i += 3;
          continue;
        }
      }

      if (asciiCodeNumber == 115) {     // 6와 7의 구별
        if (s.charAt(i + 1) == 105) {
          tempNumber += "6";
          i += 2;
          continue;
        }

        if (s.charAt(i + 1) == 101) {
          tempNumber += "7";
          i += 4;
          continue;
        }
      }

      if (i >= s.length() - 1) {
        break;
      }
    }

   	  answer = Integer.parseInt(tempNumber);
      return answer;
      }
    }

테스트

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class SolutionTest {
  @Test
  void onlyNumbers() {
    Solution solution = new Solution();

    assertEquals(123, solution.solution("123"));
  }

  @Test
  void inputStringNumberUnder10() {
    Solution solution = new Solution();

    assertEquals(8, solution.solution("eight"));
    assertEquals(5, solution.solution("five"));
  }

  @Test
  void inputStringNumberUnder100() {
    Solution solution = new Solution();

    assertEquals(38, solution.solution("38"));
    assertEquals(301, solution.solution("3zeroone"));
    assertEquals(819, solution.solution("eightonenine"));
    assertEquals(38, solution.solution("threeeight"));
  }
}
profile
가벼운 사진, 그렇지 못한 글

0개의 댓글