[Algorithm] 프로그래머스 레벨1 풀이 모음 - (Javascript)

권준혁·2020년 11월 1일
0

Algorithm

목록 보기
1/1
post-thumbnail
  • 우측의 네비게이터 메뉴 또는 Ctrl+F 를 이용해 찾아주세요

  • 제목을 클릭하면 문제로 이동합니다. (새창열기 Ctrl+Click)

다트게임 2018 KAKAO (새창열기 Ctrl+Click)

function solution(dartResult) {
    let origin = [...dartResult].reduce((arr,v,i)=>{
        if (v==='0' && arr[i-1]==='1') return [...arr,'10'];
        if (v==='1' && arr[i+1]==='0') return [...arr];
        return [...arr,v];
    },[]);
    let scores = [];
    origin.forEach((v,i)=>{
        const len = scores.length;
        if (v==='S') scores.push(origin[i-1]/1);
        if (v==='D') scores.push(Math.pow(origin[i-1]/1 , 2));
        if (v==='T') scores.push(Math.pow(origin[i-1]/1 , 3));
        if (v==='*') {
            const hasBefore = len >= 2;
            if(hasBefore) scores[len-2] = scores[len-2]*2;
            scores[len-1] = scores[len-1]*2;
        }
        if (v==='#') scores[len-1] = scores[len-1] - 2*scores[len-1];
    })
    return scores.reduce((accum,v)=>accum+v,0);
}
  • 매개변수 dartResult에서 넘어오는 문자열에서 10점을 분리하는 과정(1-9는 한 자리, 10은 두 자리)을 거치지 않아 수정이 필요했었다.
  • 처음 만들었을 때 세 개의 배열 SDT, options, scores로 각각 분리한 뒤 처리하는 로직으로 만들었는데 비효율적인 것 같아 최대한 배열생성을 자제하며 수정했다.

■ [비밀지도 2018 KAKAO] (https://programmers.co.kr/learn/courses/30/lessons/17681)

function solution(n, arr1, arr2) {
    const toBinary = (arr) => arr.map(item=>item.toString(2))
                                 .map(str=> '0'.repeat(n - str.length)+str)
                                 .map(binary => Array.from(binary).map(digit => digit/1));
    const binaryMap1 = toBinary(arr1);
    const binaryMap2 = toBinary(arr2);
    const resultMap = binaryMap1.map((line,index) => line.map((d,i)=> binaryMap2[index][i] + d >= 1? 1: 0 ));
    return resultMap.reduce((arr,line)=> [...arr, line.map(digit=> digit? '#':' ').join('')],[]);
}
  • toBinary는 10진수인 배열요소를 2진수로 만든 뒤, 부족한 만큼 앞자리에 0을 넣어 숫자의 길이를 맞춰준다.

  • 그런 뒤, Array.from() 메서드로 문자열을 배열로 만들고, 각 요소를 정수로 변경한다.

  • resultMap 은 이런 형태가 된다.

    [ [ 1, 1, 1, 1, 1 ],
    [ 1, 0, 1, 0, 1 ],
    [ 1, 1, 1, 0, 1 ],
    [ 1, 0, 0, 1, 1 ],
    [ 1, 1, 1, 1, 1 ] ]
  • reduce() 메서드를 이용해 문제의 결과에 맞게 형태를 변경해준다.


실패율 2019 KAKAO

function solution(N, stages) {
    let divisors = Array(N+1).fill(0);
    stages.forEach((stage)=>{
        for (let i = 0; i < stage; i++) {divisors[i] += 1}
    })

    const Rate = divisors.reduce((arr,divisor,index)=>{
        return [...arr, divisor === 0? 0 :stages.filter(stage => stage===index+1).length/divisor]
    },[]);

    const result = Rate.reduce((arr,rate,index)=>[...arr ,[index+1 , rate]],[]);
    result.pop();
    result.sort((a,b)=> {
        if(a[1]===b[1]) return a[0]-b[0];
        return b[1]-a[1];
    })
    return result.map(v => v[0]);
}
  • 먼저 실패율의 분모가 될 divisors 배열을 생성한다.
  • divisors는 stages배열을 stage별로 통과한사람 + 도전중인사람 이다
  • Rate는 도전중인사람 / divisors 배열 각 요소
  • result는 Rate를 entry로 나타낸다.
  • result를 정렬하고 정렬된 result의 각 요소의 첫 번째 원소인 stage들의 배열을 반환한다.

예산 2018 summer/winter coding

function solution(d, budget) {
    let supports = 0;
    d.sort((a,b)=>a-b).reduce((accum,v) => {
        if (accum+v <= budget) supports++;
        return accum+v;
    },0);
    return supports;
}
  • 매개변수 d는 부서별 신청한 금액이다.
  • d를 오름차순으로 정렬한 뒤 reduce를 이용해 누산된 금액이 총 예산 budget이하라면 supports를 증가시킨다.

x만큼 간격이 있는 n개의 숫자

function solution(x, n) {
    const array = Array(n).fill(x);
    return array.reduce((arr,v,i)=>{
        const num = arr[i-1] ? arr[i-1] + x : x; 
        return [...arr,num];
    },[]);
}
  • 매개변수 n만큼 길이를 가지는 array, 각 요소를 x로 초기화 했습니다.
  • array[i-1]? 로 시작하는 삼항식은 인덱스가 -1인 경우에 대한 판별식입니다.
  • 바로 앞 요소보다 x씩 증가합니다.

행렬의 덧셈

function solution(arr1, arr2) {
    return arr1.map((arr,index)=>arr.map((v,i)=>v+arr2[index][i]));
}
  • 2차원 배열끼리 각 요소를 더하는 것이므로 그 것에 대응하는 arr2[index][i]와 v를 더해 리턴합니다.

핸드폰 번호 가리기

function solution(phone_number) {
    return [...phone_number].map((v,i)=> i<=[...phone_number].length-5? '*':v).join('');
}

하샤드 수

function solution(x) {
    return x % Array.from(x+'').map(i => i/1).reduce((acc,i)=> acc+i,0) ? false : true;
}

콜라츠 추측

function solution(num) {
    let step = 0;
    let n = num;
    while (n > 1) {
        let isOdd = n % 2 === 0? false : true;
        n = isOdd?  n * 3 + 1 : n / 2;
        step++;
        if(step==500) {
            step = -1;
            break;
        };
    }
    return step;
}

최대공약수와 최소공배수

function solution(n, m) {
    const gcd = (a,b) =>  b? gcd(b, a%b) : a;
    return [gcd(n,m) , n*m /gcd(n,m)];
}
  • a%b가 0일때 까지 반복되는 재귀함수입니다.
  • 최공배수는 두 수의 곱을 최대공약수로 나눈 값입니다.

제일 작은 수 제거하기

function solution(arr) {
    arr.splice(arr.findIndex(v=> v===Math.min(...arr)),1)
    return arr.length <=1? [-1] : arr;
}

정수 제곱근 판별

function solution(n) {
    const sqrt = Math.sqrt(n) + 1;
    return Number.isInteger(sqrt)? Math.pow(sqrt,2) : -1;
}
  • Number.isInteger() 라는 함수를 사용해봤다.

이상한 문자 만들기

function solution (s) {
    const result = s.toUpperCase().split(' ').map(item => {
        return Array.from(item).map((a,i)=> i%2===1? a.toLowerCase() : a);
    })
    return [...result].join(' ').split(',').join('');
}

약수의 합

function solution(n) {
    let result = 0
    for (let i = 1; i <= n; i++) {
        if (n % i == 0) result = result + i;
    }
    return result;
}

시저 암호

function solution(s, n) {
    const lower = [];
    for(let i = 97; i<= 122; i++) {lower.push(i);};
    const upper = lower.map(item=> item-32);

    const findIndex = (alpha, n) => {
        const ascii = alpha.charCodeAt(0);
        const a = lower.find(i => i===ascii);
        const A = upper.find(i => i===ascii);

        let encoded;
        if(!a && !A) return ' ';
        if(a) encoded = a+n>122? a-26+n : a+n;
        if(A) encoded = A+n>90? A-26+n : A+n;

        return String.fromCharCode(encoded);
    }

    const result = Array.from(s).map(alpha => {
        let encoded = findIndex(alpha,n);
        return encoded;
    })
    return result.join('');
}
  • lower와 upper은 소문자와 대문자 아스키 값을 갖고있는 배열이다.
  • findIndex함수는 알파벳 alpha, 밀어낼 수 n을 매개변수로 갖는다.

수박수박수박수박수박수?

function solution(n) {
    return Array(n).fill('').map((item,index)=> index % 2 === 0? '수':'박').join('');
}

소수찾기

function solution(n) {
    const sqrt = Math.sqrt(n);
    let primes = Array(n).fill(1);
    let count = 2;
    while(count <= sqrt){
        for(let a=count+count; a<=n; a+=count) {
            primes[a-1] = 0;
        }
        count++;
    }
    primes[0] = 0;
    return primes.filter(v=>v>=1).length;
}

문자열 내 p와 y의 개수

function solution(s){
    const result = Array.from(s).map(item=>{
        if(item === 'p' || item ==='P') return -1;
        if(item === 'y' || item ==='Y') return 1;
        return 0;
    }).reduce((ac,cr)=>ac+cr,0);
    return result===0
}

다른사람의 풀이

function solution(s) {
  return s.match(/p/ig).length == s.match(/y/ig).length;
}
  • 정규식을 이용해 더 간단하게 작성할 수 있다.

문자열 내 마음대로 정렬하기

function solution(strings, n) {
    strings.sort((a,b) => {
        if(a[n] > b[n]) return 1;
        if(a[n] < b[n]) return -1;
        if(a[n] === b[n]) return a.localeCompare(b);
    })
    return strings;
}

두 정수 사이의 합

function solution(a, b) {
    return (a + b) * (Math.abs(a-b)+1)/2;
}

나누어 떨어지는 숫자 배열

function solution(arr, divisor) {
    const divided = arr.map(item=>{
        return item % divisor === 0 ? item : undefined;
    }).filter(i => i).sort((a,b)=>a-b);
    return divided.length===0? [-1] : divided;
}

같은 숫자는 싫어

function solution(arr){
    return arr.map((item,index)=>item===arr[index+1]? undefined : item).filter(i=> i>=0);
}
  • filter() 함수의 조건을 i=>i 로 했을 때 0이 제외되기 때문에, i=> i>=0 으로 작성해야하는 것에 주의

2016년

function solution(a, b) {
    const date = new Date(2016,a-1,b);
    const days = ['SUN','MON','TUE','WED','THU','FRI','SAT'];
    return days[date.getDay()];
}

K번째 수

function solution(array, commands) {
    return commands.map(command => {
        let i = command[0]-1;
        let j = command[1];
        let k = command[2]-1;
        return [...array].slice(i,j).sort((a,b)=>a-b)[k];
    });
}

체육복

function solution(n, lost, reserve) {
    let students = Array(n).fill(1);
    reserve.forEach(a => students[a-1]=2);
    lost.forEach(a=> students[a-1]-- );
    students.forEach((item,i)=>{
        if(item>=2 && students[i-1]===0){
            students[i-1] = 1;
            students[i] = 1;
        }
    })
    students.forEach((item,i)=>{
        if(item>=2 && students[i+1]===0 ){
            students[i+1] = 1;
            students[i] = 1;
        }
    })
    return students.filter(i=> i>0).length
}
  • 최초 students배열은 모두 1개씩 체육복을 가지고 있다고 가정
  • reserve배열에 해당하는 학생들은 2개씩 체육복을 가지고있도록 수정
  • lost에 해당하는 학생들은 각각 체육복 -1 (여벌을 가져온 학생도 체육복을 도난 맞을 수 있음, 이런 경우 -1개)
  • forEach문은 각각 앞 번호에게 빌려주는 경우, 뒷 번호에게 빌려주는 경우

모의고사

function solution(answers) {
    const length = answers.length;
    const patternA = [1,2,3,4,5].join('').toString().repeat(Math.ceil(length/5)).split('').map(i=>i/1);
    const patternB = [2,1,2,3,2,4,2,5].join('').toString().repeat(Math.ceil(length/8)).split('').map(i=>i/1);
    const patternC = [3,3,1,1,2,2,4,4,5,5].join('').toString().repeat(Math.ceil(length/10)).split('').map(i=>i/1);
    const score = [[1,0],[2,0],[3,0]];
    answers.forEach((item,index)=>{
        if(patternA[index]===item) score[0][1]++;
        if(patternB[index]===item) score[1][1]++;
        if(patternC[index]===item) score[2][1]++;
    })
    return score.filter(item=>item[1]=== Math.max(...score.map(item=>item[1])))
                 .map(item=>item[0]).sort();
}
  • 먼저 각 패턴들을 답안의 길이에 맞게 반복해 늘려준다.
  • answer에 forEach() 함수로 채점한다.

완주하지 못한 선수

function solution(participant, completion) {
    participant.sort();
    completion.sort();
    let result;
    participant.some((element,index)=>{
        if(element !== completion[index]) {
            result = element
            return true
        }
    })
    return result;
}
  • some으로 반복했기 때문에 중간에 탈출할 수 있다.

크레인 인형뽑기 게임

function solution (board, moves) {
    const basket = [];
    let result = 0;
    moves.forEach((move,i)=>{
        const foundLine = board.find(line=> line[move-1] > 0);
        if (foundLine)  {
            basket.push(foundLine[move-1]);
            foundLine[move-1] = 0;
        }
        const index = basket.findIndex((v,i)=> v=== basket[i+1]);
        if (index > -1) {
            basket.splice(index,1);
            basket.splice(index,1);
            result++;
        }
    })
    return result*2;
}
  • 크레인의 움직임을 담은 배열 매개변수 moves를 forEach로 순회하면서, 해당하는 인형을 찾아 basket에 push()로 담는다.
  • 매 반복시마다 같은인형이 있는지 찾아 index에 결과를 담는다.
  • index가 -1보다 크다면 터져야 하는 인형이 있으므로 result를 증가시키고 splice로 요소를 제거한다.

몇몇 문제는 제외했습니다.
읽어주셔서 감사합니다.

profile
웹 프론트엔드, RN앱 개발자입니다.

0개의 댓글