Add examples for Zig language (#242)

* add zig examples

* improved zig binary search

This commit improves the binary search code in zig. The function has
been made generic and the logic has been cleaned up a bit.
The code has been updated to work with zig versions >= 0.9

* simplify zig selection sort

This commit simplifies the logic of the zig selection sort. It now swaps
in place the elements of the array instead of creating another array.
This avoids allocating heap memory.
The code has also been upgraded to zig version 0.9.1

* make zig recursion examples generic

This commit modifies the zig examples for the recursion chapter to be
generic. It also updates the code to zig version 0.9.1

* update chapter 4 examples

This commit updates the zig examples in chapter 4. In particular
examples have been made generic where possible. The code has been
updated to zig version 0.9.1

* update zig hash table examples

This commit updates the examples for the chapter 5 about hash tables.
Some improvements have been done (using a set instead of a map). The
code has been updated to zig version 0.9.1

* update breadth first search zig example

This commit updates the zig example for the breadth first search
algorithm. It adds a unit test and updates the code to zig version 0.9.1

* revamp zig dijkstra example

* add comments in dijkstra zig

* fix zig greedy algorithm

* add test for zig dijkstra

* add test for zig greedy algorithm

* improve zig chapter 9 exercise

This commit improves the zig exercise to comput the longest common
subsequence.
A main function has been added and the allocator code has been extracted
from the `subsequence` function.
This commit is contained in:
Paolo Grisoli
2022-11-18 23:36:32 +01:00
committed by GitHub
parent f03841e79a
commit 5d9ae511d5
22 changed files with 1165 additions and 1 deletions

View File

@@ -0,0 +1,38 @@
const print = @import("std").debug.print;
const expect = @import("std").testing.expect;
pub fn main() void {
var arr = [_]i32{ 1, 2, 3, 4 };
print("{}\n", .{sum(i32, &arr)});
}
fn sum(comptime T: type, arr: []T) T {
var total: T = 0;
for (arr) |x| {
total += x;
}
return total;
}
test "sum" {
var arr0 = [_]i32{ 1, 2, 3, 4 };
var arr1 = [_]i32{};
var tests = [_]struct {
arr: []i32,
exp: i32,
}{
.{
.arr = &arr0,
.exp = 10,
},
.{
.arr = &arr1,
.exp = 0,
},
};
for (tests) |t| {
var n = sum(@TypeOf(t.exp), t.arr);
try expect(n == t.exp);
}
}

View File

@@ -0,0 +1,37 @@
const print = @import("std").debug.print;
const expect = @import("std").testing.expect;
pub fn main() void {
var list = [_]i32{ 1, 2, 3, 4 };
print("{}\n", .{sum(i32, &list)});
}
fn sum(comptime T: type, list: []T) T {
if (list.len == 0) {
return 0;
}
return list[0] + sum(T, list[1..]);
}
test "sum" {
var arr0 = [_]i32{ 1, 2, 3, 4 };
var arr1 = [_]i32{};
var tests = [_]struct {
arr: []i32,
exp: i32,
}{
.{
.arr = &arr0,
.exp = 10,
},
.{
.arr = &arr1,
.exp = 0,
},
};
for (tests) |t| {
var n = sum(@TypeOf(t.exp), t.arr);
try expect(n == t.exp);
}
}

View File

@@ -0,0 +1,40 @@
const print = @import("std").debug.print;
const expect = @import("std").testing.expect;
pub fn main() void {
var arr = [_]i32{ 4, 3, 2, 1 };
print("{}\n", .{count(i32, arr[0..])});
}
fn count(comptime T: type, arr: []T) T {
if (arr.len == 0) {
return 0;
} else return 1 + count(T, arr[1..]);
}
test "count" {
var arr0 = [_]i32{};
var arr1 = [_]i32{42};
var arr2 = [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var tests = [_]struct {
arr: []i32,
exp: i32,
}{
.{
.arr = &arr0,
.exp = 0,
},
.{
.arr = &arr1,
.exp = 1,
},
.{
.arr = &arr2,
.exp = 9,
},
};
for (tests) |t| {
try expect(count(@TypeOf(t.exp), t.arr) == t.exp);
}
}

View File

@@ -0,0 +1,47 @@
const print = @import("std").debug.print;
const expect = @import("std").testing.expect;
pub fn main() void {
print("{}\n", .{findMax(i32, &[_]i32{ 1, 2, 3, 4 })});
}
fn findMax(comptime T: type, arr: []const T) T {
switch (arr.len) {
0 => return 0,
1 => return arr[0],
else => {
const x = findMax(T, arr[1..]);
if (arr[0] > x) {
return arr[0];
} else return x;
},
}
}
test "find max" {
const tests = [_]struct {
arr: []const i32,
exp: i32,
}{
.{
.arr = &[_]i32{ 1, 2, 3, 4 },
.exp = 4,
},
.{
.arr = &[_]i32{ 8, 42, 3, 1 },
.exp = 42,
},
.{
.arr = &[_]i32{42},
.exp = 42,
},
.{
.arr = &[_]i32{},
.exp = 0,
},
};
for (tests) |t| {
try expect(findMax(@TypeOf(t.exp), t.arr) == t.exp);
}
}

View File

@@ -0,0 +1,79 @@
const std = @import("std");
const print = std.debug.print;
const expect = std.testing.expect;
const heap = std.heap;
const mem = std.mem;
pub fn main() !void {
var gpa = heap.GeneralPurposeAllocator(.{}){};
var arena = heap.ArenaAllocator.init(gpa.allocator());
defer arena.deinit();
var s = [_]u8{ 5, 3, 6, 2, 10 };
print("{d}\n", .{try quicksort(u8, arena.allocator(), &s)});
}
fn quicksort(comptime T: type, allocator: mem.Allocator, s: []const T) anyerror![]const T {
// base case, arrays with 0 or 1 element are already "sorted"
if (s.len < 2) {
return s;
}
var lower = std.ArrayList(T).init(allocator);
var higher = std.ArrayList(T).init(allocator);
const pivot = s[0];
for (s[1..]) |item| {
if (item <= pivot) {
try lower.append(item);
} else {
try higher.append(item);
}
}
var low = try quicksort(T, allocator, lower.items);
var high = try quicksort(T, allocator, higher.items);
var res = std.ArrayList(T).init(allocator);
try res.appendSlice(low);
try res.append(pivot);
try res.appendSlice(high);
return res.items;
}
test "quicksort" {
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
}
const tests = [_]struct {
s: []const u8,
exp: []const u8,
}{
.{
.s = &[_]u8{},
.exp = &[_]u8{},
},
.{
.s = &[_]u8{42},
.exp = &[_]u8{42},
},
.{
.s = &[_]u8{ 3, 2, 1 },
.exp = &[_]u8{ 1, 2, 3 },
},
};
for (tests) |t| {
var res = try quicksort(u8, arena.allocator(), t.s);
try expect(res.len == t.exp.len);
for (res) |e, i|
try expect(e == t.exp[i]);
}
}

View File

@@ -0,0 +1,86 @@
const std = @import("std");
const print = std.debug.print;
const expect = std.testing.expect;
const heap = std.heap;
const mem = std.mem;
pub const io_mode = .evented;
pub const Error = error{OutOfMemory};
pub fn main() !void {
var gpa = heap.GeneralPurposeAllocator(.{}){};
var arena = heap.ArenaAllocator.init(gpa.allocator());
defer arena.deinit();
var s = [_]u8{ 5, 3, 6, 2, 10 };
print("{d}\n", .{try quicksort(arena.allocator(), &s)});
}
// NOTE: this async version cannot be generic because allocating a frame for a
// generic function is not trivial.
fn quicksort(allocator: mem.Allocator, s: []const u8) Error![]const u8 {
if (s.len < 2) {
return s;
}
var lower = std.ArrayList(u8).init(allocator);
var higher = std.ArrayList(u8).init(allocator);
const pivot = s[0];
for (s[1..]) |item| {
if (item <= pivot) {
try lower.append(item);
} else {
try higher.append(item);
}
}
const low_frame = try allocator.create(@Frame(quicksort));
low_frame.* = async quicksort(allocator, lower.items);
var high = try quicksort(allocator, higher.items);
var low = try await low_frame;
var res = std.ArrayList(u8).init(allocator);
try res.appendSlice(low);
try res.append(pivot);
try res.appendSlice(high);
return res.items;
}
test "quicksort" {
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
}
const tests = [_]struct {
s: []const u8,
exp: []const u8,
}{
.{
.s = &[_]u8{},
.exp = &[_]u8{},
},
.{
.s = &[_]u8{42},
.exp = &[_]u8{42},
},
.{
.s = &[_]u8{ 3, 2, 1 },
.exp = &[_]u8{ 1, 2, 3 },
},
};
for (tests) |t| {
var res = try quicksort(arena.allocator(), t.s);
try expect(res.len == t.exp.len);
for (res) |e, i|
try expect(e == t.exp[i]);
}
}