MediumOwnership and borrowingNot started

Longest word in a headline

A newspaper's layout tool needs the longest word of every headline to decide on the column width. Complete longest, which takes a slice of words borrowed from the headline and returns one of those words without copying it into a new String. For each input line print the longest word and its length in characters as <word> (<length>); when several words share the greatest length, print the one that appears first. Words are separated by one or more spaces.

Input

One headline per line until end of input; each headline has at least one word, and words are separated by spaces.

Output

One line per headline: <word> (<length>).

Example 1

Input

storm delays harbour ferries

Output

harbour (7)

harbour has 7 letters; every other word is shorter.

Example 2

Input

one two six ten
council   approves  new    cycle lane

Output

one (3)
approves (8)

In the first headline every word has 3 letters, so the first word wins. The extra spaces in the second headline are not a problem for split_whitespace.

Constraints

  • 1 <= number of headlines <= 100
  • Each headline has 1-200 characters and at least one word

Hints

Hint 1 of 3

Keep track of the best word so far, starting with words[0], and replace it only when a strictly longer word appears.

Hint 2 of 3

The return type &'a str says the result borrows from the same place the words do, so returning an element of the slice is allowed.

Hint 3 of 3

Compare lengths with chars().count() (or len() for ASCII); use > rather than >= so ties keep the earlier word.

Solution

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

fn longest<'a>(words: &[&'a str]) -> &'a str {
    let mut best = words[0];
    for &w in words {
        if w.chars().count() > best.chars().count() {
            best = w;
        }
    }
    best
}

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let headline = line.unwrap();
        let words: Vec<&str> = headline.split_whitespace().collect();
        if words.is_empty() {
            continue;
        }
        let word = longest(&words);
        println!("{} ({})", word, word.chars().count());
    }
}

Why it works

The signature fn longest<'a>(words: &[&'a str]) -> &'a str is the heart of the exercise. The parameter contains two borrows: the slice itself and the string pieces inside it. The result is one of the pieces, so it must be tied to the pieces' lifetime 'a, not to the shorter-lived slice; without the annotation the compiler cannot tell which of the two you mean and refuses to guess. Because the function returns a borrow, no text is copied: the headline is split once with split_whitespace, the Vec<&str> holds views into it, and the answer is another view. Using strict > in the comparison is what makes ties resolve to the earliest word.

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

// The returned &str borrows from the words, not from the slice itself,
// so the signature needs a named lifetime.
fn longest<'a>(words: &[&'a str]) -> &'a str {
    // return the longest word; on a tie keep the earliest one
    words[0]
}

fn main() {
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let headline = line.unwrap();
        let words: Vec<&str> = headline.split_whitespace().collect();
        if words.is_empty() {
            continue;
        }
        let word = longest(&words);
        println!("{} ({})", word, word.chars().count());
    }
}
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: 5 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.