rs-04-group-consecutive
0.000
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": ""
}
]