โ† run

rs-01-rle

1.000
3/3 testsยท basic
Challenge ยท difficulty 1/5
# Run-length encoding

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

```rust
pub fn run_length_encode(input: &str) -> String
```

Encode consecutive runs of the same character as `<char><count>`. A single character still
gets a count of `1`.

- `run_length_encode("aaabbc")` โ†’ `"a3b2c1"`
- `run_length_encode("")` โ†’ `""`
- `run_length_encode("abc")` โ†’ `"a1b1c1"`

Tests live in `tests/` and call it as `challenge::run_length_encode`.
tests/rle.rs
use challenge::run_length_encode;

#[test]
fn basic_runs() {
    assert_eq!(run_length_encode("aaabbc"), "a3b2c1");
}

#[test]
fn empty() {
    assert_eq!(run_length_encode(""), "");
}

#[test]
fn all_singles() {
    assert_eq!(run_length_encode("abc"), "a1b1c1");
}
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


To solve this problem, we need to implement a function that performs run-length encoding on a given string. Run-length encoding is a simple form of data compression where consecutive runs of the same character are replaced by the character followed by the count of its consecutive occurrences.

### Approach
1. **Check for Empty Input**: If the input string is empty, return an empty string immediately.
2. **Initialize Variables**: Set up variables to keep track of the current character and its count. Start with the first character of the string and a count of 1.
3. **Iterate Through Characters**: Loop through each character starting from the second one. For each character:
   - If it matches the current character, increment the count.
   - If it does not match, append the current character and its count to the result string, then update the current character and reset the count to 1.
4. **Final Append**: After the loop, append the last tracked character and its count to the result string to ensure the final run is included.

This approach ensures that each character and its consecutive count are processed efficiently, resulting in the desired run-length encoded string.

### Solution Code

```rust
pub fn run_length_encode(input: &str) -> String {
    if input.is_empty() {
        return String::new();
    }

    let mut result = String::new();
    let mut current_char = input.chars().next().unwrap();
    let mut count = 1;

    for char in input.chars().skip(1) {
        if char == current_char {
            count += 1;
        } else {
            result.push_str(&format!("{}{}", current_char, count));
            current_char = char;
            count = 1;
        }
    }

    result.push_str(&format!("{}{}", current_char, count));
    result
}
```

### Explanation
- **Empty Input Handling**: The function first checks if the input string is empty and returns an empty string if true.
- **Initialization**: The first character of the input string is set as the initial `current_char`, and the count is initialized to 1.
- **Loop Through Characters**: Starting from the second character, each character is compared to `current_char`. If it matches, the count is incremented. If it does not match, the current run is appended to the result string, and the tracking variables are updated.
- **Final Append**: After the loop, the last tracked run is appended to ensure all characters are included in the result.

This method efficiently processes each character exactly once, resulting in a time complexity of O(n), where n is the length of the input string. This ensures optimal performance even for longer strings.

Test output (stdout)


running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


running 3 tests
...
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Reasoning (chain-of-thought)

Okay, I need to implement the run-length encoding function in Rust. Let's see, the function is called run_length_encode and it takes a string slice input and returns a String. So the signature is pub fn run_length_encode(input: &str) -> String.

Run-length encoding works by taking consecutive runs of the same character and replacing them with the character followed by the count. For example, "aaabbc" becomes "a3b2c1". Even single characters get a count of 1, like "abc" becomes "a1b1c1".

Hmm, how do I approach this? I think I'll need to iterate through each character in the input string, keep track of the current character and the count of consecutive occurrences.

Let me outline the steps:

1. If the input string is empty, return an empty string. That's the base case.

2. Initialize variables:
   - current_char as the first character of the string.
   - count starts at 1.

3. Iterate over each character starting from the second one:
   a. If the character is the same as current_char, increment count.
   b. If it's different, append the current run to the result string, then set current_char to this new character and reset count to 1.

4. After the loop ends, don't forget to append the last run.

Wait, but how do I handle the iteration? Maybe using a for loop with indices would be better, so I can access each character by index.

Let me think about the code structure.

Start by checking if the input is empty. If so, return empty.

Else, create a mutable String to build the result.

Then, loop through each character, keeping track of the current run.

Wait, maybe using an iterator with a state would be more efficient. Alternatively, I can loop through each character, compare with the previous one, and accumulate counts.

Let me think about the code:

Initialize result as an empty String.

If input is empty, return result.

Set current_char to the first character, count to 1.

Then, loop from the second character to the end:

for char in input.chars().skip(1) {
   if char == current_char {
       count += 1;
   } else {
       // append current run to result
       result.push_str(format!("{}{}", current_char, count).as_str());
       current_char = char;
       count = 1;
   }
}

After the loop, append the last run.

Wait, but in Rust, strings are immutable, so I need to build the result efficiently. Using a String and appending each part is the way to go.

Wait, but in the code, when I process each character, I have to compare it to the current_char. So for each character after the first, I check if it's the same as current_char.

Wait, but what about the first character? Let's see:

For input "aaabbc", the first character is 'a', count is 1. Then next 'a's increase count to 3. Then 'b's, etc.

So the code outline is:

pub fn run_length_encode(input: &str) -> String {
    if input.is_empty() {
        return String::new();
    }

    let mut result = String::new();
    let mut current_char = input.chars().next().unwrap();
    let mut count = 1;

    for char in input.chars().skip(1) {
        if char == current_char {
            count += 1;
        } else {
            result.push_str(&format!("{}{}", current_char, count));
            current_char = char;
            count = 1;
        }
    }

    // Add the last run
    result.push_str(&format!("{}{}", current_char, count));

    result
}

Wait, but what if the input is a single character? Like "a". Then the loop doesn't run, and the last run is added, which is correct.

Testing the examples:

Example 1: "aaabbc" โ†’ a3b2c1.

Let's see:

current_char starts as 'a', count 1.

Next chars: 'a', 'a', 'b', 'b', 'c'.

Loop:

Second 'a' โ†’ count 2.

Third 'a' โ†’ count 3.

Then 'b' is different. So append 'a3' to result. current_char becomes 'b', count 1.

Next 'b' โ†’ count 2.

Then 'c' is different. Append 'b2'. current_char 'c', count 1.

Loop ends. Append 'c1'.

Result is 'a3b2c1' โ†’ correct.

Another example: "abc" โ†’ a1b1c1.

Loop:

After 'a', next is 'b' โ†’ different. Append 'a1', current_char 'b', count 1.

Next is 'c' โ†’ different. Append 'b1', current_char 'c', count 1.

Loop ends. Append 'c1'. So result is 'a1b1c1' โ†’ correct.

Another test case: empty string returns empty.

What about a string with all same characters, like "aaaa"? Should return "a4".

Yes, the code should handle that.

Wait, but what about when the input is empty? The initial check returns empty.

What about when the input has only one character? It appends it correctly.

So the code seems to handle all cases.

But wait, in the code, when input is not empty, we unwrap the first character. What if input is empty? The initial check returns, so the unwrap is safe.

Yes, because if input is empty, the function returns early.

So the code should be correct.

I think this should work. Now, I'll write the code as per the function signature.