Update examples for Zig (#287)

* update zig in chapters 1-6

* fix zig dijkstras algo

* fix zig greedy algo

* fix longest_common_subsequence in zig

* cleanup

* test: use testing allocator
This commit is contained in:
Paolo Grisoli
2024-12-07 14:29:48 +01:00
committed by GitHub
parent 177581a9a4
commit 8a13efde83
13 changed files with 357 additions and 260 deletions

View File

@@ -7,43 +7,45 @@ pub fn main() !void {
var arena = heap.ArenaAllocator.init(gpa.allocator());
defer arena.deinit();
var states_needed_array = [_][]const u8{ "mt", "wa", "or", "id", "nv", "ut", "ca", "az" };
var states_needed = std.BufSet.init(arena.allocator());
const ally = arena.allocator();
const states_needed_array = [_][]const u8{ "mt", "wa", "or", "id", "nv", "ut", "ca", "az" };
var states_needed = std.BufSet.init(ally);
for (states_needed_array) |sn| {
try states_needed.insert(sn);
}
var stations = std.StringHashMap(*std.BufSet).init(arena.allocator());
var stations = std.StringHashMap(*std.BufSet).init(ally);
var kone = std.BufSet.init(arena.allocator());
try kone.insert("id");
try kone.insert("nv");
try kone.insert("ut");
try stations.put("kone", &kone);
var k_one = std.BufSet.init(ally);
try k_one.insert("id");
try k_one.insert("nv");
try k_one.insert("ut");
var ktwo = std.BufSet.init(arena.allocator());
try ktwo.insert("wa");
try ktwo.insert("id");
try ktwo.insert("mt");
try stations.put("ktwo", &ktwo);
var k_two = std.BufSet.init(ally);
try k_two.insert("wa");
try k_two.insert("id");
try k_two.insert("mt");
var kthree = std.BufSet.init(arena.allocator());
try kthree.insert("or");
try kthree.insert("nv");
try kthree.insert("ca");
try stations.put("kthree", &kthree);
var k_three = std.BufSet.init(ally);
try k_three.insert("or");
try k_three.insert("nv");
try k_three.insert("ca");
var kfour = std.BufSet.init(arena.allocator());
try kfour.insert("nv");
try kfour.insert("ut");
try stations.put("kfour", &kfour);
var k_four = std.BufSet.init(ally);
try k_four.insert("nv");
try k_four.insert("ut");
var kfive = std.BufSet.init(arena.allocator());
try kfive.insert("ca");
try kfive.insert("az");
try stations.put("kfive", &kfive);
var k_five = std.BufSet.init(ally);
try k_five.insert("ca");
try k_five.insert("az");
var stations_covering = try setCovering(arena.allocator(), &stations, &states_needed);
try stations.put("kone", &k_one);
try stations.put("ktwo", &k_two);
try stations.put("kthree", &k_three);
try stations.put("kfour", &k_four);
try stations.put("kfive", &k_five);
const stations_covering = try setCovering(ally, &stations, &states_needed);
for (stations_covering) |sc| {
std.debug.print("{s}\n", .{sc});
@@ -59,8 +61,8 @@ fn setCovering(allocator: mem.Allocator, stations: *std.StringHashMap(*std.BufSe
var it = stations.iterator();
while (it.next()) |station| {
var covered = &std.ArrayList([]const u8).init(allocator);
try intersect(states_needed, station.value_ptr.*, covered);
var covered = std.ArrayList([]const u8).init(allocator);
try intersect(states_needed, station.value_ptr.*, &covered);
if (covered.items.len > states_covered.len) {
best_station = station.key_ptr.*;
states_covered = covered.items;
@@ -80,10 +82,61 @@ fn setCovering(allocator: mem.Allocator, stations: *std.StringHashMap(*std.BufSe
return final_array.toOwnedSlice();
}
test "setCovering" {
var arena = heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit();
const ally = arena.allocator();
const states_needed_array = [_][]const u8{ "mt", "wa", "or", "id", "nv", "ut", "ca", "az" };
var states_needed = std.BufSet.init(ally);
for (states_needed_array) |sn| {
try states_needed.insert(sn);
}
var stations = std.StringHashMap(*std.BufSet).init(ally);
var kone = std.BufSet.init(ally);
try kone.insert("id");
try kone.insert("nv");
try kone.insert("ut");
try stations.put("kone", &kone);
var ktwo = std.BufSet.init(ally);
try ktwo.insert("wa");
try ktwo.insert("id");
try ktwo.insert("mt");
try stations.put("ktwo", &ktwo);
var kthree = std.BufSet.init(ally);
try kthree.insert("or");
try kthree.insert("nv");
try kthree.insert("ca");
try stations.put("kthree", &kthree);
var kfour = std.BufSet.init(ally);
try kfour.insert("nv");
try kfour.insert("ut");
try stations.put("kfour", &kfour);
var kfive = std.BufSet.init(ally);
try kfive.insert("ca");
try kfive.insert("az");
try stations.put("kfive", &kfive);
const stations_covering = try setCovering(ally, &stations, &states_needed);
// The order of the keys in the hashmap affects the final result.
// StringHashMap always produces the same order and we can assert over it.
const expectedStations = &[_][]const u8{ "kfour", "ktwo", "kthree", "kfive" };
for (stations_covering, 0..) |sc, i| {
try std.testing.expectEqualStrings(expectedStations[i], sc);
}
}
fn intersect(left: *std.BufSet, right: *std.BufSet, intersection: *std.ArrayList([]const u8)) !void {
var l_it = left.iterator();
var r_it = right.iterator();
while (l_it.next()) |l| {
var r_it = right.iterator();
while (r_it.next()) |r| {
if (std.mem.eql(u8, l.*, r.*)) {
try intersection.append(l.*);
@@ -92,6 +145,54 @@ fn intersect(left: *std.BufSet, right: *std.BufSet, intersection: *std.ArrayList
}
}
test "intersect" {
var arena = heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit();
const ally = arena.allocator();
var left = std.BufSet.init(ally);
try left.insert("banana");
try left.insert("mango");
try left.insert("papaya");
var right = std.BufSet.init(ally);
try right.insert("banana");
try right.insert("mango");
try right.insert("avocado");
{
// partial intersection
const expected = &[2][]const u8{ "banana", "mango" };
var actual = std.ArrayList([]const u8).init(ally);
try intersect(&left, &right, &actual);
for (actual.items, expected) |a, e| {
try std.testing.expectEqualStrings(e, a);
}
}
{
// full intersection
const expected = &[3][]const u8{ "banana", "mango", "papaya" };
var actual = std.ArrayList([]const u8).init(ally);
try intersect(&left, &left, &actual);
for (actual.items, expected) |a, e| {
try std.testing.expectEqualStrings(e, a);
}
}
{
// no intersection
var empty = std.BufSet.init(ally);
var actual = std.ArrayList([]const u8).init(ally);
try intersect(&left, &empty, &actual);
try std.testing.expect(actual.items.len == 0);
}
}
fn difference(lessening: *std.BufSet, subtracting: [][]const u8) void {
var less_it = lessening.iterator();
@@ -104,55 +205,52 @@ fn difference(lessening: *std.BufSet, subtracting: [][]const u8) void {
}
}
test "setCovering" {
var gpa = heap.GeneralPurposeAllocator(.{}){};
var arena = heap.ArenaAllocator.init(gpa.allocator());
defer {
arena.deinit();
const leaked = gpa.deinit();
if (leaked) std.testing.expect(false) catch @panic("TEST FAIL"); //fail test; can't try in defer as defer is executed after we return
test "difference" {
var arena = heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit();
const ally = arena.allocator();
{
// partial diff
var less = std.BufSet.init(ally);
try less.insert("banana");
try less.insert("mango");
try less.insert("papaya");
var sub = [_][]const u8{ "banana", "mango" };
difference(&less, &sub);
try std.testing.expect(less.count() == 1);
try std.testing.expect(less.contains("papaya"));
}
{
// full diff
var less = std.BufSet.init(ally);
try less.insert("banana");
try less.insert("mango");
try less.insert("papaya");
var states_needed_array = [_][]const u8{ "mt", "wa", "or", "id", "nv", "ut", "ca", "az" };
var states_needed = std.BufSet.init(arena.allocator());
for (states_needed_array) |sn| {
try states_needed.insert(sn);
var sub = [_][]const u8{ "avocado", "kiwi", "ananas" };
difference(&less, &sub);
try std.testing.expect(less.count() == 3);
try std.testing.expect(less.contains("banana"));
try std.testing.expect(less.contains("mango"));
try std.testing.expect(less.contains("papaya"));
}
{
// no diff
var less = std.BufSet.init(ally);
try less.insert("banana");
try less.insert("mango");
try less.insert("papaya");
var stations = std.StringHashMap(*std.BufSet).init(arena.allocator());
var sub = [_][]const u8{ "mango", "papaya", "banana" };
var kone = std.BufSet.init(arena.allocator());
try kone.insert("id");
try kone.insert("nv");
try kone.insert("ut");
try stations.put("kone", &kone);
difference(&less, &sub);
var ktwo = std.BufSet.init(arena.allocator());
try ktwo.insert("wa");
try ktwo.insert("id");
try ktwo.insert("mt");
try stations.put("ktwo", &ktwo);
var kthree = std.BufSet.init(arena.allocator());
try kthree.insert("or");
try kthree.insert("nv");
try kthree.insert("ca");
try stations.put("kthree", &kthree);
var kfour = std.BufSet.init(arena.allocator());
try kfour.insert("nv");
try kfour.insert("ut");
try stations.put("kfour", &kfour);
var kfive = std.BufSet.init(arena.allocator());
try kfive.insert("ca");
try kfive.insert("az");
try stations.put("kfive", &kfive);
var stations_covering = try setCovering(arena.allocator(), &stations, &states_needed);
var expectedStations = &[_][]const u8{ "kone", "ktwo", "kfive", "kthree" };
for (stations_covering) |sc, i| {
try std.testing.expectEqualStrings(expectedStations[i], sc);
try std.testing.expect(less.count() == 0);
}
}