{ }codelper
reading numbersreading until EOF64-bit integersP0392

Reading measurement rows mixed with commas and comments

A lab instrument wrote one measurement run per line, and the log is given until the input ends. Neither the number of lines nor the number of values on a line is given in advance. On a line, everything from the first '#' to the end of the line is a comment, and numbers written inside a comment are not counted. The rest of the line holds zero or more integers. Between two integers there are one or more spaces, tabs and commas mixed together, and these characters may also appear at the very start and end of the line. Repeated commas do not mean that a value sits between them. An integer is decimal, may start with a sign '+' or '-', and may begin with zeros. So 007 is 7, -012 is −12 and +5 is 5. Only a line with at least one integer is a record. An empty line, a line of only spaces, tabs and commas, and a line with only a comment are not records and are skipped; more records may follow them. For each record, in input order, print on one line the number of integers on that line and their sum, separated by one space. On the last line print the number of records, the total count of integers over all records and the sum of all integers, separated by single spaces. If there is no record at all, print only the line "0 0 0".

Input
The input has 1 to 1,000 lines, and a line has at most 200 characters without its line break.
An integer has 1 to 12 digits after the optional sign and its value is between −100,000,000,000 and 100,000,000,000.
An integer has at most one sign, a sign appears only at the very front of an integer, and nothing stands between the sign and the digits.
Every line, including the last one, ends with a line break.
Outside comments only digits, '+', '-', spaces, tabs and commas appear; comments contain printable ASCII characters
Output
One line "count sum" per record, then a last line "records total-count total-sum".
Numbers are written as plain digits without commas
Example 1 · stdin
# run 7 (2 sensors)
12, 007 +5
  -3,,4 # 99 is ignored

100000000000 100000000000,
,,
08 010
stdout
3 24
2 1
2 200000000000
2 18
4 9 200000000043
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

Since you do not know how many numbers a line holds, you must know where each line ends.
C scanf("%lld"), C++ std::cin >> x and Java Scanner.nextLong() skip spaces and line breaks alike, so they cannot tell where a line ends (and they stop at commas and comments).
So read one line first (Python for line in sys.stdin, Java readLine(), C# Console.ReadLine(), C fgets, C++ getline, Craykon Console.ReadLine(), JS/TS read everything and split("\n")) and then cut that line into pieces.
The cutting tools differ in how they treat empty pieces.
Python split() and Craykon Split() without an argument skip whole runs of spaces and tabs, so it is enough to turn commas into spaces first (replace(",", " "), Replace(",", " ")).
C strtok(line, " \t,\r\n") and Java StringTokenizer(data, " \t,") make no empty pieces either, and C# needs Split(seps, StringSplitOptions.RemoveEmptyEntries) spelled out.
C++ turns commas into spaces and reads with >> from a std::istringstream.
Trap one: JS/TS split(/[ \t,]+/) leaves an empty string "" next to a separator at the very start or end of the line, and Number("") is 0 without any error.
Without filtering, the third line of the example gives 4 1 instead of 2 1 and the empty line prints 1 0.
Filter with filter((t) => t !== "").
Trap two: Java split("[ \t,]+") drops only trailing empty strings and keeps the leading one, so on the third line of the example Long.parseLong("") stops with NumberFormatException.
Trap three: giving base 0 as in C strtoll(tok, NULL, 0) reads numbers that start with 0 as octal.
On the last line of the example 010 becomes 8 and 08 stops at 0, so 2 18 becomes 2 8.
Pass base 10.
Python int, JS/TS Number, Java Long.parseLong, C# long.Parse, C++ >> and Craykon ToNumber() read 007 and +5 as decimal 7 and 5.
Trap four: searching the whole line for numbers without cutting the comment (Python re.findall) also counts the 7 and 2 on the first line and the 99 on the third.
Trap five: sums exceed about 2.1 billion.
Use C/C++ long long and Java/C# long.
In Java, sum += Long.parseLong(t) with int sum compiles without an error and silently narrows to int, so the sum of the fourth record, 200000000000, becomes -1863462912.
Python has no size limit, and JS/TS/Craykon numbers are exact up to 2^53, which covers the largest total here, 1.5 × 10^15.
Trap six: if lines without numbers are not skipped, 0 0 is printed and the record count grows.
Trap seven: an empty line is not the end of input.
Stopping there loses the last two records of the example.
The end of input is null in Java and C#, NULL from C fgets, false from C++ getline and null in Craykon.

Pythonmain.py · 16 lines
import sys rows = count_all = total = 0out = []for line in sys.stdin:                 # 입력이 끝날 때까지 한 줄씩    data = line.split("#")[0]          # '#'부터는 주석    # 쉼표를 빈칸으로 바꾸면 split()이 빈칸·탭·쉼표 덩이를 한 번에 건너뛴다    nums = [int(t) for t in data.replace(",", " ").split()]    if not nums:                       # 수가 없는 줄은 기록이 아니다        continue    rows += 1    count_all += len(nums)    total += sum(nums)    out.append(f"{len(nums)} {sum(nums)}")out.append(f"{rows} {count_all} {total}")print("\n".join(out))
JavaScriptmain.js · 19 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");let rows = 0;let countAll = 0;let total = 0;const out = [];for (const line of lines) {  const data = line.split("#")[0]; // '#'부터는 주석  // 나눈 뒤 빈 조각 ""을 꼭 걸러 낸다. Number("")는 오류 없이 0이다  const nums = data.split(/[ \t,]+/).filter((t) => t !== "").map(Number);  if (nums.length === 0) continue; // 수가 없는 줄은 기록이 아니다  let sum = 0;  for (const x of nums) sum += x;  rows++;  countAll += nums.length;  total += sum;  out.push(`${nums.length} ${sum}`);}out.push(`${rows} ${countAll} ${total}`);console.log(out.join("\n"));
TypeScriptmain.ts · 20 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");let rows = 0;let countAll = 0;let total = 0;const out: string[] = [];for (const line of lines) {  const data: string = line.split("#")[0]; // '#'부터는 주석  // 나눈 뒤 빈 조각 ""을 꼭 걸러 낸다. Number("")는 오류 없이 0이다  const nums: number[] = data.split(/[ \t,]+/).filter((t) => t !== "").map(Number);  if (nums.length === 0) continue; // 수가 없는 줄은 기록이 아니다  let sum = 0;  for (const x of nums) sum += x;  rows++;  countAll += nums.length;  total += sum;  out.push(`${nums.length} ${sum}`);}out.push(`${rows} ${countAll} ${total}`);console.log(out.join("\n"));
JavaMain.java · 33 lines
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int rows = 0;        int countAll = 0;        long total = 0;        StringBuilder out = new StringBuilder();        String line;        while ((line = in.readLine()) != null) { // 입력이 끝나면 null            int hash = line.indexOf('#');            String data = hash >= 0 ? line.substring(0, hash) : line; // '#'부터는 주석            // StringTokenizer는 구분 글자가 겹치거나 맨 앞에 있어도 빈 조각을 만들지 않는다            StringTokenizer st = new StringTokenizer(data, " \t,");            int count = 0;            long sum = 0;            while (st.hasMoreTokens()) {                sum += Long.parseLong(st.nextToken());                count++;            }            if (count == 0) continue; // 수가 없는 줄은 기록이 아니다            rows++;            countAll += count;            total += sum;            out.append(count).append(' ').append(sum).append('\n');        }        out.append(rows).append(' ').append(countAll).append(' ').append(total).append('\n');        System.out.print(out);    }}
C#Main.cs · 29 lines
using System;using System.Text; class Program{    static void Main()    {        int rows = 0, countAll = 0;        long total = 0;        var sb = new StringBuilder();        char[] seps = { ' ', '\t', ',' };        string line;        while ((line = Console.ReadLine()) != null) // 입력이 끝나면 null        {            string data = line.Split('#')[0]; // '#'부터는 주석            // RemoveEmptyEntries가 없으면 구분 글자가 겹친 곳마다 빈 문자열이 생긴다            string[] parts = data.Split(seps, StringSplitOptions.RemoveEmptyEntries);            if (parts.Length == 0) continue; // 수가 없는 줄은 기록이 아니다            long sum = 0;            foreach (string t in parts) sum += long.Parse(t);            rows++;            countAll += parts.Length;            total += sum;            sb.Append(parts.Length).Append(' ').Append(sum).Append('\n');        }        sb.Append(rows).Append(' ').Append(countAll).Append(' ').Append(total).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 30 lines
#include <algorithm>#include <iostream>#include <sstream>#include <string>using namespace std; int main() {    int rows = 0, countAll = 0;    long long total = 0;    string line;    // cin >> x 는 줄 바꿈도 건너뛰어서 줄의 끝을 알 수 없다. getline으로 한 줄씩 읽는다    while (getline(cin, line)) {        line = line.substr(0, line.find('#')); // '#'부터는 주석(없으면 npos라 줄 전체)        replace(line.begin(), line.end(), ',', ' ');        istringstream in(line);        int count = 0;        long long sum = 0, x;        while (in >> x) { // 빈칸·탭 덩이를 건너뛰며 수를 하나씩 읽는다            sum += x;            count++;        }        if (count == 0) continue; // 수가 없는 줄은 기록이 아니다        rows++;        countAll += count;        total += sum;        cout << count << ' ' << sum << '\n';    }    cout << rows << ' ' << countAll << ' ' << total << '\n';    return 0;}
Cmain.c · 27 lines
#include <stdio.h>#include <stdlib.h>#include <string.h> int main(void) {    char line[256];    int rows = 0, count_all = 0;    long long total = 0;    /* scanf("%lld")는 줄 바꿈도 건너뛰어서 줄의 끝을 알 수 없다. 한 줄씩 읽어서 나눈다 */    while (fgets(line, sizeof line, stdin)) {        char *hash = strchr(line, '#'); /* '#'부터는 주석 */        if (hash) *hash = '\0';        int count = 0;        long long sum = 0;        for (char *tok = strtok(line, " \t,\r\n"); tok; tok = strtok(NULL, " \t,\r\n")) {            sum += strtoll(tok, NULL, 10); /* 꼭 10진법으로: 0을 주면 010을 8진수로 읽는다 */            count++;        }        if (count == 0) continue; /* 수가 없는 줄은 기록이 아니다 */        rows++;        count_all += count;        total += sum;        printf("%d %lld\n", count, sum);    }    printf("%d %d %lld\n", rows, count_all, total);    return 0;}
Craykonmain.cray · 28 lines
rows = 0;countAll = 0;total = 0;while (true){    line = Console.ReadLine();    if (line == null)    {        break;    }    data = line.Split("#")[0]; // '#'부터는 주석    // 쉼표를 빈칸으로 바꾸면 나누기()가 빈칸·탭·쉼표 덩이를 한 번에 건너뛴다    parts = data.Replace(",", " ").Split();    if (parts.Count == 0)    {        continue;    }    sum = 0;    foreach (t in parts)    {        sum += t.ToNumber();    }    rows += 1;    countAll += parts.Count;    total += sum;    Console.WriteLine(parts.Count + " " + sum);}Console.WriteLine(rows + " " + countAll + " " + total);