(프로그래머스) 삼각 달팽이

大 炫 ·2021년 4월 9일
0

프로그래머스

목록 보기
7/7

끙끙 머리를 싸매며 설계대로 코딩을 하고 다른사람들의 풀이를 보니
2차원배열로 많이 풀었더라.. 2차원배열로 풀생각은 전혀 안나던데...
제출 후 성능도 마음에 안들어 여기저기 최적화시키며 보기좋게 만든 코드를 공유하고자한다.

설계

간단하게 위의 이미지로 진행되는 방향에서 각각의 모서리마다 중단점으로 조건문을 걸어주어 방향을 전환시키며 배열을 채운다.

(대충 중단점을 표시해준 모습)
"내려가기", "옆으로가기", "올라가기" 를 반복

보완 전 코드

function solution(n) {
    let N = n;
    N % 2 === 0 ? N = (N+1)*(N/2) : N = (N+1) * (Math.floor(N/2)) + Math.ceil(N/2);
    const answer = Array(N).fill(0);

    let dir = "내려가기";
    let location = 0;
    let num = 1;
    let cnt = 0;
    while(answer.indexOf(0) !== -1){
        if(dir === "내려가기") {
            if (++cnt !== 1) location += cnt++;
            let downStandard = cnt;
            while(location < answer.length){
                if (answer[location] === 0) {
                    answer[location] = num++;
                    location += downStandard++;
                }
                else break;
            }
            dir = "옆으로가기";
            location -= --downStandard
        }else if(dir === "옆으로가기"){
            location++;
            while(answer[location] === 0){
                answer[location++] = num++;
            }
            dir = "올라가기";
            location--;
        }else if (dir === "올라가기"){
            location -= n--;
            let upStandard = n;
            while(answer[location] === 0){
                answer[location] = num++;
                location -= upStandard--;
            }
            dir = "내려가기";
            location += ++upStandard;
        }
    }
    return answer;
}

보완 후 코드

function solution(n) {
    let N = n;
    N % 2 === 0 ? N = (N+1)*(N/2) : N = (N+1) * (Math.floor(N/2)) + Math.ceil(N/2);
    const answer = Array(N).fill(0);

    let dir = "내려가기";
    let location = 0, cnt = 0, num = 1;
    while(num <= answer.length){
        switch (dir){
            case "내려가기":
                if (++cnt !== 1) location += cnt++;
                let downStandard = cnt;
                while(answer[location] === 0){
                        answer[location] = num++;
                        location += downStandard++;
                }
                dir = "옆으로가기";
                location -= --downStandard;
            case "옆으로가기":
                location++;
                while(answer[location] === 0){
                    answer[location++] = num++;
                }
                dir = "올라가기";
                location--;
            case "올라가기":
                location -= n--;
                let upStandard = n;
                while(answer[location] === 0){
                    answer[location] = num++;
                    location -= upStandard--;
                }
                dir = "내려가기";
                location += ++upStandard;
        }
    }
    return answer;
}

보완된 점

달라진점은 크게 두가지인데
첫번째로 가독성을 위해 switch, case문으로 보기좋게 바꿔준점
두번째는 중첩while문에서 바깥에 해당하는 while문의 조건절을

while(answer.indexOf(0) !== -1)

에서

while(num <= answer.length)

로 바꾸어주었는데 n이 커질수록 배열의 크기또한 가파르게 커지는데
때문에 보다 엄청난 차이의 성능이 나타나게되는 것이다.
였던 성능이

해설

각각 변수는 location은 answer의 인덱스, 즉 채워질 배열의 위치를
num은 1~n까지 차례대로 채워질 숫자를
cnt는 1순환과 2순환부터 달라지는 "내려가기"의 규칙때문에 순환의 횟수를
downStandard와 upStandard는 각각 location은 알맞은 규칙에따라 증가되는 기준을 나타낸것이다.
"옆으로가기"는 location이 1씩 증가하기때문에 선언해주지 않은것

필요에따라 선위증가와 후위증가를 알맞게 쓴 모습
while문이 4개가 존재하는데 각각의 while문에 break point를 주고 디버깅모드를 진행해본다면 수월하게 코드의 흐름을 파악 가능할것이다.

배운점

습관적 console.log의 디버깅의 한계점을 명확히 느낀 예제이다.
때문에 break point를 충분히 활용하며,
break point의 전능함에 전율했다..

늘 부딪혀보고 배우는것 또한 지양해야겠지만
필요에의한 학습과, 그렇지 않은 학습은
늘 엄청난 차이를 주곤한다.

profile
대현

0개의 댓글