코드로 문제해결 연습 > 프로그래머스 > 바탕화면 정리

주싱·2023년 3월 6일
0

문제

링크 : 프로그래머스 > Level 1 > 바탕화면 정리

문제 해결 코드

import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

class Solution {
    public int[] solution(String[] wallpaper) {
        return new int[]{
                top(wallpaper),
                left(wallpaper),
                bottom(wallpaper) + 1,
                right(wallpaper) + 1
        };
    }

    private static int left(String[] wallpaper) {
        int left = Arrays.stream(wallpaper)
                        .mapToInt(line -> line.indexOf('#'))
                        .filter(find -> find != -1)
                        .min()
                        .orElse(-1);
        assert left != -1;
        return left;
    }

    private static int top(String[] wallpaper) {
        int top = IntStream.range(0, wallpaper.length)
                .filter(i -> wallpaper[i].contains("#"))
                .findFirst()
                .orElse(-1);
        assert top != -1;
        return top;
    }

    private static int right(String[] wallpaper) {
        int right = Arrays.stream(wallpaper)
                .mapToInt(line -> line.lastIndexOf('#'))
                .filter(find -> find != -1)
                .max()
                .orElse(-1);
        assert right != -1;
        return right;
    }

    private static int bottom(String[] wallpaper) {
        int bottom = IntStream.iterate(wallpaper.length - 1, i -> i - 1).limit(wallpaper.length)
                .filter(i -> wallpaper[i].contains("#"))
                .findFirst()
                .orElse(-1);
        assert bottom != -1;
        return bottom;
    }
}

회고

가. 문제를 바르게 이해하라

어떻게 해결할지 보다, 문제 자체를 바르게 이해하지 못해서 혼란을 겪은 부분이 컸던 것 같다. 크게 아래 3가지 내용에 혼돈을 겪어 문제를 어렵게 바라보게 되었다.

  • 파일들이 근접(위, 아래, 대각선 방향)해 있지 않은 경우 두 번 이상의 드래그 행위로 최적화된 드래그를 해야한다고 생각하고 문제에 접근했다. 그러나 그게 아니라 어떻게든 최소 거리로 한 번에 드래그 하는 문제였다. 이를 잘못 이해한 덕분에 무척 어려운 문제라 생각해서 혼자서 푸는 걸 포기하는 순간을 만났다. ChatGPT에게 문제를 주고 가이드를 받아 보았는데 첫 문장부터 한 번의 드래그라는 문제 접근법을 보고 ChatGPT의 가이드를 덥고 다시 문제에 접근했다. 이 사실을 이해하고 나니 무척 쉬운 문제 였음을 깨달았다. 결과적으로 배경화면에서 단순하게 파일이 존재하는 가장 위, 왼쪽, 아래, 오른쪽을 찾고 드래그할 좌표점으로 변환해서 반환하면 되는 문제 였다.
  • 파일이 위치한 격자칸(인덱스 1이 기준)과 배경화면의 좌표가 되는 격자점(인덱스 0이 기준)의 개념을 분리해서 이해하지 못했다. 문제를 차분히 꼼꼼히 읽지 못한 것 같다. 문제에서는 드래그 해야할 격자점을 반환하라고 하는데 입력 받은 wallpaper 정보는 격자칸 정보였음으로 혼란을 겪었다. 처음에 격자칸에 대한 개념만 가지고 문제에 접근하자 만약에 격자칸 한 칸(i, j)에만 파일이 있다면 드래그 해야할 격자점은 (i, j, i, j)라는 드래그가 필요 없는 상태가 되었다. 격자점을 드래그한다는 개념을 제대로 이해했다면 (i, j, i+1, j+1)와 같이 생각했을 것이다. 이 제약사항은 1칸만 존재하는 예제를 다시 읽다보니 바르게 개념이 정립되었다.
  • 세로 좌표(수직으로 변하는)를 x라고 표현하고 가로 좌표(수평으로 변하는)를 y라고 표현한 점도 문제를 푸는데 혼돈을 준 것 같다. 보통 수학식의 XY 평면에서 수직으로 변하는 좌표는 Y가 되고 수평으로 변하는 좌표는 X가 된다. (문제와는 반대) 반면에 프로그래밍 언어(Java)의 이차원 배열 표현식에서는 수직으로 변하는 방향을 X라고 특정 문자와 매핑하지는 않고 문제에서 처럼 먼저 표기하곤 하는데 이 두 개념이 믹스되면서 혼란을 겪은 것 같다.

나. 문제를 잘못 이해하면 문제를 어렵게 바라본다

위에서 기록했지만 문제와 여러 제약사항을 잘못 이해함으로 매우 쉬운 문제를 매우 어렵게 바라보게 되었다. 문제를 해결하는 기술적인 칼날이 예민하고 기술적인 자유도가 높은 것도 중요하지만 문제 자체를 제대로 이해하는 능력이 먼저 중요함을 다시 한 번 느낀다.

다. 이런거 계속 해야 하나?

자꾸 이런 유형의 문제를 내가 왜 풀어야하는지 그만하고 싶은 생각이 들었다. 잘못된 유혹이다. 분명히 도메인의 문제와 제약사항 등을 바르게 이해하지 못하는 나의 약점을 드러내 주고 있고 글을 읽고 문제를 바르게 파악하는 연습이 되고 있다. 뿐만 아니다. Java 언어의 다양한 라이브러리를 자유롭게 활용하지 못하고 있는 약점도 있었는데 점점 문제를 해결하는 도구를 날카롭게하고 또한 기술적인 자유도도 훨씬 커져 가는 것을 느낀다. 꾸준히 지속하면 좋은 개발자가 되는데 도움이 된다고 생각한다.

라. ChatGPT의 도움

문제 푸는 것을 거의 포기할 뻔 했을 때 ChatGPT가 준 힌트 하나가 나를 다시 일어서게 했다. 문제를 완전히 잘못 이해하고 있었다. 이후에도 여러 문제들을 해결할 Java API(String::lastIndexOf, Stream::Iterate 등)를 찾는데 ChatGPT가 큰 도움이 되었다.

잘한 점

  • 포기하지 않고 ChatGPT에게 질문을 던지고 힌트를 얻어 다시 스스로 문제를 풀기 시작한 점을 칭찬하고 싶다.
  • 문제를 바르게 이해한 뒤에 어떻게 문제를 해결할지 방법을 하나씩 찾으며 차분히 풀어나간 점 칭찬하고 싶다.
  • 대부분의 사람들이 푼 코드를 보면 한 번 이중 루프를 돌면서 파일이 존재하는 위치를 찾으면 top, left, bottom, right 값을 갱신해 나가는 방식을 사용하고 있다. 효율적이긴 하지만 한 번에 4개의 개념을 함께 생각해서 코드를 이해하기가 어렵다는 느낌을 받는다. 개인적으로 top, left, bottom, right 각각에 집중해서 찾는 코드가 서로 직교적이고 단순한 코드를 만든다는 느낌을 받는다. 다만 성능 이슈가 생긴다면 좀 더 효율적인 다른 접근을 사용해야 할 것이다.
  • Stream API 활용이 점점 능숙해 지는 것 같다.

학습한 것

  • String::lastIndexOf 메서드 사용해서 문자열 뒤에서 부터 특정 문자 찾기
  • Stream::iterate 메서드 사용해서 배열을 뒤에서 부터 이터레이션하기
  • Optional::orElse 메서드 사용해서 값이 빈 경우 반환할 값 지정하기
  • IntStream을 활용해 객체타입의 List에서 특정 조건을 만족하는 인덱스를 추출하는 방법
profile
소프트웨어 엔지니어, 일상

0개의 댓글