ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코딩테스트] 프로그래머스 javascript 1단계 - 실패율, 명예의 전당(1), 다트게임, 숫자 짝꿍
    알고리즘/코딩 테스트 2023. 2. 1. 16:36

    실패율

     

     

    프로그래머스

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

    programmers.co.kr

    문제 설명

    슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.

    이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.

    • 실패율은 다음과 같이 정의한다.
      • 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수

    전체 스테이지의 개수 N, 게임을 이용하는 사용자가 현재 멈춰있는 스테이지의 번호가 담긴 배열 stages가 매개변수로 주어질 때, 실패율이 높은 스테이지부터 내림차순으로 스테이지의 번호가 담겨있는 배열을 return 하도록 solution 함수를 완성하라.

     

    문제풀이

    - stages의 원소의 수가 N(스테이지) 보다 작거나 같은 수를 failCount에 저장한다.

    - stages에 도전하는 원소만을 stagearr에 저장한다.

     

    function solution(N, stages) {
        let failRatio = new Map()
        let stagearr = stages.slice(0)
        for (let i = 1;i<=N;i++) {
            stagearr = stagearr.filter(v=>v>=i)
            const failCount = stagearr.filter(v=>v<=i).length
            failRatio.set(i,failCount/stagearr.length)
            // console.log(failRatio)
        }
        
        return [...failRatio].sort((a,b)=>b[1]-a[1]).map(v=>v[0])
    }

     

     

    명예의 전당(1)

     

    문제 설명

    "명예의 전당"이라는 TV 프로그램에서는 매일 1명의 가수가 노래를 부르고, 시청자들의 문자 투표수로 가수에게 점수를 부여합니다. 매일 출연한 가수의 점수가 지금까지 출연 가수들의 점수 중 상위 k번째 이내이면 해당 가수의 점수를 명예의 전당이라는 목록에 올려 기념합니다. 즉 프로그램 시작 이후 초기에 k일까지는 모든 출연 가수의 점수가 명예의 전당에 오르게 됩니다. k일 다음부터는 출연 가수의 점수가 기존의 명예의 전당 목록의 k번째 순위의 가수 점수보다 더 높으면, 출연 가수의 점수가 명예의 전당에 오르게 되고 기존의 k번째 순위의 점수는 명예의 전당에서 내려오게 됩니다.

    이 프로그램에서는 매일 "명예의 전당"의 최하위 점수를 발표합니다. 예를 들어, k = 3이고, 7일 동안 진행된 가수의 점수가 [10, 100, 20, 150, 1, 100, 200]이라면, 명예의 전당에서 발표된 점수는 아래의 그림과 같이 [10, 10, 10, 20, 20, 100, 100]입니다.

    명예의 전당 목록의 점수의 개수 k, 1일부터 마지막 날까지 출연한 가수들의 점수인 score가 주어졌을 때, 매일 발표된 명예의 전당의 최하위 점수를 return하는 solution 함수를 완성해주세요.

     

     

     

    문제풀이

    - stack을 이용해서 정렬 후 shift 하면 된다.

    - 단, index가 k보다 작을때는 push를 해야한다.

     

    function solution(k, score) {
        let stack = [];
        let answer = [];
        for (let i =0;i<score.length;i++) {
            if(i<k) {
                stack.push(score[i]);
                stack.sort((a,b)=>a-b);
            }
            if(i>=k && stack[0] <= score[i]) {
                stack.shift()
                stack.push(score[i])
                stack.sort((a,b)=>a-b)
            }
            answer.push(stack[0])
        }
        return answer
    }

     

     비교적 간단하게 풀 수 있지만 구조를 생각하지 않아 생각보다 시간이 걸렸다.

    즉, 처음 구조를 잘 짜야 한다.

     

    숫자짝꿍

     

    문제 설명

    두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다.

    예를 들어, X = 3403이고 Y = 13203이라면, X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개, Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.)
    두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요.

     

     

    1. 첫번째 시도

    - Xarr와 Yarr의 각각 문자열 개수를 세서 Map에 넣기.

    - Map을 arr로 만든 후 for문 돌려 문자열에 합치기

     

     

    채점 결과 시간초과로 5문제를 틀렸다.
    정확성: 73.7
    합계: 73.7 / 100.0
    테스트 11  실패 (시간 초과)
    테스트 12  실패 (시간 초과)
    테스트 13  실패 (시간 초과)
    테스트 14  실패 (시간 초과)
    테스트 15  실패 (시간 초과)
    function solution(X, Y) {
        // Map을 이용해서 X와 Y의 공통 숫자와 개수 찾기
        const Xarr = Array.from(X).sort((a,b)=>b-a);
        const Yarr = Array.from(Y).sort((a,b)=>b-a);
        let count = new Map();
        Xarr.forEach((v,i)=>{
            if (Yarr.includes(v)) {
                count.set(v,Xarr.lastIndexOf(v)-Xarr.indexOf(v)+1)
            }
        })
        Yarr.forEach((v,i)=>{
            if (count.has(v)) {
                const cur = Yarr.lastIndexOf(v)-Yarr.indexOf(v)+1
                 count.set(v,Math.min(cur,count.get(v)))
            }
           
        })
        console.log(count)
        // 짝꿍의 가장 큰 수 구하기
        if(count.size===0) return "-1"
        let c = [...count].sort((a,b)=>b[0]-a[0])
        let answer = ''
        c.forEach((v,i)=>{
            answer += v[0].repeat(v[1])+''
        })
        return answer*1===0?"0":answer
    }

     

    <Array.from>
    Array.from({length:3},(_,i)=>i) //[0,1,2]
    Array.from("str") // ["s","t","r"]

     실패 이유 : Xarr, Yarr,c 총 for 문을 3번 돈다. 

     

    2.  두번째 시도

    - 9~0까지 for문으로 Xarr와 Yarr의 개수를 세고 map에 넣기

    - Map을 arr로 만든 후 for문 돌려 문자열에 합치기

     

    function solution(X, Y) {
        let map = new Map()
        const Xarr = X.split('').sort((a,b)=>b-a)
        const Yarr = Y.split('').sort((a,b)=>b-a)
        
        for (let i= 9;i>=0;i--) {
            if (Xarr.includes(i+'') && Yarr.includes(i+'')) {
              const count = Math.min(
                    Xarr.lastIndexOf(i+'')-Xarr.indexOf(i+''),
                    Yarr.lastIndexOf(i+'')-Yarr.indexOf(i+'') )
              map.set(i+'',count+1)  
            }
            
        }
        // 특이 케이스 확인
        if(map.size===0) return "-1"
        if (map.size===1 && map.has('0') ) return '0'
        
        const maparr = [...map]
        let answer = ''
        console.log(maparr)
        maparr.forEach((v,i)=> {
            answer += v[0].repeat(v[1])+''
        })
        return answer
    }

     

     

    다트게임

     

    문제 설명

    카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
    갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.

    1. 다트 게임은 총 3번의 기회로 구성된다.
    2. 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
    3. 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.
    4. 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
    5. 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)
    6. 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)
    7. 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
    8. Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
    9. 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.

    0~10의 정수와 문자 S, D, T, *, #로 구성된 문자열이 입력될 시 총점수를 반환하는 함수를 작성하라.

    입출력 예제

    예제dartResultanswer설명
    1 1S2D*3T 37 11 * 2 + 22 * 2 + 33
    2 1D2S#10S 9 12 + 21 * (-1) + 101
    3 1D2S0T 3 12 + 21 + 03
    4 1S*2T*3S 23 11 * 2 * 2 + 23 * 2 + 31
    5 1D#2S*3S 5 12 * (-1) * 2 + 21 * 2 + 31
    6 1T2D3D# -4 13 + 22 + 32 * (-1)
    7 1D2S3T* 59 12 + 21 * 2 + 33 * 2

     

     

    문제풀이

    - 문자열에서 숫자만을 골라 배열에 저장한다.

    d+는 숫자로 된 문자 1개 이상인 문자열을 의미하며 g는 모든 패턴을 찾으라는 의미입니다. foo31bar52에서 이 패턴에 일치하는 것은 31과 52입니다. 그래서 리턴값을 보면 이 두개 숫자가 리턴됩니다.

    let found = "foo31bar52".match(/\d+/g); console.log(found);
    Output: [ '31', '52' ]
    위와 같이 match()를 이용하여, 아래와 같이 첫번째로 찾은 숫자와 두번쨰로 찾은 숫자를 Index로 접근할 수 있습니다.

    let num = "foo31bar52".match(/\d+/g)[0]; console.log(num); num = "foo31bar52".match(/\d+/g)[1]; console.log(num);
    Output: 31 52

    - 문자열에서 문자만을 골라 배열에 저장한다.

    - 문자열을 split(/[\d]/g) 메서드를 이용해 "SDT*#"을 확인한다. 단, 빈 문자열은 생략

    - 각각 계산한 값을 answer에 저장한다.

    - answer의 총합을 return 한다.

     

    function solution(dartResult) {
        const numArr = dartResult.match(/\d+/g).map(v=>+v)
        const strArr = dartResult.split(/\d/g).filter(v=>v!=='')
        console.log(strArr)
        var answer = [];
        for (let i =0;i<strArr.length;i++) {
            for (let s of strArr[i].split('')) {
                if(s==="S") answer.push(numArr[i]**1)
                if(s==="D") answer.push(numArr[i]**2)
                if(s==="T") answer.push(numArr[i]**3)
                if(s==="*") {answer[i] *= 2;
                    answer[i-1] *= i-1>=0? 2:1 }
                if(s==="#") answer[i] *=(-1)
            }
        }
        return answer.reduce((pre,cur)=>{return pre+cur},0);
    }
Designed by Tistory.