[고찰] 권토중래(捲土重來)

스스로의 못남이 웃겨서 적는다.

그리고 앞으로는 조금 더 발전된 사고를 하기 위해 적는다.

 

프로그래머스 알고리즘 문제 중에, 

 

<연속된 수의 합>
연속된 세 개의 정수를 더해 12가 되는 경우는 3, 4, 5입니다. 두 정수 num과 total이 주어집니다. 연속된 수 num개를 더한 값이 total이 될 때, 정수 배열을 오름차순으로 담아 return하도록 solution함수를 완성해보세요.

 

라는 문제가 있었다. 아래 예시처럼 결과가 나오면 된다.

 

num  total result
3 12 [3, 4, 5]
5 15 [1, 2, 3, 4, 5]
4 14 [2, 3, 4, 5]
5 5 [-1, 0, 1, 2, 3]

 

이것은 내가 처음에 푼 방식이다.

 

function solution(num, total) {
    //-1000부터 1000까지 배열 만들어서
    //for문을 돌면서 i부터 i+num-1까지 잘라
    //더했을 때 값이 total과 같은지 확인 후 리턴
    //아니면 i++해서 다시 실행
    
    var answer = [];
    let arr = [];
    for(let i = -1000; i <= -1; i++){
        arr.push(i);
    }
    arr.push(...Array(1000).fill().map((x,i)=>{return i})); 
    
    let n = 0;
    for(let i=0; i<arr.length; i++){
        answer = arr.slice(i, i+num);
        if(answer.reduce((acc, cur)=>{return acc+cur},0) === total){
            return answer;
        } 
    }  
}

 

무려 -1000부터 1000까지의 엄청난 배열을 만들어놓고(ㅋㅋ) num의 갯수만큼 잘라 더해보고 total과 비교해서 값이 다르면 i를 하나 올려서 다시 잘라 더해보고 true가 나올때까지 반복하는 형식이다.

스스로 풀면서도 이게 맞나 싶었다. 범위를 엄청나게 넓게 잡아놓아서 테스트는 통과했지만 해당 범위를 넘어가는 수 또한 분명 나올 수 있기 때문이다. 

 

테스트를 통과하고 도대체 다른 분들은 어떻게 풀었나 싶어 찾아봤는데 짧은 분은 2줄 정도의 코드만으로 문제를 해결하신 것이었다!

이게 무슨 일인가 싶어 열심히 코드를 읽어봤더니 

 

const n = (2 * total / num + 1 - num) / 2

 

이런 식으로 하면 n이 result의 첫 번째 숫자가 된다. 

 

내가 멍청한걸까 다른 사람들이 너무 똑똑한걸까? 도대체 저렇게 계산할 생각을 어떻게 한걸까.

저런 계산식을 생각해내진 못해도 조금 뜯어보니 total을 num으로 나누면 result의 가운데 인덱스의 값이 나온다는걸 알았다. num이 홀수면 가운데 수가 나오고 짝수면 .5의 숫자가 나온다. 

 

num total result
3 12 [3, 4, 5]

일 때 12/3 은 4가 나오고

 

num total result
4 14 [2,3,4,5]

일 땐 3.5가 나온다는 말이다.

 

왜 이 정도도 생각을 못 했을까 조금 허무해졌다. 아마 문제의 "연속된 n 개의 정수를 더해" 부분에 꽂혀 연속된 수를 더해 비교한다는 것 이상의 생각을 하지 못한게 아닐까 싶다. 

 

이 정도만 알아도 내가 짠 코드보다 훨씬 효율적인 코드를 짤 수 있다. 당장 해보았다.

 

function solution(num, total) {
    //num이 짝수인지 홀수인지 구분해
    //홀수의 경우 total/num으로 result의 가운데 수 확인 후 
    //num/2의 내림만큼 빼 result 의 첫 수 확인 및 num만큼 1씩 더한 배열로 만들어 리턴
    //짝수의 경우 total/num의 올림으로 result의 절반+1인덱스의 수 확인 후
    //num/2를 빼 result의 첫 수 확인, num만큼 1씩 더한 배열로 리턴
    
    let a = 0;
    
    if(num%2 ===1){
        a = total/num - Math.floor(num/2);
    } else {
        a = Math.ceil(total/num) - num/2;
    }
    
    return Array(num).fill().map((x, i)=>{return i+a});
    
}

 

처음 만든 코드보다 훨씬 효율적이고 좋은 코드이다. 조금만 더 수학적인 사고를 했더라면 더 금방 잘 풀었을 것이다. 

내 엉망진창인 모습을 굳이 이렇게 적는 건 스스로 실패를 발판 삼아 더 잘 하기를 바란다는 의미이다.

그야말로 권토중래(捲土重來)를 기원하며.