20240204_마법의 엘리베이터(프로그래머스)

2024. 2. 5. 08:58IT/TIL

오늘의 TIL은 프로그래머스의 문제인 마법의 엘리베이터에 관한 내용이다.

 

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/148653

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

문제에 대해서 설명하면

 

한 번 누르면 10의 n제곱(n은 0 이상인 정수)만큼 위 아래로 움직이는 엘리베이터 버튼이 있을 때,

 

현재 층수에서 0층(현재 층수에서 더해서 0이 되는 값)으고 가려고 하는데

 

가장 적게 버튼을 눌러서 가는 방법을 찾는 함수를 만드는 것이 문제이다.

 

 

우선 통과한 답은 아래와 같다.

 

더보기

 

using System;
using System.Linq;
using System.Collections.Generic;

public class Solution {
    public int solution(int storey) {
        int answer = 0;
        List<int> intList = storey.ToString()
                                .Select(i => int.Parse(i.ToString()))
                                .ToList();

        intList.Reverse();

        for (int i = 0; i < intList.Count; i++)
        {
            if (intList[i] >= 1 && intList[i] <= 4)
            {
                answer += intList[i];
            }
            else if (intList[i] >= 6)
            {
                answer += (10 - intList[i]);

                if (i + 1 < intList.Count)
                {
                    intList[i + 1]++;
                }
                else
                {
                    answer++;
                }
            }
            else if (intList[i] == 5)
            {
                answer += intList[i];

                if (i + 1 < intList.Count && intList[i + 1] >= 5)
                {
                    intList[i + 1]++;
                }
            }
        }
        
        return answer;
    }
}

 

 

이 문제를 풀면서 내가 생각한 방법은 주어진 storey(층수) 값을 각각의 하나의 숫자로 나누고(리스트로)

 

이 배열을 reverse한다.

 

List<int> intList = storey.ToString()
                        .Select(i => int.Parse(i.ToString()))
                        .ToList();

intList.Reverse();

 

 

이후에 이 리스트의 원소들을 앞부터(실제로는 맨 뒤부터) 끝까지 순회하면서 조건에 맞게 버튼을 누르게 만들었다.

 

조건 1번 - 해당 층수의 값이 1 에서 4 사이인 경우,

 

가장 최적의 값은 이를 빼주는 것이므로 해당 값을 빼준다.

for(int i = 0; i < intList.Count; i++)
{
    if (intList[i] >= 1 && intList[i] <= 4)
    {
        answer += intList[i];
    }

 

 

조건 2번 - 해당 층수의 값이 6 이상인 경우,

 

6 이상인 경우에는 10이 되기에 모자란 만큼 더한 후에 1번 더 움직이는 것이 이상적인데

 

예를 들어 7인 경우에 3을 더해서 10을 만들고 1번 눌러서 4번으로 0을 만들 수 있다.

 

하지만 이 경우에 다음 값이 존재함에 따라서 경우의 수가 달라지는데,

 

다음의 수가 없다면 1번 눌러서 0으로 만들 수 있지만,

 

다음의 수가 있다면 이 수에서도 수에 따른 조건을 적용해야 되므로, 해당 값에 1을 추가한다.

 

else if (intList[i] >= 6)
{
    answer += (10 - intList[i]);

    if (i + 1 < intList.Count)
    {
        intList[i + 1]++;
    }
    else
    {
        answer++;
    }
}

 

 

조건 3번 - 해당 층수의 값이 5인 경우,

 

해당 층수가 5인 경우에도 다음 층수의 값에 영향을 받는다.

 

우선 값이 5이므로 더해주거나 빼주거나 같은 횟수가 필요하다.

 

하지만, 다음 층수의 값에 따라서 전략이 달라지는데,

 

만약 다음 층수가 있고, 층수의 값이 5 이상이라면 이를 더해주고 다음 층수에서 값을 조정하는 것이 효율적이다.

 

반면 다음 층수가 없다면 빼주는 것이 효율적이고,

 

층수가 있더라도 다음 층수의 값이 4이하라면 빼주는 것이 효율적이다.

 

(더해준다면 오히려 횟수가 늘어나기 때문에)

else if (intList[i] == 5)
{
    answer += intList[i];

    if (i + 1 < intList.Count && intList[i + 1] >= 5)
    {
        intList[i + 1]++;
    }
}

 

 

추가로 개선했던 부분

 

초기에 리스트를 만드는 과정이

 

숫자 값을 string으로 변환하고, 이를 정렬하고, 다시 리스트로 만든 후에, 역으로 정렬하는데,

 

이 과정이 시간을 많이 소모되는 부분이였는데,

 

이를 아래처럼 수정하니 훨씬 빨라진 것을 알 수 있었다.

List<int> llist = new List<int>();

while (storey != 0)
{
    llist.Add(storey % 10);
    storey /= 10;
}

 

왼쪽이 기존의 방법, 오른쪽이 위의 방법

 

 

이렇게 해결한 문제도 좀 더 고민하여 보다 빠르게 작동하도록 개선하는 과정을 거쳤는데

 

답을 풀었다고 바로 넘어가는 것이 아니라

 

코드를 보면서 어느 부분을 개선할 수 있을지 고민하는 과정을 거친 것이

 

이번 문제를 풀면서 얻을 수 있는 경험이었다고 할 수 있다.

'IT > TIL' 카테고리의 다른 글

20240206_멀쩡한 사각형(프로그래머스)  (0) 2024.02.06
20240205_SOLID원칙  (0) 2024.02.05
20240203_최종프로젝트 트러블슈팅  (2) 2024.02.03
20240202_객체지향의 특징  (0) 2024.02.03
20240201_클래스와 객체  (0) 2024.02.01