[JavaScript] 2022 KAKAO : 신고 결과 받기

전인혁·2022년 6월 27일
0
post-thumbnail

문제분류

구현

문제

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

이용자의 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

muzi, frodo, apeach, neo
muzi frodo, apeach frodo, frodo neo, muzi neo, apeach muzi
2

예제 출력 1

[2,1,1,0]

예제 입력 2

con, ryan

예제 출력 2

ryan con, ryan con, ryan con, ryan con

Solution

  • 필요한 변수 선언한다.
    report_set : 중복된 신고가 있으면 안되므로, Set 객체를 활용한다.
    report_list, report_cnt, mail_cnt : 유저 각각에 대한 신고 내용을 담기 위해, Map 객체를 활용한다.
    badList : 각 유저의 신고 횟수를 순차적으로 담기 위한 배열

  • Map객체에 유저 정보를 담는다.
    입력값 id_list를 활용하여, report_cnt, mail_cnt 초기화

  • 각 유저의 신고내역을 저장하고, 신고당한 횟수를 저장한다.
    report_list : key (신고한 유저), value (key가 신고한 유저 목록)
    report_cnt : key(유저), value (신고 당한 횟수)

  • 신고당한 횟수 토대로 이용 정지된 유저를 파악
    report_cnt를 토대로, k회 이상 신고된 유저, 즉 이용 정지된 유저를 파악하여 badList[ ]에 저장

  • 신고 접수 목록과 이용 정지된 유저목록을 비교하여, 최종적으로 각 유저가 받을 메일 개수 확인
    report_list와 badList를 비교하여, report_list의 value와 badList의 교집합 배열을 만들고, 그 길이를 answer에 push한다.

  • 원하는 정답 형태로 출력
    " [ " + answer.join(" ") + " ] "

코드

// "fs"로 입력 받기
const fs = require("fs");
const input = fs.readFileSync("이론/code/dev/stdin").toString().split("\n");
let id_list = input[0].trim().split(", ");
let report = input[1].trim().split(", ");
let k = parseInt(input[2]);

// Solution 함수
function Solution(id_list, report, k) {
  let report_set = new Set(report); // 중복 신고 제거를 위한 Set
  let report_list = new Map(); // 유저별 신고 접수 목록
  let report_cnt = new Map(); // 유저별 신고 당한 횟수
  let mail_cnt = new Map(); // 유저별 처리 결과 메일 수신 횟수
  let badList = []; // 이용 정지된 유저 목록
  let answer = []; // 정답 출력을 위한 Array

  // report_cnt, mail_cnt 초기화
  for (let i = 0; i < id_list.length; i++) {
    report_cnt.set(id_list[i], 0);
    mail_cnt.set(id_list[i], 0);
  }

  // 중복을 제거한 report
  report = [];
  report_set.forEach((el) => {
    report.push(el);
  });

  // report_list에 각 유저의 신고내역을 저장하고, 신고당한 횟수(report_cnt) 저장
  for (let i = 0; i < report.length; i++) {
    let list = report[i].split(" ");
    if (report_list.has(list[0])) {
      report_list.set(list[0], [...report_list.get(list[0]), list[1]]);
    } else report_list.set(list[0], [list[1]]);
    report_cnt.set(list[1], report_cnt.get(list[1]) + 1);
  }

  // 이용 정지된 유저 목록 작성 (badList)
  for (let i = 0; i < id_list.length; i++) {
    if (report_cnt.get(id_list[i]) >= k) {
      badList.push(id_list[i]);
    }
  }

  // 각 유저의 처리 결과 메일 수신 횟수 저장
  for (let i = 0; i < id_list.length; i++) {
    if (report_list.get(id_list[i]) !== undefined)
      mail_cnt.set(
        id_list[i],
        report_list.get(id_list[i]).filter((el) => badList.includes(el)).length
      );
    answer.push(mail_cnt.get(id_list[i]));
  }

  // 정답 출력
  console.log("[" + answer.join(", ") + "]");
}

Solution(id_list, report, k);

느낀 점

문제의 본문이 길어서 읽고 이해하는데 시간이 걸렸지만, 이해하고 과정을 구상하는데에는 생각보다 많은 시간이 소모되지 않았다.


Map을 처음 사용하고, 프로그래머스의 구현 문제를 많이 풀어보지 않아서인지 부족한 점이 많았다.

1. 여전히 기능별로 모듈화를 하지못해서, 코드 가독성이 떨어진다.

2. 필요한 메소드를 바로바로 떠올릴 수 있도록 많은 연습을 해야겠다는 생각을 했다. (ex : Array.inclouds 등)


이번 문제를 풀이하면서, 좋았던 점은 Map 객체의 기본적인 사용을 이해할 수 있었다는 점이다.
기본적인 메소드인 Map.set, Map.get을 활용하여 데이터를 저장하고 불러올 수 있었다. 또한 for loop를 활용하여 key를 반복해서 돌리면서 Map 내부를 순회하여 값을 처리할 수도 있었다.

profile
Front-end Developer

0개의 댓글