2018년 9월 15일 토요일

카카오톡 블라인드 테스트..

를 쳐봤는데, 당연하게도 알고리즘에 a도 안파던 놈답게 2번까지가 한계였습니다..

const testInput =
["Enter uid1234 Muzi", "Enter uid4567 Prodo", "Leave uid1234", "Enter uid1234 Prodo", "Change uid4567 Ryan"]
console.log(solution(testInput));



function solution(record) {
if(typeof(record)!="object" || !record.length || record.length > 100000){
throw new Error('[ERROR] givin parameter record type is not array!');
}
const tempLogArr = stringDivider(record);
const userIdMap = storeUniqueUserInfo(tempLogArr);
let result = [];
convertLog(userIdMap,tempLogArr,(err,res)=>{
if(err){
throw new Error(err);
}else{
result = res;
}
});
return result;
}

function stringDivider(raw){ //주어진 raw data 를 작업이 편하게 나눕니다.
let arrays = new Array();
try{
for(var i in raw){
arrays.push(raw[i].split(' ',3));
}
return arrays;
}catch(e){
throw new Error(`[ERROR][stringDivider func]${e}`);
}
}

function storeUniqueUserInfo(raw){ //현제 주어진 raw data 에 고유한 userId를 map에 K:userId , V:nick 으로 끝단부터 읽습니다.
//거꾸로 읽으며, 중복은 무시하기 떄문에, Chnage 를 해도 문제가 없습니다. 현제 맵에는 최신 nick를 저장하기 때문 입니다.
var uniqueUsers = new Map();
for(var i = raw.length-1 ; i >= 0 ; i-- ){
if(!uniqueUsers.get(raw[i][1])){
uniqueUsers.set(raw[i][1],raw[i][2]);
}
}
return uniqueUsers;
}

function convertLog (userIdMap,tempLogArr,cb){ //최종적으로 주어진 데이터들을 출력물에 맞게 만드는 함수입니다.
//input parameter's data type are like
//tempLogArr = [ ['status','userId','userNick'],['status','userId','userNick'] ] ;
//userIdMap = Map K : userId, V : userNick

var totalLog = new Array();
try{
for(var i in tempLogArr){
const curStatus = tempLogArr[i][0];
if(curStatus !=='Change'){
const curLog = `${userIdMap.get(tempLogArr[i][1])}님이 ${curStatus ==='Enter' ? '들어왔습니다.' : '나갔습니다.'}`;
totalLog.push(curLog);
}
}
cb(null,totalLog);
}catch(e){
cb(new Error(`[ERROR][convertLog func]${e}`));
}
}

testInput의 로그창이 들어오면, 클라이언트가 읽어보기 쉽도록 문자열을 변형하여 출력하는 문제였습니다..
 무식하게 for문만 써서 한시간이나 걸렸네요 -_-;;

var N = 4
var stages = [4, 4, 4, 4, 4];
var expect = [4, 1, 2, 3]
console.log(solution(N,stages));

function solution(N, stages) {
if(typeof(N)!='number' || N < 1 || N >500){
throw new Error(`[ERROR]GIVIN PARAMETER N IS OUT OF RANGE`);
}
if(typeof(stages)!=='object' || stages.length < 1 || stages.length > 200000 ){
throw new Error(`[ERROR]GIVIN PARAMETER stages IS OUT OF RANGE`);
}
const sortedStages = orderUserStages(stages);
let stageFailArr = new Array();
for(var curStage = 1 ; curStage < N+1 ; curStage++){
const curStageUsersLen = findusersArr(sortedStages,curStage);
stageFailArr.push([curStage,calculate(curStageUsersLen)]);
}
var answerMap = [];
answerMap = divideNConqure(stageFailArr);
return extrectStageNumber(answerMap);
}

function orderUserStages(rawstages){
var sortedArr;
sortedArr = rawstages.sort(function(a,b){
return b - a;
});
return sortedArr;
}//userStage 를 정렬합니다. 오름차순 입니다.

function calculate(sortedStagesLen){
try{
return sortedStagesLen[1] / sortedStagesLen[0];
}catch(e){
return 0;
}
}//계산부 입니다.

function findusersArr(sortedStages,curStage){
for(var i in sortedStages){
if(sortedStages[sortedStages.length-1] === curStage){
return countUserArr(sortedStages,curStage);
}else if(sortedStages[i] < curStage){
sortedStages=sortedStages.slice(0,i);
return countUserArr(sortedStages,curStage);
}
}
}//정렬된 userStage 배열을 전체적으로 스켄하여, 선택한 스테이지의 유저들을 모두 불러옵니다.

function countUserArr(sortedStages,curStage){
var nCount = 0 ;
for(var i in sortedStages){
if(sortedStages[i] ===curStage)
nCount += 1;
}
return [sortedStages.length,nCount];
}// 정렬된 userstage 를 [깬사람, 풀고있는사람] 으로 리턴합니다.

function divideNConqure(arr){
if(arr.length > 3){
const half = Math.floor(arr.length / 2);
const left = divideNConqure(arr.slice(0,half));
const right = divideNConqure(arr.slice(half,arr.length));
var temparr = new Array();
var leftPiv = 0, rightPiv = 0;
while(temparr.length != arr.length){
try{
if(left[leftPiv][1] >= right[rightPiv][1]){
temparr.push(left[leftPiv]);
leftPiv += 1;
}else if(left[leftPiv][1] < right[rightPiv][1]){
temparr.push(right[rightPiv]);
rightPiv += 1;
}
}catch(e){
if(left[leftPiv] ==undefined){
temparr.push(right[rightPiv]);
rightPiv += 1;
}else{
temparr.push(left[leftPiv]);
leftPiv += 1;
}
}
}
return temparr;
}else{
for(var i = 0 ; i < arr.length ; i ++){
for(var j = i+1 ; j < arr.length ; j++){
if(arr[i][1] < arr[j][1]){
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
}// array[ array[ stageNum, stageUsers ],] 를 파라메터로 받습니다. 분할정복법으로 퀵소트 합니다. 오름차순 정렬입니다.

function extrectStageNumber(arr){
var result = [];
for(var i in arr){
result.push(arr[i][0]);
}
return result;
} //최종적으로 stage 번호를 출력합니다.

1부터 N번째 스테이지까지의 클리어 실패율을 도출 해 내는 문제였습니다.
stage 배열은, 각 유저별로 몇번째 스테이지에 있는지 정보입니다.
이 두 값을 통해, 실패율이 가장 높은 스테이지부터 차례로 배열에 넣어 출력하는 문제입니다.
고수님들 답지를 보니 20라인만에 다 짜버리는데 100라인짜리 내 코드를 보니 자괴감 들고 괴로워..

(숙련된 개발자의 코드. 효율성 테스트도 다 통과했다고 합니다)

이 코드를 분석해서 내껄로 만들어 응용하는 단계정도는 되야, 어느정도 js를 하는 개발자가 되겠거니 하며 기록을 남겨둡니다..

댓글 없음:

댓글 쓰기