{ }codelper
updating a mapcounting with a mapP0228

Only the last vote counts

A class president election is held by phone. During the voting period the same student may vote again any number of times, and only the last vote of each student is counted. The first line gives the number of candidates k, and the second line gives the k candidate names separated by single spaces. The third line gives the number of votes received n, and each of the next n lines gives one vote, in the order received, as "studentId candidateName" separated by one space. Student IDs are compared as strings exactly.
So "1" and "01" are different students. For each candidate print one line with the name and the number of votes it got, separated by one space, in the order the candidates appear on the second line. A candidate with no votes is printed with 0. On the last line print the number of students whose vote was counted (the number of distinct student IDs).

Input
1 ≤ k ≤ 20, 1 ≤ n ≤ 5,000.
Candidate names are distinct, 1 to 10 lowercase English letters.
A student ID is 1 to 8 lowercase English letters and digits.
The candidate in a vote is always one of the candidates
Output
k lines (candidate name, votes), then one line (number of students)
Example 1 · stdin
3
mina joon hana
5
s1 mina
s2 joon
s1 hana
s3 joon
s2 mina
stdout
mina 1
joon 1
hana 1
3
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

Keep each student's current vote in a map and overwrite it when a new vote arrives.
The trap is that overwriting and not-overwriting look alike in many languages.
Python d[k] = v, JS/TS map.set(k, v) and Craykon d[k] = v replace the old value.
Java put overwrites too, but putIfAbsent only adds when the key is missing.
A C# indexer d[k] = v overwrites, but d.Add(k, v) throws ArgumentException on an existing key.
C++ m[k] = v overwrites, but m.insert({k, v}) and emplace do nothing when the key already exists, so the first vote stays.
If you read everything first and then count per candidate over the map's values, you cannot forget to take 1 away from the old candidate when a vote moves.
Keep student IDs as strings.
Converting with Number in JS makes "1" and "01" one student.
C has no map, so write the IDs in an array and search from the front with strcmp.

Pythonmain.py · 13 lines
k = int(input())cands = input().split()n = int(input())vote = {}                       # 학생 번호 → 지금 센 표for _ in range(n):    voter, cand = input().split()    vote[voter] = cand          # 있던 표는 덮어쓴다count = {c: 0 for c in cands}for cand in vote.values():    count[cand] += 1for c in cands:    print(c, count[c])print(len(vote))
JavaScriptmain.js · 18 lines
const tok = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);let p = 0;const k = Number(tok[p++]);const cands = tok.slice(p, p + k);p += k;const n = Number(tok[p++]);// 학생 번호는 문자열 그대로 둔다("01"과 "1"은 다른 학생)const vote = new Map();for (let i = 0; i < n; i++) {  const voter = tok[p++];  const cand = tok[p++];  vote.set(voter, cand); // set은 있던 값을 덮어쓴다}const count = new Map(cands.map((c) => [c, 0]));for (const cand of vote.values()) count.set(cand, count.get(cand) + 1);const out = cands.map((c) => `${c} ${count.get(c)}`);out.push(String(vote.size));console.log(out.join("\n"));
TypeScriptmain.ts · 18 lines
import { readFileSync } from "node:fs";const tok: string[] = readFileSync(0, "utf8").trim().split(/\s+/);let p = 0;const k: number = Number(tok[p++]);const cands: string[] = tok.slice(p, p + k);p += k;const n: number = Number(tok[p++]);const vote = new Map<string, string>();for (let i = 0; i < n; i++) {  const voter: string = tok[p++];  const cand: string = tok[p++];  vote.set(voter, cand); // set은 있던 값을 덮어쓴다}const count = new Map<string, number>(cands.map((c): [string, number] => [c, 0]));for (const cand of vote.values()) count.set(cand, (count.get(cand) ?? 0) + 1);const out: string[] = cands.map((c) => `${c} ${count.get(c)}`);out.push(String(vote.size));console.log(out.join("\n"));
JavaMain.java · 28 lines
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.HashMap;import java.util.Map;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int k = Integer.parseInt(br.readLine().trim());        String[] cands = br.readLine().trim().split("\\s+");        int n = Integer.parseInt(br.readLine().trim());        Map<String, String> vote = new HashMap<>();        for (int i = 0; i < n; i++) {            StringTokenizer st = new StringTokenizer(br.readLine());            String voter = st.nextToken();            String cand = st.nextToken();            vote.put(voter, cand); // put은 덮어쓴다(putIfAbsent는 처음 값을 지킨다)        }        Map<String, Integer> count = new HashMap<>();        for (String c : cands) count.put(c, 0);        for (String cand : vote.values()) count.merge(cand, 1, Integer::sum);        StringBuilder out = new StringBuilder();        for (String c : cands) out.append(c).append(' ').append(count.get(c)).append('\n');        out.append(vote.size()).append('\n');        System.out.print(out);    }}
C#Main.cs · 27 lines
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        int k = int.Parse(Console.ReadLine().Trim());        string[] cands = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);        int n = int.Parse(Console.ReadLine().Trim());        var vote = new Dictionary<string, string>();        for (int i = 0; i < n; i++)        {            string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries);            // 인덱서 대입은 덮어쓴다. Add는 이미 있는 열쇠에서 예외를 던진다            vote[p[0]] = p[1];        }        var count = new Dictionary<string, int>();        foreach (string c in cands) count[c] = 0;        foreach (string cand in vote.Values) count[cand]++;        var sb = new StringBuilder();        foreach (string c in cands) sb.Append(c).Append(' ').Append(count[c]).Append('\n');        sb.Append(vote.Count).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 23 lines
#include <iostream>#include <string>#include <unordered_map>#include <vector> int main() {    std::ios::sync_with_stdio(false);    int k, n;    std::cin >> k;    std::vector<std::string> cands(k);    for (auto& c : cands) std::cin >> c;    std::cin >> n;    std::unordered_map<std::string, std::string> vote;    for (int i = 0; i < n; i++) {        std::string voter, cand;        std::cin >> voter >> cand;        vote[voter] = cand; // operator[]는 덮어쓴다. insert·emplace는 있던 값을 그대로 둔다    }    std::unordered_map<std::string, int> count;    for (const auto& [voter, cand] : vote) count[cand]++;    for (const auto& c : cands) std::cout << c << ' ' << count[c] << '\n';    std::cout << vote.size() << '\n';}
Cmain.c · 32 lines
#include <stdio.h>#include <string.h> /* C에는 사전이 없어서, 학생 번호와 그 학생의 표(후보 번호)를 배열에 적고 앞에서부터 찾는다 */static char voters[5000][9];static int choice[5000];static char cands[20][11]; int main(void) {    int k, n, m = 0;    scanf("%d", &k);    for (int i = 0; i < k; i++) scanf("%10s", cands[i]);    scanf("%d", &n);    for (int i = 0; i < n; i++) {        char voter[16], cand[16];        scanf("%15s %15s", voter, cand);        int c = 0;        while (strcmp(cands[c], cand) != 0) c++;        int j = 0;        while (j < m && strcmp(voters[j], voter) != 0) j++;        if (j == m) {            strcpy(voters[m], voter);            m++;        }        choice[j] = c; /* 있던 표는 덮어쓴다 */    }    int count[20] = {0};    for (int j = 0; j < m; j++) count[choice[j]]++;    for (int i = 0; i < k; i++) printf("%s %d\n", cands[i], count[i]);    printf("%d\n", m);    return 0;}
Craykonmain.cray · 24 lines
k = Console.ReadLine().ToNumber();cands = Console.ReadLine().Trim().Split(" ");n = Console.ReadLine().ToNumber();vote = Dict();for (i = 0; i < n; i++){    p = Console.ReadLine().Trim().Split(" ");    // 같은 열쇠에 다시 넣으면 있던 표를 덮어쓴다    vote[p[0]] = p[1];}count = Dict();foreach (c in cands){    count[c] = 0;}foreach (cand in vote.Values){    count[cand] = count[cand] + 1;}foreach (c in cands){    Console.WriteLine(c + " " + count[c]);}Console.WriteLine(vote.Count);