STUDY/코딩테스트 문제풀이

[프로그래머스] 코딩테스트 문제풀이 (신고 결과 받기)

수밤바 2022. 8. 22. 15:33
728x90

https://school.programmers.co.kr/learn/courses/30/lessons/92334

 

프로그래머스

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

programmers.co.kr

 

1. k번 이상 신고된 user는 아이디가 정지된다

2. 리스트는 [이용자ID 신고당한ID]로 ID사이 공백이 있다(예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.)

 
이용자의 ID가 담긴 문자열 배열 id_list, 
각 이용자가 신고한 이용자의 ID 정보가 담긴 문자열 배열 report, 
정지 기준이 되는 신고 횟수 k가 매개변수로 주어질 때, 
각 유저별로 처리 결과 메일을 받은 횟수를 배열에 담아 return 하도록 solution 함수를 완성해주세요.
const a = ["muzi", "frodo", "apeach", "neo"];
const b = ["muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi", "apeach muzi", "apeach muzi", "apeach muzi", "apeach muzi", "apeach muzi", "apeach muzi", "apeach muzi"];
const k = 2;

solution(a,b,k)

function solution(id_list, report, k) {
  var answer = [];
  return answer;
}

 

문제가 많이 어려워서

풀긴했지만 계속 시간초과가 되어 결국 컨닝했다

 

컨닝하고도 이건 어차피 못풀었겠다 싶었다

 

내가 작성한 코드

더보기

 

▶️ 처음 작성한 코드

function solution_1 (id_list, report, k) {
  var answer = [];
  var answerList = []; 

  id_list.map( name => {
    let reportIn = 0;
    let reportOut = 0;
    let reportInNM = [];
    let reportOutNM = [];
    report.filter(list=>{
        const listDet = list.split(' ');
        if(listDet.indexOf(name)==0) {
          if(reportOutNM.indexOf(listDet[1]) == -1 ){
            reportOut++;
            reportOutNM.push(listDet[1]);
          }
        }else if(listDet.indexOf(name)>0) {
          if(reportInNM.indexOf(listDet[0]) == -1 ){
            reportIn++;
            reportInNM.push(listDet[0]);
          }
        }
    })
    answerList.push({
        'userNM':name,
        'reportIn':reportIn,
        'reportInNM':reportInNM,
        'reportOut':reportOut,
        'reportOutNM':reportOutNM,
    })
  })
  let mailList = [];
  answerList.map(a=>{
    if (a.reportIn >= k) {
      a.reportInNM.map(nm => mailList.push(nm))      
    }
  })

  id_list.map(el=>{
    let count = 0;
    for(var i=0; i<mailList.length; i++){
      if (mailList[i] == el) count++;
    }
    answer.push(count)
  })
    return answer;
}

 

{
        'userNM':name, // user ID
        'reportIn':reportIn,  // 신고당한 횟수
        'reportInNM':reportInNM, // 나를 신고한유저 이름
        'reportOut':reportOut, // 내가 신고한 횟수
        'reportOutNM':reportOutNM, // 내가 신고한 아이디
  }

user별로 신고당한 횟수, 나를 신고한유저 이름, 내가 신고한 횟수, 내가 신고한 아이디를 정리해서 배열로 정리했다

k번 신고되어 정지당한 유저도 메일을 받는줄 알았는데

정지만되고 고지는 안하나보다

 

 

 

  let mailList = [];

  answerList.map(a=>{

    if (a.reportIn >= k) {

      a.reportInNM.map(nm => mailList.push(nm))      

    }

  })

신고한 횟수가 k번이 넘을경우 나를 신고한 유저 이름을 따로 배열에 담는다

 

 

  id_list.map(el=>{

    let count = 0;

    for(var i=0; i<mailList.length; i++){

      if (mailList[i] == el) count++;

    }

    answer.push(count)

  })

id_list의 순서에 맞게 카운트해서 제출한다

 

첫번째 답안지는 순회하는 구문과 불필요한 부분이 너무 많다고 생각되어 간추려봤다

 

 

 

▶️ 두번째 제출한 코드

function solution (id_list, report, k) {
  var answer = new Array(id_list.length);
  answer.fill(0);

  const uniqueReport = report.filter((element, index) => {
    return report.indexOf(element) === index;
  });
  
  id_list.map( (name) => {
    let reportIn = 0;
    let reportInNM = [];

    uniqueReport.filter(list=>{
      const listDet = list.split(' ');
      if(listDet.indexOf(name)>0) {
        reportIn++;
        reportInNM.push(listDet[0]);
      }
    })
    if (reportIn >= k) {
      reportInNM.filter(el=>{
        const i = id_list.indexOf(el);
        answer[i] +=1;
      });
    }
  });

  console.log('===>',answer)
  return answer;
}

id_list length만큼 배열에 0으로 초기화를 시키고

중복제거를 먼저 한다

id_list로 순회하며 한 ID당 report의 신고횟수와 신고자를 정리한다

report순회후 k이상일 경우만 id_list의 순서에 맞게 count한다

 

이 답안도 시간초과로 탈락되었다

순회하는 구문안에 또 순회하는 구문때문에 속도가 나오지 않는다

 

report를 순회하면서 어떻게 id_list의 순서와 비교값 종속없이 count할수 있을지 전혀 모르겠어서 

컨닝을 했다...

 

Dictionary 방식과

value만 꺼내쓰는 방식 (Object.values(..)) 을 참고했다

 

 

 

 

최종 제출한 답안

function solution (id_list, report, k) {
  var answer = [];
  
  // userMailNo : 메일보내는 횟수
  // reportNoList : 신고당한 횟수
  var userMailNo={};
  var reportNoList={};
  id_list.map(id => {
    reportNoList[id]=0;
    userMailNo[id]=0;
  });
  
  // 중복제거
  const uniqueReport = [...new Set(report)].map(item=>item.split(' '));

  uniqueReport.filter(list=>{
    reportNoList[list[1]] +=1;
  })
  uniqueReport.map(rep=>{
    if(reportNoList[rep[1]] >= k) {
      userMailNo[rep[0]] +=1;
    }
  })
  answer = Object.values(userMailNo);

  console.log('===>',answer)
  return answer;
}

 

> 초기화

id_list의 ID만큼 신고당한 횟수(reportNoList) 와 메일보내는 횟수(userMailNo) 만들고 0으로 초기화 한다

  var userMailNo={};
  var reportNoList={};
  
  id_list.map(id => {
    reportNoList[id]=0;
    userMailNo[id]=0;
  });

{'ID':0, 'ID':0, 'ID':0, 'ID':0 ...}

 

 

 

 

> 중복제거

  const uniqueReport = [...new Set(report)].map(item=>item.split(' '));

new Set

new Set(report) : 중복요소 제거

[...new Set(report)] : 중복요소 제거후 배열로 변환

.map(item=>item.split(' ')) : 공백을 기준으로 분리

  • set이란!?
const roles = new Set();
set은 중복을 허용하지 않는 데이터 집합
.add (roles.add('User')) : 이미 값이 있을경우(add 하는 값이 중복일 경우) 아무일도 일어나지 않음
.size (roles.size) : 사이즈 반환
.delete (roles.delete('User')) : 제거에 성공하면 ture, 아무일도 없었다면 false 반환

 

 

 

> 신고횟수 count

user당 신고가 몇번 되었는지 count

  uniqueReport.filter(list=>{
    reportNoList[list[1]] +=1;
  })

report의 신고당한 ID별로(list[1]) count

// reportNoList : { muzi: 1, frodo: 2, apeach: 0, neo: 2 }

 

 

 

 

> 메일보낼 ID count  

k번 이상 신고당해서 정지된 유저를 신고한 user에게 결과메일 보낼껀데

몇번 메일을 받을지 궁금해서 취합

  uniqueReport.map(rep=>{
    if(reportNoList[rep[1]] >= k) {
      userMailNo[rep[0]] +=1;
    }
  })

 

reportNoList : {신고당한 ID : 신고횟수}

rep[0] : user ID

rep[1] : 신고당한 ID

 

reportNoList의 rep[1](신고당한 ID)를 호출하여 그 value가 k보다 클경우

userMailNo의 rep[0](신고한 user ID)로 key를 만들고 value에 count

 

 

> 취합한 값 출력

answer = Object.values(userMailNo);

userMailNo의 value만 출력된다

Object.values() : 파라메터의 열거 가능한 속성의 값들로 이루어진 배열을 반환