ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스] 1106 오늘의 문제 풀이
    Algorithm 2020. 11. 6. 15:43
    반응형

    예전에 풀어봤던 문제들인데, 알고리즘 감을 되살리기 위해 다시 한 번 풀어보는 중.

    사실 예전에 풀어봤다는 게 별 의미가 없는 것 같다.

    너무 오래돼서, 내가 어떻게 풀었는지 기억이 하나도 안나기 때문에.

    1. 실패율

    function solution(N, stages) {
        let Nstages = new Array(N + 1).fill(0);
        const current = new Array(N + 1).fill(0);
        
        for(let i = 0; i < stages.length; i++) {
            for(let j = 0; j <= stages[i] - 1; j++) {
                Nstages[j]++;
                
                if(j === stages[i] - 1) current[j]++;
            }
        }
    
        Nstages = Nstages.slice(0, N);
        
        for(let i = 0; i < N; i++) {
            if(Nstages[i] === 0) {
                Nstages[i] = 0;
            } else {
                Nstages[i] = current[i] / Nstages[i];
            }
        }
        
        const result = new Array(N);
        for(let i = 0; i < result.length; i++) {
            result[i] = i + 1;
        }
        
        return result.sort((a, b) => {
            if(Nstages[a - 1] === Nstages[b - 1]) {
                return a - b;
            } else {
                if(Nstages[a - 1] > Nstages[b - 1]) {
                    return b - a;
                } else {
                    return a - b;
                }            
            }
        });
    }

    상당히 구구절절하지만 생각보다 속도가 빠르게 나와서 뿌듯.

     

    2. 비밀지도

    a. 혼자서 풀기

    function solution(n, arr1, arr2) {
        const arr1_after = arr1.map(num => {
            let q = num, r, result = '';
            while(q > 1) {
                r = q % 2;
                q = (q / 2) >> 0;
                result = r + result;
            }
            return (q + result).padStart(n, '0');
        });
        
        const arr2_after = arr2.map(num => {
            let q = num, r, result = '';
            while(q > 1) {
                r = q % 2;
                q = (q / 2) >> 0;
                result = r + result;
            }
            return (q + result).padStart(n, '0');
        });
            
        return arr1_after.map((binary, idx) => {
            let str = '';
            for(let i = 0; i < binary.length; i++) {
                if(binary[i] === '1' || arr2_after[idx][i] === '1') {
                    str += '#';
                } else {
                    str += ' ';
                }
            }
            return str;
        });
    }

     

    b. 다른 사람의 풀이

    function solution(n, arr1, arr2) {
        return arr1.map((bin, idx) => {
            return (bin | arr2[idx]).toString(2).padStart(n, '0').replace(/1|0/g, a => +a ? '#' : ' ');
        });
    }

    1. 십진수의 숫자를 논리연산 시키면 2진수로 변환해서 계산된다. 물론 결과는 십진수로 다시 변환되어 나온다.

     

    2. Number.toString(n)을 해주면, Number가 n진수 숫자 형태의 문자열로 변환된다.

     

    3. replace(/1|0/g, a =>+a ? '#' : ' ')

    만약 a가 '1'이라면 +a는 숫자 1이므로 조건문에 들어갔을 때 true를 return한다.

    반면, a가 '0'이라면 +a는 숫자 0이므로 조건문에 들어갔을 때 false를 return한다.

    당연히 알고 있는 내용이었지만, 이렇게 똑똑하게 사용될 줄은 몰랐다.

     

    3. 다트게임

    a. 혼자서 풀기

    function solution(dartResult) {
        let score = [];
        const strings = dartResult.match(/([0-9]{1,})([SDT])([*#]{0,1})/g);
    
        for(let i = 0; i < strings.length; i++) {
            let currentScore = 0;
            const digit = +strings[i].match(/[0-9]{1,}/g)[0];
            const bonus = strings[i].match(/[SDT]/g)[0];
            let option = strings[i].match(/[*#]/g);
            if(option) option = option[0];
            
            if(bonus === 'S') currentScore += digit;
            else if(bonus === 'D') currentScore += Math.pow(digit, 2);
            else if(bonus === 'T') currentScore += Math.pow(digit, 3);
            
            if(option) {
                if(option === '*') {
                    if(i - 1 >= 0) {
                        score[i - 1] = score[i - 1] * 2;
                    }
                    currentScore = currentScore * 2;
                } else if(option === '#') {
                    currentScore = currentScore * -1;
                }
            }
            score[i] = currentScore;
        }
        
        return score.reduce((prev, cur) => prev + cur, 0);
    }

    이 문제는 사실 이전에 정규표현식으로 풀었던 게 기억이 나서 풀 수 있었다.

     

    b. 다른 사람의 풀이

    function solution(dartResult) {
        let answer = 0;
        let numArr = [];
        for (let i = 0; i < dartResult.length; i = i + 2){
            let point;
            
            // 10인 경우와 아닌 경우로 분리
            if(i + 1 < dartResult.length && dartResult[i + 1] === '0'){
                point = 10;
                i++;
            } else {
                point = parseInt(dartResult[i]); 
            }
            
            const bonus = dartResult[i+1];
            
            // D면 제곱, T 면 세제곱
            if(bonus === 'D'){
                point *= point;   
            } else if(bonus === 'T'){
                point *= point * point;
            }
            
            // * 이면 현재 값과 이전값 2배, #이면 현재값 -1
            if(i + 2 < dartResult.length && dartResult[i + 2] === '*'){
                point *= 2;
                if(numArr.length !== 0){
                    numArr[numArr.length - 1] *= 2;
                }
                
                i++;
            } else if(i + 2 < dartResult.length && dartResult[i + 2] === '#'){
                point *= -1;   
                i++;
            }
            
            numArr.push(point);
        }
        
        for (let i = 0; i < numArr.length; i++){
            answer += numArr[i];
        }
        return answer;      
    }

    정규표현식을 사용하지 않은 풀이이다.

    10점인 경우는 어떻게 처리해야되나 고민이 많았는데, 그냥 i를 1 더해주면 되는 거였네.

    둘러봤던 코드들 중에 가장 보기가 편하고 이해가 잘되는 코드라서 가져와봤다.

    너무 어렵게 생각해서 오히려 꼬여버린 문제.

     

    출처

     

    [프로그래머스] [1차] 다트 게임 (JavaScript)

    문제 프로그래머스 2018 KAKAO BLIND RECRUITMENT [1차] 다트게임 https://programmers.co.kr/learn/courses/30/lessons/17682 코딩테스트 연습 - [1차] 다트 게임 programmers.co.kr 언어 자바스크립트(JavaScri..

    jongbeom-dev.tistory.com

     

    4. 예산

    function solution(d, budget) {
        let answer = 0;
        const department = d.slice();
        
        department.sort((a, b) => a - b).reduce((acc, cur, idx) => {
            if(acc + cur <= budget) {
                answer = idx + 1;
                return acc + cur;
            } else {
                return acc;
            }
        }, 0);
        
        return answer;
    }

     

    5. 키패드 누르기

    function solution(numbers, hand) {
        let answer = '';
        let leftThumb = 10, rightThumb = 12;
        
        for(let i = 0; i < numbers.length; i++) {
            let curNum = numbers[i];
            
            if(curNum === 1 || curNum === 4 || curNum === 7) {
                /* 왼쪽인 경우 */
                answer += 'L';
                leftThumb = curNum;
            } else if(curNum === 3 || curNum === 6 || curNum === 9) {
                /* 오른쪽인 경우 */
                answer += 'R';
                rightThumb = curNum;
            } else {
                /* 중간인 경우 */
                if(curNum === 0) curNum = 11;
    
                let leftDistance = 100, rightDistance = 100;
    
                leftDistance = Math.abs(leftThumb - curNum);
                rightDistance = Math.abs(rightThumb - curNum);
    
                leftDistance = (leftDistance % 3) + Math.floor(leftDistance / 3);
                rightDistance = (rightDistance % 3) + Math.floor(rightDistance / 3);
    
                if(leftDistance === rightDistance) {
                    if(hand === 'right') {
                        answer += 'R';
                        rightThumb = curNum;
                    } else {
                        answer += 'L';
                        leftThumb = curNum;
                    }
                } else if(leftDistance > rightDistance) {
                    answer += 'R';
                    rightThumb = curNum;
                } else {
                    answer += 'L';
                    leftThumb = curNum;
                }
            }
        }
        
        return answer;
    }

    요거는 내가 카카오 인턴십 지원했을 때 직접 풀었던 문제다.

    그때는 너무 긴장을 해서, 아무것도 생각이 안났는데

    시간이 지나고 오늘 다시 풀어보기 규칙이 눈에 보였다.

    항상 문제에서 규칙을 발견하는 게 제일 중요한듯.

     

    한 줄에 3개씩 놓여 있으니까, 키패드 사이의 거리(절대값)를 3으로 나눴을 때세로로 움직이는 양이고, 나머지가로로 움직이는 양이었다.이렇게 간단한 규칙을 단순히 긴장때문에 못 찾았다니.

     

    일단, 모든 알고리즘 문제들이

    문제를 내기 위해 만들어진 문제이니만큼

    틀림없이 규칙을 가지고 있다는 마인드로,

    눈에 불을 밝히고 규칙을 찾을 수 있도록 해야겠다.

     

     

    6. 두 개 뽑아서 더하기

    a. 혼자서 풀기

    function solution(numbers) {
        var answer = [];
        
        for(let i = 0; i < numbers.length - 1; i++) {
            for(let j = i + 1; j < numbers.length; j++) {
                const cur = numbers[i] + numbers[j];
                if(answer.indexOf(cur) === -1) {
                    answer.push(cur);
                }
            }
        }
        
        return answer.sort((a, b) => a - b);
    }

    b. 다른 사람의 풀이

    function solution(numbers) {
        const temp = [];
    
        for (let i = 0; i < numbers.length; i++) {
            for (let j = i + 1; j < numbers.length; j++) {
                temp.push(numbers[i] + numbers[j]);
            }
        }
    
        const answer = [...new Set(temp)];
    
        return answer.sort((a, b) => a - b);
    }

    사실, indexOf도 반복문이기 때문에 내 풀이는 3중 반복문이나 마찬가지이다.

    이 사람은 반복문과 조건문을 사용하지 않고, set을 이용하여 현명하게 중복을 없앴다.

    spread operator는 덤으로.

     

     

    반응형

    댓글

Designed by Tistory.