RosettaCodeData/Task/Move-to-front-algorithm/Zig/move-to-front-algorithm.zig

79 lines
2.1 KiB
Zig

const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
const examples = [_][]const u8{ "broood", "bananaaa", "hiphophiphop" };
for (examples) |example| {
const encoded = try encode(allocator, example);
defer allocator.free(encoded);
const decoded = try decode(allocator, encoded);
defer allocator.free(decoded);
std.debug.print("{s} encodes to {any} decodes to {s}\n", .{ example, encoded, decoded });
}
}
fn getSymbols(allocator: std.mem.Allocator) ![]u8 {
var symbols = std.ArrayList(u8).init(allocator);
errdefer symbols.deinit();
var c: u8 = 'a';
while (c <= 'z') : (c += 1) {
try symbols.append(c);
}
return symbols.toOwnedSlice();
}
fn encode(allocator: std.mem.Allocator, input: []const u8) ![]usize {
var output = std.ArrayList(usize).init(allocator);
errdefer output.deinit();
var symbols = try getSymbols(allocator);
defer allocator.free(symbols);
for (input) |byte| {
// Find position of the byte in symbols
var position: usize = 0;
for (symbols, 0..) |symbol, i| {
if (symbol == byte) {
position = i;
break;
}
}
// Remove the byte at the position
const char = symbols[position];
std.mem.copyForwards(u8, symbols[1..position + 1], symbols[0..position]);
symbols[0] = char;
try output.append(position);
}
return output.toOwnedSlice();
}
fn decode(allocator: std.mem.Allocator, input: []const usize) ![]u8 {
var output = std.ArrayList(u8).init(allocator);
errdefer output.deinit();
var symbols = try getSymbols(allocator);
defer allocator.free(symbols);
for (input) |position| {
try output.append(symbols[position]);
// Remove the byte at the position
const char = symbols[position];
std.mem.copyForwards(u8, symbols[1..position + 1], symbols[0..position]);
symbols[0] = char;
}
return output.toOwnedSlice();
}