[우아한테크코스] 착한 문제(?)에 그렇지 못한 코드 (1)

진승범·2022년 11월 5일
0

소감


1주차 온보밍 미션 기간이 끝이 났다.. 하지만 곧바로 2주차 START~
돌이켜보면 후회가 가장 많이 남은 한 주 였다. 문제의 난이도보다는 클린코드를 작성하기 위한 몸부림을 많이 쳤던 거 같다. 뭐 다소 까다로운 문제들도 있었지만, 모두 재미있는 문제들이었다. 이번 회고록에서는 각 문제에 대한 나의 느낌과 소감을 공유해보려고 한다.

문제 풀이에 관한 코드 Github
https://github.com/jindaram-stu/java-onboarding/tree/jindaram-stu/src/main/java/onboarding

📢 1번 문제

가장 먼저 친숙한 이름들이 나와 반가웠다. 가끔가다 코딩테스트 관련 문제를 살펴보면, 되게 딱딱한 문제들도 있지만, 1번 문제처럼 친숙한 소재를 가지는 문제들이 많은 걸 느끼곤 한다. 그런 부분들이 해당 문제와 조금 가깝게 느끼게 해주는 거 같다. 포비와 크롱.. 기억하겠어 😂
문제 난이도는 그닥 높진 않았지만, 예외 케이스를 한도 끝도 없이 생각하다보니 코드가 길어지는 걸 느꼈다. 조건문을 반복해서 사용해야 할 일이 있었는데, 한 줄로 표현 가능한 IF문을 작성할까 했었지만, 많은 사람들이 쓰는 IF문 형식을 유지해야 가독성이 좋을 거 같아서, 일부러 늘어뜨려 작성했다. 잘한 건지는 모르겠지만, 나만 보는 코드가 아닌 같이 보는 코드라는 생각을 하며 첫 문제 풀이를 시작했다.

📢 2번 문제

개인적으로 조금 난이도가 있었던 문제였다. 문제를 잘 사펴보니 문자들을 삭제하는 과정을 설명해주신 것이 큰 도움이 되었다. 처음엔 두 문자만 처리하는 줄 알았지만, 슬랙에 도는 흉흉한 소문들을 확인해보니 두 문자 이상이 반복되는 모든 경우에 대해서 처리를 하는 것이었다. 나는 Stack을 활용하여 문제를 풀었다. Stack의 peek() 값과 현재 위치한 인덱스의 문자가 같으면 반복 카운트를 +1 하여 Stack의 peek()과 현재 위치한 인덱스 문자가 다를 때 반복 카운트 만큼 Stack을 제거하는 로직으로 풀었다. 2번 문제에서 코드를 간단하게 구성하는 것이 중요하지만 그렇게 하기 위해선 로직도 간단해야 한다는 것을 느꼈다. 로직이 복잡하다면 메소드로 분리하기도 애매하고, 분리했을 때 파라미터가 너무 많아진다는 것을 느꼈다. 가장 간단한 로직을 작성해야 클린하게 코드를 짜기 편한 걸 깨달았다!

📢 3번 문제

3번 문제는 조금 쉽게 풀 수 있었다. 숫자를 문자열로 파싱한 뒤에 3,6,9가 각각 들어가는 부분을 계산하면 쉽게 문제를 풀 수 있다! 코드가 간단해서 첨부해보겠다!

public class Problem3 {
    public static int solution(int number) {
        int resultClap = 0;
        for (int i=1; i<=number; i++) {
            String stringNumber = String.valueOf(i);
            int threeCount = count(stringNumber,"3");
            int sixCount = count(stringNumber,"6");
            int nineCount = count(stringNumber,"9");

            resultClap += threeCount + sixCount + nineCount;
        }
        return resultClap;
    }

    public static Integer count(String number, String clapCondition) {
        return number.length() - number.replace(clapCondition,"").length();
    }
}

📢 4번 문제

문제를 보며 가장 먼저 청개구리는 역순으로 변환을 하니, 스펠링에 늘어뜨려 놓은 문자열을 선언한 뒤, 뒤에서부터 계산하면 되겠다는 생각이 떠올랐다. 그리고 알파벳인 경우에만 위 로직을 적용해야 하므로, 변환 전에 추출한 Character가 문자인지도 확인하는 메소드도 추가했다. 비교적 로직이 간단해서 메소드를 분리하기 편했고 깔끔하게 작성한(?) 문제라고 생각한다. (아마두) 😊

📢 5번 문제

어디서 많이 본 것 같은 문제다. 나의 경우 Cash에 해당하는 [50,000원, 10,000원, 5,000원, 1,000원, 500원, 100원, 50원, 10원, 1원] 을 상수로 정의해두고, 반복을 통해 money를 계산했다. 각각의 몫을 ArrayList에 추가했당! 개인적으로 제일 간단하게 풀 수 있었던 문제!

📢 6번 문제

갑자기 팍 올라간 문제의 난이도..! 문제를 보자 2글자씩 나눈 뒤 어딘가에 저장하여 매번 검사해야 한다는 사실을 떠올렸으나, 실제 구현에 애를 먹었다. 2글자씩 나눈 값이 저장한 공간에 존재하지 않는다면, 넘어가고 존재한다면 존재하는 crew의 이메일을 List에 추가하려 했으나, 그렇다면 기존 crew가 추가되지 않는다는 사실을 깨달았다. 문제를 해결하려 깊게 고민하다보니, Map의 key, value로 해결할 수 있었다. Map의 containsKey() 메소드로 닉네임을 2글자로 분리한 것이 있는지 없는지 확인할 수 있었고, value에는 나눈 유저의 이메일을 넣어두었다. 그래서 다음 코드와 같이 해결할 수 있었다. 😊

if (segments.containsKey(word)) {
    emails.add(segments.get(word));
    emails.add(crewEmail);
}
if(!segments.containsKey(word)) {
    segments.put(word,crewEmail);
}

그렇게 잘 풀리나 싶었지만.. 테스트케이스를 공유하는 슬랙 채널을 확인해보니 "두근두근"과 같이 동일한 닉네임에서 반복하는 결과에 대한 테스트케이스를 발견했다. 결국 해당 테스트케이스에 대해서는 예외처리를 진행하지 못했다. 앞으로는 어떤 값들이 들어올 수 있는지 문제성향과 잘 파악하며 풀이를 진행해야겠다.. 😂

📢 7번 문제

6번 문제를 보고 잔뜩 쫄았지만 은근(?) 어렵지 않게 구현할 수 있었던 문제였다. 먼저 다음과 같은 순서도를 생각했다.
1. user와 친구인 부분과 친구가 아닌 부분 분리하기
2. ②에서 분리한 친구 관계 중 user의 친구가 한 명만 존재한다면 나머지 친구에게 +10점 부여
3. 방문한 이들 중 user의 친구를 제외한 이들에게 +1점 부여
4. Comparator을 이용한 커스텀 정렬 후 리턴
그리고 이를 유의하면서 구현하다보니 금방 구현할 수 있었다.


회고

1주차가 무사히(?) 끝났다. 다소 코딩테스트와 같은 느낌이 있었지만, 시간이 너무나도 넉넉하여 못 푼 문제는 없었다. 하지만 시간이 많은 만큼 코드의 가독성과 성능에 대한 타협점을 찾느라 애를 많이 먹었던 시간이었던 것 같다. 그런만큼 개발에 대한 시각을 나만 하는 것이 아닌, 남과 같이 한다는 시각을 가지게 되었고 그런만큼 코드의 성능보다 유지보수와 가독성이 좋은 코드도 중요하다는 것을 깨달을 수 있는 한 주였다. 어떤 미션이 앞으로 출제될지는 모르겠지만 남은 3번의 미션동안 이 점을 유의하여 미션을 수행해야겠다! 좋은 결과를 낳지 않더라도, 최선을 다한 만큼 후회없는 시간이 되었으면 좋겠다. 👍 그리고 4주동안 같이 진행하는 분들도 열심히 힘냈으면 좋겠다!!

0개의 댓글