[프로그래머스]신고 결과 받기

lee-goeun·2022년 5월 7일
0

문제링크
https://programmers.co.kr/learn/courses/30/lessons/92334

문제 설명

신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다.

  • 각 유저는 한 번에 한 명의 유저를 신고할 수 있습니다.
    • 신고 횟수에 제한은 없습니다. 서로 다른 유저를 계속해서 신고할 수 있습니다.
    • 한 유저를 여러 번 신고할 수도 있지만, 동일한 유저에 대한 신고 횟수는 1회로 처리됩니다.
  • k번 이상 신고된 유저는 게시판 이용이 정지되며, 해당 유저를 신고한 모든 유저에게 정지 사실을 메일로 발송합니다.
    • 유저가 신고한 모든 내용을 취합하여 마지막에 한꺼번에 게시판 이용 정지를 시키면서 정지 메일을 발송합니다.

다음은 전체 유저 목록이 ["muzi", "frodo", "apeach", "neo"]이고, k = 2(즉, 2번 이상 신고당하면 이용 정지)인 경우의 예시입니다.

각 유저별로 신고당한 횟수는 다음과 같습니다.

위 예시에서는 2번 이상 신고당한 "frodo"와 "neo"의 게시판 이용이 정지됩니다. 이때, 각 유저별로 신고한 아이디와 정지된 아이디를 정리하면 다음과 같습니다.

따라서 "muzi"는 처리 결과 메일을 2회, "frodo"와 "apeach"는 각각 처리 결과 메일을 1회 받게 됩니다.

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

제한사항

  • 2 ≤ id_list의 길이 ≤ 1,000
    • 1 ≤ id_list의 원소 길이 ≤ 10
    • id_list의 원소는 이용자의 id를 나타내는 문자열이며 알파벳 소문자로만 이루어져 있습니다.
    • id_list에는 같은 아이디가 중복해서 들어있지 않습니다.
  • 1 ≤ report의 길이 ≤ 200,000
    • 3 ≤ report의 원소 길이 ≤ 21
    • report의 원소는 "이용자id 신고한id"형태의 문자열입니다.
    • 예를 들어 "muzi frodo"의 경우 "muzi"가 "frodo"를 신고했다는 의미입니다.
    • id는 알파벳 소문자로만 이루어져 있습니다.
    • 이용자id와 신고한id는 공백(스페이스)하나로 구분되어 있습니다.
    • 자기 자신을 신고하는 경우는 없습니다.
  • 1 ≤ k ≤ 200, k는 자연수입니다.
  • return 하는 배열은 id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 수를 담으면 됩니다.

입출력 예

문제풀이

  1. report에 중복된 값을 제거하고 report 2번째 요소의 중복 갯수를 센다.
  2. 중복갯수가 k보다 작으면 report에 해당 요소를 제거한다.
  3. id_list 순서대로 report에 남아있는 요소와 일치하는 값이 있으면 1씩 증가해서 정답 배열을 리턴한다.

코드

function solution(id_list, report, k) {
    report = report.filter((v,i) => i == report.indexOf(v));
    let accu = report.map(v => v.split(" "));
    let count = accu.reduce((acc, cur) => {
        acc[cur[1]] = (acc[cur[1]] || 0) + 1;
        return acc;
    },{});
    let answer = Array(id_list.length).fill(0);
    for (let [key, value] of Object.entries(count)) 
        if(value<k)  accu = accu.filter(e => e[1] != key);
    console.log(accu)
     id_list.map((v, i) => accu.map(e => v == e[0] ? answer[i]++ : answer[i]));
    return answer;
}

이렇게 하니 시간초과가 난다ㅠㅠ 아마 반복문을 두 번 돌려서 그런 거 같은데 어떻게 반복문을 한번으로 줄여야 할지 모르겠어서 다른 분 코드를 봤다..

다른사람 코드

function solution(id_list, report, k) {
   let reports = [...new Set(report)].map(a=>{return a.split(' ')});
   let counts = new Map();
   for (const bad of reports){
       counts.set(bad[1],counts.get(bad[1])+1||1)
   }
   let good = new Map();
   for(const report of reports){
       if(counts.get(report[1])>=k){
           good.set(report[0],good.get(report[0])+1||1)
       }
   }
   let answer = id_list.map(a=>good.get(a)||0)
   return answer;
}

신고를 받은 누적갯수와 메일을 받은 누적갯수에 대한 배열을 따로 설정하여 반복문의 수를 줄인 거 같다.

TIL

  • new Map : 새로운 map 생성
  • map.get( key ) : map에 key에 대한 value값을 리턴
  • map.set( key, value ) : key와 value값 추가
  • ( bad[1]+1 || 1 ) : bad[1] 값에 1을 추가하거나 1의 값으로 셋팅
  • map에 대한 공부를 더해서 map을 잘 사용할 수 있도록 해야겠다.
  • 변수를 설정할 때 큰 맥락으로 잡기

0개의 댓글