알고리즘/프로그래머스 - JS

[프로그래머스 - JS] level.2 프린터

개발자성장기 2022. 12. 23. 13:22
반응형

 

 


나의 풀이 

<첫 통과 코드>

더보기
function solution(priorities, location) {
    if(priorities.length === 1) return 1
    let num = 0
    const sample = priorities.reduce((acc,cur,index,arr) => {
        const max = Math.max(...arr)
        if (max === cur || acc.filter(x => Object.values(x).includes(max))[0]){
            acc.splice(num,0,{[index]:cur})
            num += 1
            return acc
        }
        acc.push({[index] : cur}) 
        return acc
    },[])
    const newArray = filtering(sample)
    const result = newArray.reduce((acc, cur, index) => {
        if(JSON.stringify(cur) === JSON.stringify({[location]:priorities[location]})) acc = index + 1
        return acc
    },null)
    return result ? result : priorities.length

}

function filtering(sample, print = []) {
    if(sample.length === 1) return print
    const maxNumber = sample.map((x) => Number(Object.values(x)))
    const max = Math.max(...maxNumber)
    const toto = Number(Object.values(sample[0]))
    if(max === toto ){
       print.push(sample.shift())
    } else{
            sample.push(sample.shift())
    }
    return filtering(sample, print)   
}

 

<간단한 리팩터링 후>

function solution(priorities, location) {
  if (priorities.length === 1) return 1;

  const prioritiesIndexed = shiftMaximumToFrontWithIndex(priorities);
  const sortPriorities = sortAccordingToImportance(prioritiesIndexed);
  const result = locateResultByLocation(sortPriorities, priorities, location);

  return result ? result : priorities.length;
}

function shiftMaximumToFrontWithIndex(priorities, accIndex = 0) {
  const max = Math.max(...priorities);
  const prioritiesIndexed = priorities.reduce((acc, cur, index) => {
    if (max === cur || acc.filter((x) => Object.values(x).includes(max))[0]) {
      acc.splice(accIndex, 0, { [index]: cur });
      accIndex += 1;
      return acc;
    }
    acc.push({ [index]: cur });
    return acc;
  }, []);
  return prioritiesIndexed;
}

function sortAccordingToImportance(prioritiesIndexed, print = []) {
  if (prioritiesIndexed.length === 1) return print;
  const maxNumber = Math.max(...prioritiesIndexed.map((x) => Number(Object.values(x))));
  const firstNumber = Number(Object.values(prioritiesIndexed[0]));
  if (maxNumber === firstNumber) {
    print.push(prioritiesIndexed.shift());
  } else {
    prioritiesIndexed.push(prioritiesIndexed.shift());
  }
  return sortAccordingToImportance(prioritiesIndexed, print);
}

function locateResultByLocation(sortPriorities, priorities, location) {
  return sortPriorities.reduce((acc, cur, index) => {
    if (JSON.stringify(cur) === JSON.stringify({ [location]: priorities[location] })) acc = index + 1;
    return acc;
  }, null);
}

 

 

정말 비효율 적이다.  

아직 스택과 큐를 100% 정확하게 활용 못하는 것 같다. 

다시 제대로 공부하자 

 

코드 설명

1. 

  const prioritiesIndexed = shiftMaximumToFrontWithIndex(priorities);

이 함수는 priorities의 max값을 제일 앞으로 위치시킨다.

(단순히 max값을 맨 앞으로 가져오는게 아니라 index와 함께 전체적인 순서를 유지하면서 max값을 맨 앞으로 가져온다.)

(ex   [ 4, 5 ,1 ].    ->  [ { 1 : 5 }, { 2 : 1 }, { 0 : 4 } ]    key는 index이고 value는 value이다 )

하지만 여기서 [ 4, 5, 3, 2 ]   ->  5, 3, 2, 4   까지만 하고 return 하기에  다음 함수에서 5, 4, 3, 2 이렇게 만들어준다.

 

2. 

  const sortPriorities = sortAccordingToImportance(prioritiesIndexed);

  이 함수는   max 값 뒤에있는 값들을 중요도가 높은 순서대로 정렬해준다. 

 

3. 

const result = locateResultByLocation(sortPriorities, priorities, location);

location에 해당되는 값을 반환해주는 함수이다. 

 

지금 생각해봐도  정말 별로이다. 

그냥 1, 2번을 한번에 해줄 수 없었을까? 왜 굳이 두 번에 나누어서 해야하지 ? 

그리고 굳이 전부 정렬을 한뒤에 result를 return 해줘야하나 ? 

location에 알맞은 값이 나오면 바로 return하고 함수를 종료하면 안되나 ??? 

해서 정답 통과후 다른 사람 코드를 보고 아예전체 수정을 하였다. 

 

 

function solution(priorities, location, result = 0) {
  const queue = priorities.map((p, i) => ({ priority: p, index: i }));

  while (queue.length > 0) {
    const current = queue.shift();
    const higherPriority = queue.some((d) => d.priority > current.priority);

    if (higherPriority) {
      queue.push(current);
      continue;
    }
    result += 1;
    if (current.index === location) {
      return result;
    }
  }
}

1. queue를 통해  priorities 배열 내의 값에 index를 포함시켜주기 위해 객체로 변경해 준다.  [{ value  : index } , ...]이런식으로 생성 됨

2. current    ->  배열의 맨 앞의 값을 추출한다.

3. higherPriority  -> 현재 값보다  더 큰 값이 배열 내 존재하니? 

4. if. ->   higher~이 true이면  현재 값을 queue 배열의 가장 뒤로 보낸다. 그리고 다시 while문 처음부터 시작  

5. if   ->   false이면 result += 1; 을 해준다.

6.  if  현재 index와 location이 같으면 result를 return해준다. 

 

여기서 while대신 for문을 사용하면  for루프 도중에 계속 배열이 변경되어 에러가 발생할 수 있어 while을 사용하였다.

else를 지양하기 위해 continue를 사용하였다. 

 


다른 사람 풀이 

function solution(priorities, location) {
    var list = priorities.map((t,i)=>({
        my : i === location,
        val : t
    }));
    var count = 0;        
    while(true){
        var cur = list.splice(0,1)[0];        
        if(list.some(t=> t.val > cur.val )){
            list.push(cur);                        
        }
        else{            
            count++;
            if(cur.my) return count;
        }
    }
}

 

반응형