-
[코딩테스트] 프로그래머스 javascript 1단계 - 실패율, 명예의 전당(1), 다트게임, 숫자 짝꿍알고리즘/코딩 테스트 2023. 2. 1. 16:36
실패율
문제 설명
슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의 수가 급감한 것이다. 원인은 신규 사용자와 기존 사용자 사이에 스테이지 차이가 너무 큰 것이 문제였다.
이 문제를 어떻게 할까 고민 한 그녀는 동적으로 게임 시간을 늘려서 난이도를 조절하기로 했다. 역시 슈퍼 개발자라 대부분의 로직은 쉽게 구현했지만, 실패율을 구하는 부분에서 위기에 빠지고 말았다. 오렐리를 위해 실패율을 구하는 코드를 완성하라.
- 실패율은 다음과 같이 정의한다.
- 스테이지에 도달했으나 아직 클리어하지 못한 플레이어의 수 / 스테이지에 도달한 플레이어 수
전체 스테이지의 개수 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 }
다트게임
문제 설명
카카오톡 게임별의 하반기 신규 서비스로 다트 게임을 출시하기로 했다. 다트 게임은 다트판에 다트를 세 차례 던져 그 점수의 합계로 실력을 겨루는 게임으로, 모두가 간단히 즐길 수 있다.
갓 입사한 무지는 코딩 실력을 인정받아 게임의 핵심 부분인 점수 계산 로직을 맡게 되었다. 다트 게임의 점수 계산 로직은 아래와 같다.- 다트 게임은 총 3번의 기회로 구성된다.
- 각 기회마다 얻을 수 있는 점수는 0점에서 10점까지이다.
- 점수와 함께 Single(S), Double(D), Triple(T) 영역이 존재하고 각 영역 당첨 시 점수에서 1제곱, 2제곱, 3제곱 (점수1 , 점수2 , 점수3 )으로 계산된다.
- 옵션으로 스타상(*) , 아차상(#)이 존재하며 스타상(*) 당첨 시 해당 점수와 바로 전에 얻은 점수를 각 2배로 만든다. 아차상(#) 당첨 시 해당 점수는 마이너스된다.
- 스타상(*)은 첫 번째 기회에서도 나올 수 있다. 이 경우 첫 번째 스타상(*)의 점수만 2배가 된다. (예제 4번 참고)
- 스타상(*)의 효과는 다른 스타상(*)의 효과와 중첩될 수 있다. 이 경우 중첩된 스타상(*) 점수는 4배가 된다. (예제 4번 참고)
- 스타상(*)의 효과는 아차상(#)의 효과와 중첩될 수 있다. 이 경우 중첩된 아차상(#)의 점수는 -2배가 된다. (예제 5번 참고)
- Single(S), Double(D), Triple(T)은 점수마다 하나씩 존재한다.
- 스타상(*), 아차상(#)은 점수마다 둘 중 하나만 존재할 수 있으며, 존재하지 않을 수도 있다.
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); }
'알고리즘 > 코딩 테스트' 카테고리의 다른 글
[코딩테스트 javascript] 체육복 - Greedy ,그리디, 탐욕 (0) 2023.02.02 [코딩테스트 javascript] 여행경로 - BFS,DFS , 그래프 탐색 알고리즘, 너비탐색알고리즘,깊이탐색알고리즘 (0) 2023.02.01 [코딩테스트] 프로그래머스 javascript 1단계 - 2016년, 소수 찾기 (0) 2023.01.31 [코딩테스트 javascript] 단어변환 - BFS , 그래프 탐색 알고리즘, 너비탐색알고리즘 (0) 2023.01.30 [코딩테스트 javascript] 네트워크 - DFS , 그래프 탐색 알고리즘 (0) 2023.01.30 - 실패율은 다음과 같이 정의한다.