Algorithm

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

죠죠_ 2022. 6. 29. 13:26

 

 

코딩테스트 연습 - 신고 결과 받기

문제 설명 신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의

programmers.co.kr

 

맨날 알고리즘 무서워서 도망치다가 이번에는 정말 안되겠어서 

프로그래머스에 들어갔는데. 레벨 1도 어렵다;;;; 

하다보면 금새 적응하겠지 낙관하다가도 이거 아직은 한 문제 푸는데 너무 오래 걸린다.

 

문제는 총4번 정도 다시 풀어봤는데

1차 시도 : 코드만 길어지고 문제 갈피를 잡지 못해 실패 

2차 시도 : 모범답안에 감탄해 따라서 풀어봄

3차 시도 : 위 과정 반복

4차 시도 : 내 스타일로 다시 짜기  

 

나도 저 코드 보고 장성훈씨 같은 마음이였음을...ㅜ

 

몇 번 다시 풀면서 손에 익히긴했는데 

나는 하나씩 스텝바이 스텝 짜는걸 더 좋아하는지 조금 수정하고 싶어졌다.

 

처음 푸는 마음으로 다시 문제를 추려보니 

1. 신고자와 신고당한 유저의 중복건수를 제한 후 유저별 report 당한 회수 구하기 

2. k번 이상 신고되어 정지되는 회원

3. 정지 회원을 신고한 회원이 총 몇 번 메일을 수신하는지 

이런 플로우로 정리해 볼 수 있었다.

 

우선 입력값으로 받는 report는 중복 데이터가 있어 정제가 필요했다. 

 // report 신고자, 신고당한 유저 나누기 (중복 제거)
    const reports = [...new Set(report)].map(x => x.split(' '));

Set 객체는 자료형에 관계 없이 원시 값과 객체 참조 모두 유일한 값을 저장할 수 있음 (중복 x)

 

 // 유저별 report 당한 회수
let reportedUser = new Map();
for (const reported of reports) {
    reportedUser.set(reported[1],reportedUser.get(reported[1]) + 1 || 1);
}

유저별로 report 당한 회수를 map에 담아주는데 

기존에 신고 내역이 있으면 +1을 누적한다

 

 // 정지 회원 (k번 이상 reported)
let blockedUser = []
for (let [key,val] of reportedUser) {
    if (val >= k) {
        blockedUser.push(key)
    }
}

신고당한 회원들 중 회수(val)이 k차례 이상인 회원을 추려 blockedUser에 담아준다

  // 메일 수신 회수
    let mailedCnt = new Map();
    for (const user of reports) {
        for (let i = 0; i < blockedUser.length; i++ ) {
             if (user[1] === blockedUser[i]) {
                 mailedCnt.set(user[0],mailedCnt.get(user[0]) +1 ||1 )
             }
        }
    }

위와 비슷한 방법으로 이용이 정지된 회원을 신고한 적 있는 회원을 찾아 cnt를 누적한다

 

let answer = id_list.map((key,val) => mailedCnt.get(key)|0);

이제 최초에 입력받은 회원수에 앞서 누적한 메일 수신 회수를 누적할건데

메일을 아예 받을 일 없는 회원은 0을 set 해 줘야한다.

 

마지막 answer에서 매번 헤매는데. 

아무래도 map을 제대로 이해를 못해서 그런것같다. 

function solution(id_list, report, k) {
    // report 신고자, 신고당한 유저 나누기 (중복 제거)
    const reports = [...new Set(report)].map(x => x.split(' '));
    
    // 유저별 report 당한 회수
    let reportedUser = new Map();
    for (const reported of reports) {
        reportedUser.set(reported[1],reportedUser.get(reported[1]) + 1 || 1);
    }
    
    // 정지 회원 (k번 이상 reported)
    let blockedUser = []
    for (let [key,val] of reportedUser) {
        if (val >= k) {
            blockedUser.push(key)
        }
    }
    
    // 메일 수신 회수
    let mailedCnt = new Map();
    for (const user of reports) {
        for (let i = 0; i < blockedUser.length; i++ ) {
             if (user[1] === blockedUser[i]) {
                 mailedCnt.set(user[0],mailedCnt.get(user[0]) +1 ||1 )
             }
        }
    }
    
    let answer = id_list.map((key,val) => mailedCnt.get(key)|0);
    
    return answer;
}