Skip to content

← Ownership I: Moves, Copy, Clone, Drop step 8 of 20

Easy Primitives

Ownership through function calls

Pair up labels with weights and summarise each pair, using three helpers you are not allowed to change.

pub fn summarise(labels: Vec<String>, weights: Vec<i64>) -> Vec<String>

Why by-value parameters matter

Up to now moves have been two-line puzzles. This is where they start shaping program structure. A by-value parameter is a contract: “hand me this value; you will not have it afterwards.” When several such contracts want the same value, you have to decide, at every call site, which one gets the original and what the others get instead.

The three fixed helpers:

fn consume_label(l: String) -> usize   // char count
fn score(n: i64) -> i64                // n * 2 + 1
fn tag(l: String, n: i64) -> String    // "{l}={n}"

All three must appear in your solution. That is not a stylistic request: if you compute a char count inline instead of calling consume_label, the helper becomes unused and rustc’s dead_code lint — promoted to an error by -D warnings — fails your submission.

The output

Return a Vec<String> whose first element is a header

"{labels.len()}x{weights.len()}"

followed by one element per pair, zipping the two inputs and stopping at the shorter one. Each pair element is

"{tag(label, score(weight))}|{consume_label(label)}|{weight}"

So labels = ["ada"], weights = [3] gives ["1x1", "ada=7|3|3"].

Read that pair format carefully. Each label must reach both tag and consume_label, and each weight must reach both score and the raw output field. Those two situations look identical and are not.

::: question The starter fails with two E0382s. One of them is fixed by cloning and one is fixed by moving a line. Which is which — and why is the weight not a problem at all? The header is a reordering fix. The starter computes labels.len() and weights.len() after the loop, but the loop consumed both vectors with into_iter() / zip. Nothing needs duplicating; the measurement just has to happen while the vectors still exist. Move one line above the loop and it is gone. Cloning both vectors would also compile, and would allocate a copy of every string in the input to compute two integers.

The label is a clone. tag and consume_label both take String by value and neither hands it back, so under these fixed signatures one of them gets label.clone() and there is no way around it. That is a legitimate clone — you can say precisely what it buys and precisely what it costs — and this track allows it. In Track 3, &str parameters make it unnecessary, which is exactly the pain that motivates references.

The weight needs nothing. i64 is Copy. score(w) duplicates eight bytes and leaves w completely valid, so it appears twice in the same expression without ceremony. This is the same contrast as the last problem, seen from the caller’s side rather than the type’s: whether a by-value parameter is a sacrifice depends entirely on whether the type is Copy. :::

A note on signatures you will write yourself

needless_pass_by_value is a clippy lint that flags exactly the parameters this track is built on — it suggests &str where you wrote String, &[T] where you wrote Vec<T>. It is a pedantic lint, off by default, and for good reason: a deliberately consuming API is not a mistake. String::into_bytes, Vec::into_iter and every builder method you will write later all take self on purpose.

The lint that is on by default and that you should never trip is ptr_arg: taking &String or &Vec<T> as a parameter. Those are strictly worse than &str and &[T] — they accept fewer callers and give you nothing extra. None of this problem’s fixed helpers do that; when you start designing your own signatures in Track 3, that is the rule to remember.

Watch out

consume_label counts chars, not bytes, so multi-byte text does not inflate the count. And one weight in the hidden cases is chosen so that score(w) lands exactly on i64::MAX — the harness compiles with -O, which turns off overflow checks, so one step further would wrap silently instead of panicking.

Remember the grade is compile + tests + clippy -D warnings.

Loading visualization…