How to resolve the algorithm Run-length encoding step by step in the Zig programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Run-length encoding step by step in the Zig programming language

Table of Contents

Problem Statement

Given a string containing uppercase characters (A-Z), compress repeated 'runs' of the same character by storing the length of that run, and provide a function to reverse the compression. The output can be anything, as long as you can recreate the input with it.

Note: the encoding step in the above example is the same as a step of the Look-and-say sequence.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Run-length encoding step by step in the Zig programming language

Source code in the zig programming language

const std = @import("std");

fn Run(comptime T: type) type {
    return struct {
        value: T,
        length: usize,
    };
}

fn encode(
    comptime T: type,
    input: []const T,
    allocator: std.mem.Allocator,
) ![]Run(T) {
    var runs = std.ArrayList(Run(T)).init(allocator);
    defer runs.deinit();

    var previous: ?T = null;
    var length: usize = 0;

    for (input) |current| {
        if (previous == current) {
            length += 1;
        } else if (previous) |value| {
            try runs.append(.{
                .value = value,
                .length = length,
            });
            previous = current;
            length = 1;
        } else {
            previous = current;
            length += 1;
        }
    }

    if (previous) |value| {
        try runs.append(.{
            .value = value,
            .length = length,
        });
    }

    return runs.toOwnedSlice();
}

test encode {
    const input =
        "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW";

    const expected = [_]Run(u8){
        .{ .length = 12, .value = 'W' },
        .{ .length = 1, .value = 'B' },
        .{ .length = 12, .value = 'W' },
        .{ .length = 3, .value = 'B' },
        .{ .length = 24, .value = 'W' },
        .{ .length = 1, .value = 'B' },
        .{ .length = 14, .value = 'W' },
    };

    const allocator = std.testing.allocator;
    const actual = try encode(u8, input, allocator);
    defer allocator.free(actual);

    try std.testing.expectEqual(expected.len, actual.len);
    for (expected, actual) |e, a| {
        try std.testing.expectEqual(e.length, a.length);
        try std.testing.expectEqual(e.value, a.value);
    }
}

fn decode(
    comptime T: type,
    runs: []const Run(T),
    allocator: std.mem.Allocator,
) ![]T {
    var values = std.ArrayList(T).init(allocator);
    defer values.deinit();
    for (runs) |r|
        try values.appendNTimes(r.value, r.length);
    return values.toOwnedSlice();
}

test decode {
    const runs = [_]Run(u8){
        .{ .length = 12, .value = 'W' },
        .{ .length = 1, .value = 'B' },
        .{ .length = 12, .value = 'W' },
        .{ .length = 3, .value = 'B' },
        .{ .length = 24, .value = 'W' },
        .{ .length = 1, .value = 'B' },
        .{ .length = 14, .value = 'W' },
    };

    const allocator = std.testing.allocator;
    const decoded = try decode(u8, &runs, allocator);
    defer allocator.free(decoded);

    try std.testing.expectEqualStrings(
        "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW",
        decoded,
    );
}

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.debug.assert(gpa.deinit() == .ok);

    const allocator = gpa.allocator();
    var input = std.ArrayList(u8).init(allocator);
    defer input.deinit();

    const stdout = std.io.getStdOut().writer();
    const stdin = std.io.getStdIn().reader();
    try stdout.print("Input: ", .{});
    try stdin.streamUntilDelimiter(input.writer(), '\n', null);

    const runs = try encode(u8, input.items, allocator);
    defer allocator.free(runs);

    try stdout.print("Encoded:\n", .{});
    for (runs) |r|
        try stdout.print("  {}\n", .{r});

    const decoded = try decode(u8, runs, allocator);
    defer allocator.free(decoded);

    try stdout.print("Decoded: {s}\n", .{decoded});
}

  

You may also check:How to resolve the algorithm Proper divisors step by step in the Perl programming language
You may also check:How to resolve the algorithm Inverted index step by step in the OCaml programming language
You may also check:How to resolve the algorithm Flatten a list step by step in the Ring programming language
You may also check:How to resolve the algorithm Fairshare between two and more step by step in the Ring programming language
You may also check:How to resolve the algorithm Flatten a list step by step in the Icon and Unicon programming language