[Programmers/CodingTest/Python]レポート結果の取得


問題の説明
新入社員の武志氏は、掲示板の不良ユーザーを通報し、メールで処理結果を送信するシステムを開発しようとした.ムーチが開発するシステムには、次のものがあります.
  • プレイヤーは1人につき1人のプレイヤーしか申告できません.
    -通報回数を制限しない.異なるプレイヤーを通報し続けることができます.
    -1人のプレイヤーを複数回通報することができるが、同じプレイヤーに対する通報回数は1回に処理される.
  • k以上で通報されたプレイヤーは掲示板の使用を停止し、そのプレイヤーを通報したすべてのプレイヤーにメールで停止事実を送信する.
    -ユーザーが申告したすべての内容を収集し、最後に掲示板の使用を一度に停止し、停止メールを送信します.
  • 以下に、完全なユーザリストが[「muzi」、「frodo」、「apeach」、「neo」、k=2(すなわち、2回以上通報された場合は使用を停止する)の例を示す.
    유저 ID		유저가 신고한 ID	설명
    "muzi"		"frodo"			"muzi"가 "frodo"를 신고했습니다.
    "apeach"	"frodo"			"apeach"가 "frodo"를 신고했습니다.
    "frodo"		"neo"			"frodo"가 "neo"를 신고했습니다.
    "muzi"		"neo"			"muzi"가 "neo"를 신고했습니다.
    "apeach"	"muzi"			"apeach"가 "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"]				["neo"]
    "apeach"	["muzi", "frodo"]	["frodo"]
    "neo"		없음					없음
    したがって、「muzi」には処理結果メールが2回、「frodo」と「apeach」にはそれぞれ処理結果メールが1回受信されます.
    ユーザIDを含む文字列配列idリスト、ユーザごとに申告されたユーザID情報を含む文字列配列レポート、停止を基準とした申告回数kをパラメータとする場合は、ユーザごとに解決関数を1つ作成し、処理結果におけるメールの受信回数を列に記録して返してください.
    せいげんじょうけん
  • 2≦id listの長さ≦1000
    -1≦id listの要素長≦10
    -idリストの要素は、ユーザーidを表す文字列であり、アルファベット小文字のみから構成されます.
    -idリストに同じIDが重複していません.
  • 1≦レポート長≦200000
    -3≦reportの要素長≦21
    Reportの要素は、「ユーザidが申告するid」形式の文字列です.
    -例えば「Muzi Frodo」は、「Muzi」が「Frodo」を通報したという意味です.
    -idは小文字のみで構成されます.
    -ユーザidと申告されたidは、スペースで区切られています.
    -自分の状況を報告しなかった.
  • 1≦k≦200,kは自然数である.
  • を返す配列は、idリストのid順に各ユーザが受信した結果メール数をリストする.
  • I/O例
    id_list								report																k	result
    ["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例説明
    I/O例#1
    問題の例.
    I/O例#2
    「ryan」は「con」を4回報告したが、与えられた条件により、1人のプレイヤーが同じプレイヤーを複数回通報した場合、1回の通報回数に処理される.そのため、「con」は一度通報された.3回以上通報されていないユーザーは、「con」と「ryan」は結果メールを受信しません.したがって、[0,0]を返します.
    時間制限ガイド
    精度テスト:10秒
    方法
    今回の問題で重要なのは繰り返し申告することです.set()関数で申告リストをセットに変換し、重複を解消し、idごとに申告回数を保存するディックシーケンスを宣言した後、レポートを巡回してディックシーケンスに値を追加し、レポートは申告者と被申告者を区別し、それぞれ他のリストに保存します.申告回数を保存しているディック社を巡回し、k以上の価値がある場合は、制限された人員を保存リストに単独で保存し、レポートを単独で保存しているリストを巡回し、申告された制限された人員のインデックス数を増やすことで解決します.
  • の答えをidリストの長さの0に入力します.
  • reportは、set()関数によってセットに変換される.
  • 報告書を申告者と被申告者が保存したリストarrに分けると発表した.
  • idごとに申告された回数はdefaultdict()として公表される.
  • ツアー
  • reportのiに挨拶を伝えます.
    ->arrではiで区切って書くことを標準とし、リストとして列挙します.
    ->total[arr[-1][1]]増加1.(増加値1はarrに入れたばかりのiにおける避難者idに相当する)
  • .
  • は、有限人員リストbadを格納すると発表した.
  • totalのnameを巡回し、cntに対するfor文.
    ->cntがk以上の場合badにnameを追加します.
  • 繰返し長
  • arrのiについてfor文を回します.
    ->arr[i][1]がbadにある場合、
    -->answer[id_list,index(arr[i][0])]増加1.
  • の答えを返します.
  • solution.py
    import collections
    def solution(id_list, report, k):
        answer = [0]*len(id_list)
        report=set(report)
        arr=[]
        total=collections.defaultdict(int)
        for i in report:
            arr.append(list(i.split()))
            total[arr[-1][1]] += 1
        bad=[]
        for name, cnt in total.items():
            if cnt>=k:
                bad.append(name)
        for i in range(len(arr)):
            if arr[i][1] in bad:
                answer[id_list.index(arr[i][0])]+=1
        return answer