[プログラマ]レポート結果の取得(Java)
問題の説明
新入社員の武志氏は、掲示板の不良ユーザーを通報し、メールで処理結果を送信するシステムを開発しようとした.ムーチが開発するシステムには、次のものがあります.
ユーザIDユーザが申告したIDは、「Muzi」「Frodo」「Muzi」「Frodo」が申告したことを示している.「apeach」「frodo」「apeach」「frodo」が「frodo」を報告した.「frodo」「neo」「frodo」は「neo」を報告した.「Muzi」「neo」「Muzi」が「neo」を通報「apeach」「muzi」「apeach」「muzi」が「muzi」を通報
各ユーザーが通報された回数は以下の通りです.
ユーザIDが申告された回数「muzi」1「frodo」2「apeach」0「neo」2
上記の例では、2回以上通報された「frodo」と「neo」の掲示板は使用を停止します.この場合、ユーザーごとに申告したIDと無効なIDを以下のように整理することができます.
プレイヤーIDユーザーが申告したID停止のIDには「Muzi」「frodo」「neo」「frodo」「neo」「frodo」「neo」「apeach」「Muzi」「frodo」「neo」「neo」がありません
したがって、「muzi」には処理結果メールが2回、「frodo」と「apeach」にはそれぞれ処理結果メールが1回受信されます.
ユーザIDを含む文字列配列idリスト、ユーザごとに申告されたユーザID情報を含む文字列配列レポート、停止を基準とした申告回数kをパラメータとする場合は、ユーザごとに解決関数を1つ作成し、処理結果におけるメールの受信回数を列に記録して返してください.
せいげんじょうけん
I/O例
id_listreportkresult["muzi", "frodo", "apeach", "neo"]["muzi frodo","apeach frodo","frodo neo","muzi neo","apeach muzi"]2[2,1,1,0]["con", "ryan"]["ryan con", "ryan con", "ryan con", "ryan con"]3[0,0]
I/O例説明
問題の例.
「ryan」は「con」を4回報告したが、与えられた条件により、1人のプレイヤーが同じプレイヤーを複数回通報した場合、1回の通報回数に処理される.そのため、「con」は一度通報された.3回以上通報されていないユーザーは、「con」と「ryan」は結果メールを受信しません.したがって、[0,0]を返します.
時間制限ガイド
私の答え
ReportedCountInfoMapは、通報者が誰を通報したか、通報された人が何度通報されたかを保存するReportedCountInfoMapを発表した.
ReportInfoMapは、同一ユーザの通報回数を1回処理するため、重複処理のためにSetとして保存する.ReportedCountInfoMapは、通報された人が停止基準以上になった場合、そのユーザを通報した通報者に停止メールを送るため、通報回数を保存する方式で行うとしている.
テストケースはすべて合格したが,既に申告したプレイヤーを申告者が再度申告する場合,処理が乱れているようで,改めて修正した.
受精前
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
class Solution {
public int[] solution(String[] idList, String[] report, int k){
// @param idList : 이용자의 ID를 담은 배열.
// @param report : 신고한 이용자와 신고당한 이용자의 정보를 담은 배열. ex) "a b",.. -> a가 b를 신고
// @param k : 신고 횟수에 따른 정지 기준 정수값.
// @return answer : id_list에 담긴 id 순서대로 각 유저가 받은 결과 메일 배열.
int[] answer = new int[idList.length];
HashMap<String, HashSet<String>> reporterInfoMap = new HashMap<>();
HashMap<String, Integer> reportedCountInfoMap = new HashMap<>();
for(String reportInfo : report){
String reporter = reportInfo.split(" ")[0]; // 신고 한 사람
String reported = reportInfo.split(" ")[1]; // 신고 당한 사람
boolean flag = false;
if(reporterInfoMap.containsKey(reporter)){
if(reporterInfoMap.get(reporter).contains(reported)){
// 이미 신고한 유저를 또 신고했을 경우
flag = true;
} else {
reporterInfoMap.get(reporter).add(reported);
}
} else {
reporterInfoMap.put(reporter, new HashSet<String>(){{
add(reported);
}});
}
if (flag) {
continue;
} else if (reportedCountInfoMap.containsKey(reported)){
reportedCountInfoMap.put(reported, reportedCountInfoMap.get(reported)+1);
} else {
reportedCountInfoMap.put(reported, 1);
}
}
for (String reported : reportedCountInfoMap.keySet()){
int reportedCount = reportedCountInfoMap.get(reported);
if(reportedCount >= k){
// 메일 발송 대상
for(int i=0; i<idList.length; i++){
if(reporterInfoMap.get(idList[i]) == null){
answer[i] = 0;
} else if(reporterInfoMap.get(idList[i]).contains(reported)){
answer[i]++;
}
}
}
}
return answer;
}
}
変更後
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
class Solution {
public int[] solution(String[] idList, String[] report, int k){
// @param idList : 이용자의 ID를 담은 배열.
// @param report : 신고한 이용자와 신고당한 이용자의 정보를 담은 배열. ex) "a b",.. -> a가 b를 신고
// @param k : 신고 횟수에 따른 정지 기준 정수값.
// @return answer : id_list에 담긴 id 순서대로 각 유저가 받은 신고 결과 메일 개수 배열.
int[] answer = new int[idList.length];
HashMap<String, HashSet<String>> reporterInfoMap = new HashMap<>();
HashMap<String, Integer> reportedCountInfoMap = new HashMap<>();
HashSet<String> reportSet = new HashSet<>(Arrays.asList(report));
for(String reportInfo : reportSet){
String reporter = reportInfo.split(" ")[0]; // 신고 한 사람
String reported = reportInfo.split(" ")[1]; // 신고 당한 사람
reporterInfoMap.putIfAbsent(reporter, new HashSet<String>(){{
add(reported);
}});
reporterInfoMap.get(reporter).add(reported);
reportedCountInfoMap.put(reported, reportedCountInfoMap.getOrDefault(reported, 0)+1);
}
for (String reported : reportedCountInfoMap.keySet()){
int reportedCount = reportedCountInfoMap.get(reported);
if(reportedCount >= k){
// 메일 발송 대상
for(int i=0; i<idList.length; i++){
if(reporterInfoMap.containsKey(idList[i]) && reporterInfoMap.get(idList[i]).contains(reported)) {
answer[i]++;
}
}
}
}
return answer;
}
}
他人の草(崔錫賢、progg)
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public int[] solution(String[] id_list, String[] report, int k) {
Users users = IntStream.range(0, id_list.length)
.mapToObj(i -> new User(i, new UserId(id_list[i])))
.collect(Collectors.collectingAndThen(Collectors.toList(), Users::new));
Reports reports = Arrays.stream(report)
.map(rawReport -> ReportParser.parse(users, rawReport))
.collect(Collectors.collectingAndThen(Collectors.toList(), Reports::new));
Mails mails = reports.generateMails(users, k);
return users.findSortedAll().stream()
.mapToInt(user -> mails.findAllByUser(user).size())
.toArray();
}
private static class Mails {
private final List<Mail> mails;
public Mails(List<Mail> mails) {
this.mails = mails;
}
public List<Mail> findAllByUser(User user) {
return mails.stream()
.filter(mail -> mail.isSameUser(user))
.collect(Collectors.toList());
}
}
private static class Mail {
private final User recipient;
public Mail(User recipient) {
this.recipient = recipient;
}
public boolean isSameUser(User user) {
return Objects.equals(recipient, user);
}
}
private static class ReportParser {
private static final String DELIMITER = " ";
public static Report parse(Users users, String report) {
String[] splitted = report.split(DELIMITER);
User reporter = users.findUser(new UserId(splitted[0]));
User reported = users.findUser(new UserId(splitted[1]));
return new Report(reporter, reported);
}
}
private static class Reports {
private final List<Report> reports;
public Reports(List<Report> reports) {
this.reports = reports;
}
public Mails generateMails(Users users, int mailThreshold) {
return users.findSortedAll().stream()
.map(user -> generateMailsOf(user, mailThreshold))
.flatMap(Collection::stream)
.collect(Collectors.collectingAndThen(Collectors.toList(), Mails::new));
}
private List<Mail> generateMailsOf(User user, int mailThreshold) {
List<Report> userReports = reports.stream()
.filter(report -> report.isReported(user))
.distinct()
.collect(Collectors.toList());
if (userReports.size() >= mailThreshold) {
return userReports.stream()
.map(Report::getReporter)
.map(Mail::new)
.collect(Collectors.toList());
}
return Collections.emptyList();
}
}
private static class Report {
private final User reporter;
private final User reported;
public Report(User reporter, User reported) {
this.reporter = reporter;
this.reported = reported;
}
public boolean isReported(User user) {
return reported.equals(user);
}
public User getReporter() {
return reporter;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Report report = (Report) o;
return Objects.equals(reporter, report.reporter) && Objects.equals(reported, report.reported);
}
@Override
public int hashCode() {
return Objects.hash(reporter, reported);
}
}
private static class Users {
private final List<User> users;
public Users(List<User> users) {
this.users = users;
}
public User findUser(UserId userId) {
return users.stream()
.filter(user -> user.getId().equals(userId))
.findAny()
.orElseThrow(() -> new IllegalArgumentException("User Not Found. id: " + userId));
}
public List<User> findSortedAll() {
return users.stream()
.sorted()
.collect(Collectors.toList());
}
}
private static class User implements Comparable<User> {
private final Integer sequence;
private final UserId userId;
public User(Integer sequence, UserId userId) {
this.sequence = sequence;
this.userId = userId;
}
public UserId getId() {
return userId;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(userId, user.userId);
}
@Override
public int hashCode() {
return Objects.hash(userId);
}
@Override
public int compareTo(User other) {
return this.sequence.compareTo(other.sequence);
}
}
private static class UserId {
private final String id;
public UserId(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserId userId1 = (UserId) o;
return Objects.equals(id, userId1.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
return "Id{" +
"id='" + id + '\'' +
'}';
}
}
}
他の人がコードを短く書くために最善を尽くしていることが明らかになった.この人は対象を導きに問題を解決する最良の人の選択のようだ.(しまった…)n/a.結論
今回の問題の鍵は,申告者が申告したプレイヤーを再申告する場合をどのように処理するかにある.ほとんどがSetで解決している人で、たまにStream APIで解決している人も見かけます.問題そのものの難易度は高くなく、問題の指紋を読み取って近づければ、すぐに解決できる.
Reference
この問題について([プログラマ]レポート結果の取得(Java)), 我々は、より多くの情報をここで見つけました https://velog.io/@ckr3453/프로그래머스-신고-결과-받기-javaテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol