← run

rs-04-group-consecutive

0.000
0/1 tests· algorithms
Challenge · difficulty 4/5
# Group consecutive runs

Implement the library file **`src/lib.rs`** exposing:

```rust
pub fn group_consecutive<T: PartialEq + Clone>(items: &[T]) -> Vec<(T, usize)>
```

Collapse runs of consecutive equal elements (a form of run-length encoding).
Walk `items` left to right; each maximal run of equal adjacent elements becomes a
single `(value, run_length)` pair in the output. Pairs appear in the same order
the runs occur, and `run_length` is always at least `1`.

The function is **generic**: it must work for any element type `T` that is
`PartialEq + Clone` (e.g. `i32`, `char`, `String`). Use `PartialEq` to compare
adjacent elements and `Clone` to copy the representative value into the result.
Do not require `T: Copy`, `T: Hash`, or `T: Ord`.

Behavior:

- Empty input returns an empty `Vec`.
- Only **consecutive** equal elements are merged; equal elements separated by a
  different element form separate runs.

Examples:

- `group_consecutive(&[1, 1, 2, 3, 3, 3])` → `vec![(1, 2), (2, 1), (3, 3)]`
- `group_consecutive(&['a', 'a', 'b', 'a'])` → `vec![('a', 2), ('b', 1), ('a', 1)]`
- `group_consecutive::<i32>(&[])` → `vec![]`
- `group_consecutive(&[1, 2, 3])` → `vec![(1, 1), (2, 1), (3, 1)]`
- `group_consecutive(&[7, 7, 7])` → `vec![(7, 3)]`

Use only the standard library. Tests live in `tests/` and call it as
`challenge::group_consecutive`.
tests/group.rs
use challenge::group_consecutive;

#[test]
fn ints_with_runs() {
    assert_eq!(
        group_consecutive(&[1, 1, 2, 3, 3, 3]),
        vec![(1, 2), (2, 1), (3, 3)]
    );
}

#[test]
fn chars_prove_generic() {
    assert_eq!(
        group_consecutive(&['a', 'a', 'b', 'a']),
        vec![('a', 2), ('b', 1), ('a', 1)]
    );
}

#[test]
fn works_for_owned_strings() {
    let v = vec!["x".to_string(), "x".to_string(), "y".to_string()];
    assert_eq!(
        group_consecutive(&v),
        vec![("x".to_string(), 2), ("y".to_string(), 1)]
    );
}

#[test]
fn empty_input() {
    let out = group_consecutive::<i32>(&[]);
    assert_eq!(out, Vec::<(i32, usize)>::new());
}

#[test]
fn all_distinct() {
    assert_eq!(
        group_consecutive(&[1, 2, 3]),
        vec![(1, 1), (2, 1), (3, 1)]
    );
}

#[test]
fn all_same() {
    assert_eq!(group_consecutive(&[7, 7, 7]), vec![(7, 3)]);
}

#[test]
fn single_element() {
    assert_eq!(group_consecutive(&[42]), vec![(42, 1)]);
}
System prompt
You are an expert programmer. Solve the task exactly as specified. Output your solution as fenced code blocks using the required file name(s) and the exact function/type signatures requested. Prefer correctness; do not include prose outside code unless asked.
Proposed solution
```rust
pub fn group_consecutive<T: PartialEq + Clone>(items: &[T]) -> Vec<(T, usize)> {
    let mut result = Vec::new();
    
    if items.is_empty() {
        return result;
    }

    let mut current_value = items[0].clone();
    let mut current_count = 1;

    for &item in &items[1..] {
        if item == current_value {
            current_count += 1;
        } else {
            result.push((current_value, current_count));
            current_value = item.clone();
            current_count = 1;
        }
    }

    // Push the last run
    result.push((current_value, current_count));
    
    result
}
```

Errors (stderr)

error[E0507]: cannot move out of a shared reference
  --> src/lib.rs:11:18
   |
11 |     for &item in &items[1..] {
   |          ----    ^^^^^^^^^^^
   |          |
   |          data moved here because `item` has type `T`, which does not implement the `Copy` trait
   |
help: consider removing the borrow
   |
11 -     for &item in &items[1..] {
11 +     for item in &items[1..] {
   |

For more information about this error, try `rustc --explain E0507`.
error: could not compile `challenge` (lib) due to 1 previous error
error: could not compile `challenge` (lib test) due to 1 previous error
Self-repair attempts
[
  {
    "total": 1,
    "answer": "```rust\npub fn group_consecutive<T: PartialEq + Clone>(items: &[T]) -> Vec<(T, usize)> {\n    let mut result = Vec::new();\n    \n    if items.is_empty() {\n        return result;\n    }\n\n    let mut current_value = items[0].clone();\n    let mut current_count = 1;\n\n    for &item in &items[1..] {\n        if item == current_value {\n            current_count += 1;\n        } else {\n            result.push((current_value, current_count));\n            current_value = item.clone();\n            current_count = 1;\n        }\n    }\n\n    // Push the last run\n    result.push((current_value, current_count));\n    \n    result\n}\n```",
    "passed": 0,
    "test_error": "error[E0507]: cannot move out of a shared reference\n  --> src/lib.rs:11:18\n   |\n11 |     for &item in &items[1..] {\n   |          ----    ^^^^^^^^^^^\n   |          |\n   |          data moved here because `item` has type `T`, which does not implement the `Copy` trait\n   |\nhelp: consider removing the borrow\n   |\n11 -     for &item in &items[1..] {\n11 +     for item in &items[1..] {\n   |\n\nFor more information about this error, try `rustc --explain E0507`.\nerror: could not compile `challenge` (lib) due to 1 previous error\nerror: could not compile `challenge` (lib test) due to 1 previous error"
  },
  {
    "total": 7,
    "answer": "```rust\npub fn group_consecutive<T: PartialEq + Clone>(items: &[T]) -> Vec<(T, usize)> {\n    let mut result = Vec::new();\n    \n    if items.is_empty() {\n        return result;\n    }\n\n    let mut current_value = items[0].clone();\n    let mut current_count = 1;\n\n    for item in &items[1..] {\n        if *item == current_value {\n            current_count += 1;\n        } else {\n            result.push((current_value, current_count));\n            current_value = item.clone();\n            current_count = 1;\n        }\n    }\n\n    // Push the last run\n    result.push((current_value, current_count));\n    \n    result\n}\n```",
    "passed": 7,
    "test_error": ""
  }
]