Sales records are given one per line until the end of input.
A record line is a product name and an amount, separated by one or more whitespace characters (spaces or tabs).
A line may also have whitespace at its start and end.
A line that is empty or only whitespace is not a record, so skip it. More records may follow a blank line.
For each product, print "name count total" on its own line, in the order each product first appeared.
On the last line, print "TOTAL allCount allTotal".
Write every total with exactly two digits after the decimal point (12.5 as 12.50, 7 as 7.00).
If there are no records at all, print only "TOTAL 0 0.00".
Input
0 to 10,000 records, each line at most 100 characters without the line break, at most 1,000 distinct names. Names are 1 to 12 lowercase English letters. Amounts are between 0 and 10,000 inclusive and have no decimal part or 1 to 2 decimal digits, like "7", "7.5" or "0.05"
Output
one line per product, then the TOTAL line
Example 1 · stdin
mina 12.5
jun 3
mina 0.05
jun 7.25
stdout
mina 2 12.55
jun 2 10.25
TOTAL 4 22.80
main.py
Error List00F8 ↓ · ⇧F8 ↑
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
Each language signals the end of input differently. Python for line in sys.stdin, Java readLine() returns null, C# Console.ReadLine() returns null, C fgets returns NULL, C++ getline is false, and JS/TS read everything with readFileSync(0) and split it into lines. In Craykon, Console.ReadLine() returning null means the end. A blank line ("") is not the end of input; stopping there loses the records after it. When splitting, JS line.split(" ") makes an empty piece "" where there are two spaces, and Number("") is 0 with no error, so it is silently wrong. Use split(/\s+/) after trim(). Python split(), C# Split((char[])null, RemoveEmptyEntries), C++ >>, C sscanf and Craykon Split() treat any run of whitespace as one separator. For two decimals use Python f"{x:.2f}", JS/TS x.toFixed(2), C/C++ printf("%.2f"). Without a format you get 12.5 or 0.30000000000000004 (0.1 + 0.2). Java String.format and C# ToString("F2") follow the machine's locale, so a German locale prints 12,50; pass Locale.ROOT and CultureInfo.InvariantCulture. Summing into a C float keeps only about 7 significant digits, so totals near 100 million come out wrong; use double. Craykon writes Str.Fixed(total, 2), and the Keys of a Dict() keep insertion order for the name order.
Pythonmain.py · 19 lines
import systotals = {} # 이름 → [건수, 합계]. dict는 처음 넣은 차례를 지킨다all_count, all_sum = 0, 0.0for line in sys.stdin: # 입력이 끝날 때까지 line = line.strip() if not line: # 빈 줄은 건너뛴다(입력 끝이 아님) continue name, amount = line.split() amount = float(amount) if name not in totals: totals[name] = [0, 0.0] totals[name][0] += 1 totals[name][1] += amount all_count += 1 all_sum += amountfor name, (count, total) in totals.items(): print(f"{name} {count} {total:.2f}")print(f"TOTAL {all_count} {all_sum:.2f}")
JavaScriptmain.js · 20 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const totals = new Map(); // 이름 → { count, sum }, 처음 넣은 차례let allCount = 0;let allSum = 0;for (const raw of lines) { const line = raw.trim(); if (line === "") continue; // 빈 줄은 건너뛴다 const [name, amount] = line.split(/\s+/); // 빈칸이 여러 개여도 한 번에 const x = Number(amount); if (!totals.has(name)) totals.set(name, { count: 0, sum: 0 }); const t = totals.get(name); t.count++; t.sum += x; allCount++; allSum += x;}const out = [];for (const [name, t] of totals) out.push(`${name} ${t.count} ${t.sum.toFixed(2)}`);out.push(`TOTAL ${allCount} ${allSum.toFixed(2)}`);console.log(out.join("\n"));
TypeScriptmain.ts · 22 lines
import { readFileSync } from "node:fs";interface Tally { count: number; sum: number }const lines: string[] = readFileSync(0, "utf8").split("\n");const totals = new Map<string, Tally>(); // 처음 넣은 차례를 지킨다let allCount = 0;let allSum = 0;for (const raw of lines) { const line: string = raw.trim(); if (line === "") continue; // 빈 줄은 건너뛴다 const [name, amount] = line.split(/\s+/); const x: number = Number(amount); const t: Tally = totals.get(name) ?? { count: 0, sum: 0 }; t.count++; t.sum += x; totals.set(name, t); allCount++; allSum += x;}const out: string[] = [];for (const [name, t] of totals) out.push(`${name} ${t.count} ${t.sum.toFixed(2)}`);out.push(`TOTAL ${allCount} ${allSum.toFixed(2)}`);console.log(out.join("\n"));
JavaMain.java · 33 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.LinkedHashMap;import java.util.Locale;import java.util.Map;public class Main { public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); Map<String, Integer> counts = new LinkedHashMap<>(); // 처음 넣은 차례를 지킨다 Map<String, Double> sums = new LinkedHashMap<>(); int allCount = 0; double allSum = 0; String line; while ((line = in.readLine()) != null) { // null이면 입력 끝 line = line.trim(); if (line.isEmpty()) continue; String[] p = line.split("\\s+"); double x = Double.parseDouble(p[1]); counts.merge(p[0], 1, Integer::sum); sums.merge(p[0], x, Double::sum); allCount++; allSum += x; } StringBuilder out = new StringBuilder(); // Locale.ROOT: 소수점이 쉼표인 지역 설정에서도 12.50으로 for (String name : counts.keySet()) out.append(String.format(Locale.ROOT, "%s %d %.2f%n", name, counts.get(name), sums.get(name))); out.append(String.format(Locale.ROOT, "TOTAL %d %.2f%n", allCount, allSum)); System.out.print(out); }}
C#Main.cs · 40 lines
using System;using System.Collections.Generic;using System.Globalization;using System.Text;class Program{ static void Main() { var inv = CultureInfo.InvariantCulture; // 소수점이 늘 '.' var names = new List<string>(); // Dictionary는 차례를 약속하지 않아서 따로 둔다 var counts = new Dictionary<string, int>(); var sums = new Dictionary<string, double>(); int allCount = 0; double allSum = 0; string line; while ((line = Console.ReadLine()) != null) { line = line.Trim(); if (line.Length == 0) continue; string[] p = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); double x = double.Parse(p[1], inv); if (!counts.ContainsKey(p[0])) { names.Add(p[0]); counts[p[0]] = 0; sums[p[0]] = 0; } counts[p[0]]++; sums[p[0]] += x; allCount++; allSum += x; } var sb = new StringBuilder(); foreach (string name in names) sb.Append(name).Append(' ').Append(counts[name]).Append(' ').Append(sums[name].ToString("F2", inv)).Append('\n'); sb.Append("TOTAL ").Append(allCount).Append(' ').Append(allSum.ToString("F2", inv)).Append('\n'); Console.Write(sb); }}
C++main.cpp · 39 lines
#include <cstdio>#include <iostream>#include <sstream>#include <string>#include <unordered_map>#include <vector>int main() { std::vector<std::string> names; // 처음 나온 차례 std::unordered_map<std::string, int> at; // 이름 → names의 자리 std::vector<int> counts; std::vector<double> sums; int allCount = 0; double allSum = 0; std::string line; while (std::getline(std::cin, line)) { // 실패하면 입력 끝 std::istringstream ss(line); // >>는 앞뒤·사이 빈칸을 모두 건너뛴다 std::string name; double x; if (!(ss >> name >> x)) continue; // 빈 줄 auto it = at.find(name); int i; if (it == at.end()) { i = (int)names.size(); at[name] = i; names.push_back(name); counts.push_back(0); sums.push_back(0); } else { i = it->second; } counts[i]++; sums[i] += x; allCount++; allSum += x; } for (std::size_t i = 0; i < names.size(); i++) std::printf("%s %d %.2f\n", names[i].c_str(), counts[i], sums[i]); std::printf("TOTAL %d %.2f\n", allCount, allSum);}
Cmain.c · 29 lines
#include <stdio.h>#include <string.h>#define MAXN 1000static char names[MAXN][13];static int counts[MAXN];static double sums[MAXN]; /* float는 유효 숫자가 7자리뿐이라 합이 커지면 틀린다 */static int k = 0;int main(void) { char line[256], name[16]; double x; int all_count = 0; double all_sum = 0; while (fgets(line, sizeof line, stdin)) { /* NULL이면 입력 끝 */ if (sscanf(line, "%12s %lf", name, &x) != 2) continue; /* 빈 줄 */ int i = 0; while (i < k && strcmp(names[i], name) != 0) i++; if (i == k) strcpy(names[k++], name); counts[i]++; sums[i] += x; all_count++; all_sum += x; } for (int i = 0; i < k; i++) printf("%s %d %.2f\n", names[i], counts[i], sums[i]); printf("TOTAL %d %.2f\n", all_count, all_sum); return 0;}
Craykonmain.cray · 30 lines
counts = Dict();sums = Dict();allCount = 0;allSum = 0;line = Console.ReadLine();while (line != null){ line = line.Trim(); // 빈 줄은 건너뛴다(입력 끝은 빈값) if (line != "") { p = line.Split(); x = p[1].ToNumber(); if (!counts.Contains(p[0])) { counts[p[0]] = 0; sums[p[0]] = 0; } counts[p[0]] += 1; sums[p[0]] += x; allCount += 1; allSum += x; } line = Console.ReadLine();}foreach (name in counts.Keys){ Console.WriteLine(name + " " + counts[name] + " " + Str.Fixed(sums[name], 2));}Console.WriteLine("TOTAL " + allCount + " " + Str.Fixed(allSum, 2));