MediumError handlingNot started

Sum the valid readings

A river gauge sends one reading per line over a flaky radio link, so some lines arrive garbled: 12x, --, a blank line, or a number too large for a 64-bit integer. Read all lines until input ends. A line is valid when, after trimming spaces, it parses as an i64; every other line is invalid. Print one line sum=<S> valid=<V> invalid=<I> with the sum of the valid readings and the two counts. The program must never panic on bad input.

Input

Zero or more lines until end of input. There may be no lines at all.

Output

One line: sum=<S> valid=<V> invalid=<I>.

Example 1

Input

12
-4
12x

30

Output

sum=38 valid=3 invalid=2

12, -4 and 30 are valid (sum 38); 12x and the blank line are not.

Example 2

Input

9223372036854775807
-1
9223372036854775808

Output

sum=9223372036854775806 valid=2 invalid=1

The last line is one more than the largest i64, so parsing fails and it counts as invalid instead of crashing the program.

Constraints

  • 0 <= number of lines <= 10000
  • The sum of the valid readings fits in an i64

Hints

Hint 1 of 3

line.trim().parse::<i64>() gives a Result: Ok(value) for a number, Err(_) for anything else, including an empty string.

Hint 2 of 3

Match on the Result and update sum and valid in the Ok arm, invalid in the Err arm; never call unwrap() here.

Hint 3 of 3

The for line in stdin.lock().lines() loop simply runs zero times on empty input, so the counters start at zero and the final println! handles that case by itself.

Solution

Show a reference solution and explanation
 Rust · reference solution
use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut sum: i64 = 0;
    let mut valid = 0;
    let mut invalid = 0;
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        match line.trim().parse::<i64>() {
            Ok(value) => {
                sum += value;
                valid += 1;
            }
            Err(_) => invalid += 1,
        }
    }
    println!("sum={} valid={} invalid={}", sum, valid, invalid);
}

Why it works

parse returns Result<i64, ParseIntError> precisely so that bad text is a value you can inspect rather than a crash. Matching on it turns the two outcomes into the two counters; unwrap() would be the wrong tool because a garbled line is expected, not exceptional. Trimming first matters: lines() strips the newline but not other spaces, and " 8 " should count as 8. Overflowing text such as 9223372036854775808 is rejected by parse with a PosOverflow error kind, so the same Err arm covers it without any special case. sum is an i64 because readings can be negative and large.

Your program
use std::io::{self, BufRead};

fn main() {
    let stdin = io::stdin();
    let mut sum: i64 = 0;
    let mut valid = 0;
    let mut invalid = 0;
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        // try to parse the trimmed line as an i64 and match on the Result
    }
    println!("sum={} valid={} invalid={}", sum, valid, invalid);
}
Run is not available for Rust in the browser yet. Write your program here, then download it and run it locally with rustc 1.94 against the examples above. The reference solution below was verified the same way.

Tests: 6 cases including the examples. Passing every test marks the exercise solved in this browser.

How this page was checked. Every program on it was run with rustc 1.94 at build time by the publishing checks, and the output shown is what it printed. Running Rust inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with rustc 1.94 locally.