From e7dcf0b6ef10944271fea4b677cb2722c632dabd Mon Sep 17 00:00:00 2001 From: bsubei <6508762+bsubei@users.noreply.github.com> Date: Sun, 21 Jul 2024 12:23:30 -0400 Subject: [PATCH 001/118] fix build files broken by latest 0.14.0-dev changes to Build.Step.MakeOptions --- build.zig | 10 +++++----- test/tests.zig | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build.zig b/build.zig index b40f8bd..8c7ab7b 100644 --- a/build.zig +++ b/build.zig @@ -274,7 +274,7 @@ const ZiglingStep = struct { return self; } - fn make(step: *Step, prog_node: std.Progress.Node) !void { + fn make(step: *Step, options: Step.MakeOptions) !void { // NOTE: Using exit code 2 will prevent the Zig compiler to print the message: // "error: the following build command failed with exit code 1:..." const self: *ZiglingStep = @alignCast(@fieldParentPtr("step", step)); @@ -285,7 +285,7 @@ const ZiglingStep = struct { return; } - const exe_path = self.compile(prog_node) catch { + const exe_path = self.compile(options.progress_node) catch { self.printErrors(); if (self.exercise.hint) |hint| @@ -295,7 +295,7 @@ const ZiglingStep = struct { std.process.exit(2); }; - self.run(exe_path.?, prog_node) catch { + self.run(exe_path.?, options.progress_node) catch { self.printErrors(); if (self.exercise.hint) |hint| @@ -436,7 +436,7 @@ const ZiglingStep = struct { zig_args.append("--listen=-") catch @panic("OOM"); - return try self.step.evalZigProcess(zig_args.items, prog_node); + return try self.step.evalZigProcess(zig_args.items, prog_node, false); } fn help(self: *ZiglingStep) void { @@ -525,7 +525,7 @@ const PrintStep = struct { return self; } - fn make(step: *Step, _: std.Progress.Node) !void { + fn make(step: *Step, _: Step.MakeOptions) !void { const self: *PrintStep = @alignCast(@fieldParentPtr("step", step)); print("{s}", .{self.message}); } diff --git a/test/tests.zig b/test/tests.zig index 126a1cd..9fed107 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -150,7 +150,7 @@ const CheckNamedStep = struct { return self; } - fn make(step: *Step, _: std.Progress.Node) !void { + fn make(step: *Step, _: Step.MakeOptions) !void { const b = step.owner; const self: *CheckNamedStep = @alignCast(@fieldParentPtr("step", step)); const ex = self.exercise; @@ -202,7 +202,7 @@ const CheckStep = struct { return self; } - fn make(step: *Step, _: std.Progress.Node) !void { + fn make(step: *Step, _: Step.MakeOptions) !void { const b = step.owner; const self: *CheckStep = @alignCast(@fieldParentPtr("step", step)); const exercises = self.exercises; @@ -325,7 +325,7 @@ const FailStep = struct { return self; } - fn make(step: *Step, _: std.Progress.Node) !void { + fn make(step: *Step, _: Step.MakeOptions) !void { const b = step.owner; const self: *FailStep = @alignCast(@fieldParentPtr("step", step)); @@ -368,7 +368,7 @@ const HealStep = struct { return self; } - fn make(step: *Step, _: std.Progress.Node) !void { + fn make(step: *Step, _: Step.MakeOptions) !void { const b = step.owner; const self: *HealStep = @alignCast(@fieldParentPtr("step", step)); From 4cc1158fbcc5380cf7d7b38cd63f04733701e7fa Mon Sep 17 00:00:00 2001 From: bsubei <6508762+bsubei@users.noreply.github.com> Date: Sun, 21 Jul 2024 12:26:03 -0400 Subject: [PATCH 002/118] fix tests build file broken by addRemoveDirTree now requiring LazyPath --- test/tests.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/tests.zig b/test/tests.zig index 9fed107..5f64f8e 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -50,7 +50,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step { case_step.dependOn(&verify.step); } - const cleanup = b.addRemoveDirTree(tmp_path); + const cleanup = b.addRemoveDirTree(.{ .src_path = .{ .owner = b, .sub_path = tmp_path } }); cleanup.step.dependOn(case_step); step.dependOn(&cleanup.step); @@ -82,7 +82,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step { const verify = CheckStep.create(b, exercises, stderr); verify.step.dependOn(&cmd.step); - const cleanup = b.addRemoveDirTree(tmp_path); + const cleanup = b.addRemoveDirTree(.{ .src_path = .{ .owner = b, .sub_path = tmp_path } }); cleanup.step.dependOn(&verify.step); step.dependOn(&cleanup.step); From b26e3b2ac488e609896f166d3c48297960e7f598 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 4 Aug 2024 14:19:05 +0200 Subject: [PATCH 003/118] Fixed error message through a TAB in the comment, see https://github.com/ziglang/zig/issues/20928 --- exercises/103_tokenization.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/103_tokenization.zig b/exercises/103_tokenization.zig index eded880..6f71177 100644 --- a/exercises/103_tokenization.zig +++ b/exercises/103_tokenization.zig @@ -119,9 +119,9 @@ // after all we need some practice. Suppose we want to count the words // of this little poem: // -// My name is Ozymandias, King of Kings; -// Look on my Works, ye Mighty, and despair! -// by Percy Bysshe Shelley +// My name is Ozymandias, King of Kings; +// Look on my Works, ye Mighty, and despair! +// by Percy Bysshe Shelley // // const std = @import("std"); From 1ba74488e4a07663f6986af8aeefa32071dac192 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 4 Aug 2024 15:05:11 +0200 Subject: [PATCH 004/118] Changed needed zig version. --- README.md | 3 ++- build.zig | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 776bafb..4336743 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.42 +Version-0.14.0-dev.839 +* *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) * *2024-05-29* zig 0.13.0-dev.339 - rework std.Progress - see [#20059](https://github.com/ziglang/zig/pull/20059) * *2024-03-21* zig 0.12.0-dev.3518 - change to @fieldParentPtr - see [#19470](https://github.com/ziglang/zig/pull/19470) diff --git a/build.zig b/build.zig index 8c7ab7b..e3fa9ac 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.42"; + const required_zig = "0.14.0-dev.839"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From 70b0522cb2ab7d886bfd01ec96503b0e21e043a5 Mon Sep 17 00:00:00 2001 From: Michael Cooper Date: Thu, 8 Aug 2024 08:23:14 -0700 Subject: [PATCH 005/118] Add build parameter to start at a specific exercise --- README.md | 8 +++++++- build.zig | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4336743..5385cff 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ reading these. ## A Note About Versions **Hint:** To check out Ziglings for a stable release of Zig, you can use -the appropriate tag. +the appropriate tag. The Zig language is under very active development. In order to be current, Ziglings tracks **development** builds of the Zig @@ -128,6 +128,12 @@ It can be handy to check just a single exercise: zig build -Dn=19 ``` +Or run all exercises, starting from a specific one: + +``` +zig build -Ds=27 +``` + Or let Ziglings pick an exercise for you: ``` diff --git a/build.zig b/build.zig index e3fa9ac..abc98b9 100644 --- a/build.zig +++ b/build.zig @@ -161,6 +161,7 @@ pub fn build(b: *Build) !void { const override_healed_path = b.option([]const u8, "healed-path", "Override healed path"); const exno: ?usize = b.option(usize, "n", "Select exercise"); const rand: ?bool = b.option(bool, "random", "Select random exercise"); + const start: ?usize = b.option(usize, "s", "Start at exercise"); const sep = std.fs.path.sep_str; const healed_path = if (override_healed_path) |path| @@ -221,6 +222,26 @@ pub fn build(b: *Build) !void { return; } + if (start) |s| { + if (s == 0 or s > exercises.len - 1) { + print("unknown exercise number: {}\n", .{s}); + std.process.exit(2); + } + const first = exercises[s - 1]; + const ziglings_step = b.step("ziglings", b.fmt("Check ziglings starting with {s}", .{first.main_file})); + b.default_step = ziglings_step; + + var prev_step = &header_step.step; + for (exercises[(s - 1)..]) |ex| { + const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); + verify_stepn.step.dependOn(prev_step); + + prev_step = &verify_stepn.step; + } + ziglings_step.dependOn(prev_step); + return; + } + // Normal build mode: verifies all exercises according to the recommended // order. const ziglings_step = b.step("ziglings", "Check all ziglings"); From 17f9312034aa8a040193dc7c3ec543d02b1d4b4d Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 11 Aug 2024 16:29:14 +0200 Subject: [PATCH 006/118] Clarification in description for ranges in loops. --- exercises/095_for3.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/095_for3.zig b/exercises/095_for3.zig index e4c4662..0d4f42f 100644 --- a/exercises/095_for3.zig +++ b/exercises/095_for3.zig @@ -28,7 +28,7 @@ // 0..10 is a range from 0 to 9 // 1..4 is a range from 1 to 3 // -// At the moment, ranges are only supported in 'for' loops. +// At the moment, ranges in loops are only supported in 'for' loops. // // Perhaps you recall Exercise 13? We were printing a numeric // sequence like so: From 3baf0ae657a80e8a63e96924560a3908b6ea6a9d Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 11 Aug 2024 18:23:48 +0200 Subject: [PATCH 007/118] Simplified de-referencing for clarification --- exercises/046_optionals2.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/046_optionals2.zig b/exercises/046_optionals2.zig index a5436d9..86654f7 100644 --- a/exercises/046_optionals2.zig +++ b/exercises/046_optionals2.zig @@ -48,7 +48,7 @@ pub fn main() void { // If e1 and e2 are valid pointers to elephants, // this function links the elephants so that e1's tail "points" to e2. fn linkElephants(e1: ?*Elephant, e2: ?*Elephant) void { - e1.?.*.tail = e2.?; + e1.?.tail = e2; } // This function visits all elephants once, starting with the From 031e11aa61e59ec4997427010263d21b8a886e79 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 19 Aug 2024 14:04:48 +0200 Subject: [PATCH 008/118] Added license to contributing --- CONTRIBUTING.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bb43f67..8d9d6b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -40,6 +40,7 @@ fit for one reason or another. ## Platforms and Zig Versions + Because it uses the Zig build system, Ziglings should work wherever Zig does. @@ -75,6 +76,15 @@ interface. Specifically: eternal Ziglings contributor glory is yours! +## Licence + +If you submit your contribution to the repository/project, +you agree that your contribution will be licensed under +the license of this repository/this project. +Please note, it does not change your rights to use your own +contribution for any other purpose. + + ## The Secrets If you want to peek at the secrets, take a look at the `patches/` From dab5197027490d4170a47ac105113c0f07d64672 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 22 Aug 2024 18:19:21 +0200 Subject: [PATCH 009/118] Fixes changes in zig build system. --- README.md | 3 ++- build.zig | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5385cff..9216582 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.839 +Version-0.14.0-dev.1248 +* *2024-08-04* zig 0.14.0-dev.1248 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) * *2024-05-29* zig 0.13.0-dev.339 - rework std.Progress - see [#20059](https://github.com/ziglang/zig/pull/20059) diff --git a/build.zig b/build.zig index abc98b9..ceadc8b 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.839"; + const required_zig = "0.14.0-dev.1248"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { @@ -316,7 +316,7 @@ const ZiglingStep = struct { std.process.exit(2); }; - self.run(exe_path.?, options.progress_node) catch { + self.run(exe_path, options.progress_node) catch { self.printErrors(); if (self.exercise.hint) |hint| @@ -426,7 +426,7 @@ const ZiglingStep = struct { print("{s}PASSED{s}\n\n", .{ green_text, reset_text }); } - fn compile(self: *ZiglingStep, prog_node: std.Progress.Node) !?[]const u8 { + fn compile(self: *ZiglingStep, prog_node: std.Progress.Node) ![]const u8 { print("Compiling: {s}\n", .{self.exercise.main_file}); const b = self.step.owner; @@ -457,7 +457,21 @@ const ZiglingStep = struct { zig_args.append("--listen=-") catch @panic("OOM"); - return try self.step.evalZigProcess(zig_args.items, prog_node, false); + // + // NOTE: After many changes in zig build system, we need to create the cache path manually. + // See https://github.com/ziglang/zig/pull/21115 + // Maybe there is a better way (in the future). + const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false); + const exe_name = switch (self.exercise.kind) { + .exe => self.exercise.name(), + .@"test" => "test", + }; + const sep = std.fs.path.sep_str; + const root_path = exe_dir.?.root_dir.path.?; + const sub_path = exe_dir.?.subPathOrDot(); + const exe_path = b.fmt("{s}{s}{s}{s}{s}", .{ root_path, sep, sub_path, sep, exe_name }); + + return exe_path; } fn help(self: *ZiglingStep) void { From 8e35cf79901ffe38b3325412a605fdb6cefbeb8f Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 22 Aug 2024 18:32:36 +0200 Subject: [PATCH 010/118] Insert wrong version number into build file. --- README.md | 4 ++-- build.zig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9216582..417cf88 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.1248 -* *2024-08-04* zig 0.14.0-dev.1248 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) +Version-0.14.0-dev.1224 +* *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) * *2024-05-29* zig 0.13.0-dev.339 - rework std.Progress - see [#20059](https://github.com/ziglang/zig/pull/20059) diff --git a/build.zig b/build.zig index ceadc8b..c488608 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.1248"; + const required_zig = "0.14.0-dev.1224"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From b2f56c7cea6475d5335dd8e8642181817fdc390b Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 2 Sep 2024 19:33:59 +0200 Subject: [PATCH 011/118] Fixes several changes in std.builtin.zig --- README.md | 1 + build.zig | 2 +- exercises/065_builtins2.zig | 8 ++++---- exercises/071_comptime6.zig | 2 +- exercises/076_sentinels.zig | 4 ++-- patches/patches/065_builtins2.patch | 10 +++++----- patches/patches/071_comptime6.patch | 6 +++--- patches/patches/076_sentinels.patch | 4 ++-- patches/patches/082_anonymous_structs3.patch | 6 +++--- 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 417cf88..7b8c8c1 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ that if you update one, you may need to also update the other. ### Version Changes Version-0.14.0-dev.1224 +* *2024-07-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) diff --git a/build.zig b/build.zig index c488608..0ddc23f 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.1224"; + const required_zig = "0.14.0-dev.1409"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index 283aca5..0790db4 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -94,7 +94,7 @@ pub fn main() void { print("He has room in his heart for:", .{}); // A StructFields array - const fields = @typeInfo(Narcissus).Struct.fields; + const fields = @typeInfo(Narcissus).@"struct".fields; // 'fields' is a slice of StructFields. Here's the declaration: // @@ -110,15 +110,15 @@ pub fn main() void { // name will not be printed if the field is of type 'void' // (which is a zero-bit type that takes up no space at all!): if (fields[0].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[0].name}); } if (fields[1].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[1].name}); } if (fields[2].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[2].name}); } // Yuck, look at all that repeated code above! I don't know diff --git a/exercises/071_comptime6.zig b/exercises/071_comptime6.zig index 7723291..5938abc 100644 --- a/exercises/071_comptime6.zig +++ b/exercises/071_comptime6.zig @@ -38,7 +38,7 @@ pub fn main() void { // Please use an 'inline for' to implement the block below // for each field in the slice 'fields'! - const fields = @typeInfo(Narcissus).Struct.fields; + const fields = @typeInfo(Narcissus).@"struct".fields; ??? { if (field.type != void) { diff --git a/exercises/076_sentinels.zig b/exercises/076_sentinels.zig index 357bd95..accb600 100644 --- a/exercises/076_sentinels.zig +++ b/exercises/076_sentinels.zig @@ -78,7 +78,7 @@ fn printSequence(my_seq: anytype) void { // a switch to handle printing the Array or Pointer fields, // depending on which type of my_seq was passed in: switch (my_typeinfo) { - .Array => { + .array => { print("Array:", .{}); // Loop through the items in my_seq. @@ -86,7 +86,7 @@ fn printSequence(my_seq: anytype) void { print("{}", .{s}); } }, - .Pointer => { + .pointer => { // Check this out - it's pretty cool: const my_sentinel = sentinel(@TypeOf(my_seq)); print("Many-item pointer:", .{}); diff --git a/patches/patches/065_builtins2.patch b/patches/patches/065_builtins2.patch index 4b0ccd2..d5da950 100644 --- a/patches/patches/065_builtins2.patch +++ b/patches/patches/065_builtins2.patch @@ -1,5 +1,5 @@ ---- exercises/065_builtins2.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/065_builtins2.zig 2023-10-05 20:04:07.136101712 +0200 +--- exercises/065_builtins2.zig 2024-09-02 19:15:56.569952315 +0200 ++++ answers/065_builtins2.zig 2024-09-02 19:13:44.280600350 +0200 @@ -58,7 +58,7 @@ // Oops! We cannot leave the 'me' and 'myself' fields // undefined. Please set them here: @@ -24,16 +24,16 @@ // (which is a zero-bit type that takes up no space at all!): - if (fields[0].??? != void) { + if (fields[0].type != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[0].name}); } - if (fields[1].??? != void) { + if (fields[1].type != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[1].name}); } - if (fields[2].??? != void) { + if (fields[2].type != void) { - print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name}); + print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[2].name}); } diff --git a/patches/patches/071_comptime6.patch b/patches/patches/071_comptime6.patch index 8731344..98fb6e3 100644 --- a/patches/patches/071_comptime6.patch +++ b/patches/patches/071_comptime6.patch @@ -1,8 +1,8 @@ ---- exercises/071_comptime6.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/071_comptime6.zig 2023-10-05 20:04:07.162768879 +0200 +--- exercises/071_comptime6.zig 2024-09-02 19:21:50.250454978 +0200 ++++ answers/071_comptime6.zig 2024-09-02 19:21:23.553250563 +0200 @@ -40,7 +40,7 @@ - const fields = @typeInfo(Narcissus).Struct.fields; + const fields = @typeInfo(Narcissus).@"struct".fields; - ??? { + inline for (fields) |field| { diff --git a/patches/patches/076_sentinels.patch b/patches/patches/076_sentinels.patch index cbfae31..7abd01e 100644 --- a/patches/patches/076_sentinels.patch +++ b/patches/patches/076_sentinels.patch @@ -1,5 +1,5 @@ ---- exercises/076_sentinels.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/076_sentinels.zig 2023-10-05 20:04:07.186102649 +0200 +--- exercises/076_sentinels.zig 2024-09-02 19:27:04.336781039 +0200 ++++ answers/076_sentinels.zig 2024-09-02 19:26:15.709134934 +0200 @@ -82,7 +82,7 @@ print("Array:", .{}); diff --git a/patches/patches/082_anonymous_structs3.patch b/patches/patches/082_anonymous_structs3.patch index 7beb511..193a65a 100644 --- a/patches/patches/082_anonymous_structs3.patch +++ b/patches/patches/082_anonymous_structs3.patch @@ -1,11 +1,11 @@ ---- exercises/082_anonymous_structs3.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/082_anonymous_structs3.zig 2023-10-05 20:04:07.212769813 +0200 +--- exercises/082_anonymous_structs3.zig 2024-08-04 15:57:16.753494020 +0200 ++++ answers/082_anonymous_structs3.zig 2024-09-02 19:30:00.967005314 +0200 @@ -82,14 +82,14 @@ // @typeInfo(Circle).Struct.fields // // This will be an array of StructFields. - const fields = ???; -+ const fields = @typeInfo(@TypeOf(tuple)).Struct.fields; ++ const fields = @typeInfo(@TypeOf(tuple)).@"struct".fields; // 2. Loop through each field. This must be done at compile // time. From a6759458b0b29fa6f52debb253bea27288a6c272 Mon Sep 17 00:00:00 2001 From: Seeingu Date: Wed, 4 Sep 2024 10:09:21 +0800 Subject: [PATCH 012/118] fixed typo: the date in version changes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b8c8c1..5853d7e 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ that if you update one, you may need to also update the other. ### Version Changes Version-0.14.0-dev.1224 -* *2024-07-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) +* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) From 7f1df869382bcb4dfc7847d72c24cdd915fb579d Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Wed, 4 Sep 2024 20:52:42 +0200 Subject: [PATCH 013/118] Reseted the simplification for de-referencing. --- README.md | 2 +- exercises/046_optionals2.zig | 2 +- patches/patches/046_optionals2.patch | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7b8c8c1..5853d7e 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ that if you update one, you may need to also update the other. ### Version Changes Version-0.14.0-dev.1224 -* *2024-07-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) +* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579) diff --git a/exercises/046_optionals2.zig b/exercises/046_optionals2.zig index 86654f7..a5436d9 100644 --- a/exercises/046_optionals2.zig +++ b/exercises/046_optionals2.zig @@ -48,7 +48,7 @@ pub fn main() void { // If e1 and e2 are valid pointers to elephants, // this function links the elephants so that e1's tail "points" to e2. fn linkElephants(e1: ?*Elephant, e2: ?*Elephant) void { - e1.?.tail = e2; + e1.?.*.tail = e2.?; } // This function visits all elephants once, starting with the diff --git a/patches/patches/046_optionals2.patch b/patches/patches/046_optionals2.patch index 9229f05..1b364a6 100644 --- a/patches/patches/046_optionals2.patch +++ b/patches/patches/046_optionals2.patch @@ -1,5 +1,5 @@ ---- exercises/046_optionals2.zig 2024-06-23 19:43:16 -+++ answers/046_optionals2.zig 2024-06-23 19:42:46 +--- exercises/046_optionals2.zig 2024-09-04 20:51:36.766783971 +0200 ++++ answers/046_optionals2.zig 2024-09-04 20:51:01.389400985 +0200 @@ -22,7 +22,7 @@ const Elephant = struct { From c8b60f2c3006996b3f43b744deb19e42f2ff5ed5 Mon Sep 17 00:00:00 2001 From: chrboesch Date: Sat, 7 Sep 2024 12:53:07 +0000 Subject: [PATCH 014/118] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index bc944dc..56a7408 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021 Dave Gauer +Copyright (c) 2021 Dave Gauer, Chris Boesch Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 26f4785a992493fb06505479cfb37e2c18b1c13e Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sat, 7 Sep 2024 19:21:57 +0200 Subject: [PATCH 015/118] Corrects the description of the new @typeInfo().@"struct".fields --- exercises/082_anonymous_structs3.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/082_anonymous_structs3.zig b/exercises/082_anonymous_structs3.zig index 6760ff3..573d0bb 100644 --- a/exercises/082_anonymous_structs3.zig +++ b/exercises/082_anonymous_structs3.zig @@ -75,11 +75,11 @@ fn printTuple(tuple: anytype) void { // with fields specific to that type. // // The list of a struct type's fields can be found in - // TypeInfo's Struct.fields. + // TypeInfo's @"struct".fields. // // Example: // - // @typeInfo(Circle).Struct.fields + // @typeInfo(Circle).@"struct".fields // // This will be an array of StructFields. const fields = ???; From f28346d0095abfd2cd6ea8dabb944ed0c4a41f46 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sat, 7 Sep 2024 19:36:45 +0200 Subject: [PATCH 016/118] New patch file for 82 --- patches/patches/082_anonymous_structs3.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/patches/082_anonymous_structs3.patch b/patches/patches/082_anonymous_structs3.patch index 193a65a..b918011 100644 --- a/patches/patches/082_anonymous_structs3.patch +++ b/patches/patches/082_anonymous_structs3.patch @@ -1,7 +1,7 @@ ---- exercises/082_anonymous_structs3.zig 2024-08-04 15:57:16.753494020 +0200 -+++ answers/082_anonymous_structs3.zig 2024-09-02 19:30:00.967005314 +0200 +--- exercises/082_anonymous_structs3.zig 2024-09-07 19:13:58.210327580 +0200 ++++ answers/082_anonymous_structs3.zig 2024-09-07 19:21:20.972733477 +0200 @@ -82,14 +82,14 @@ - // @typeInfo(Circle).Struct.fields + // @typeInfo(Circle).@"struct".fields // // This will be an array of StructFields. - const fields = ???; From 827146f6806afc1baa640a284e41999e11b1fab6 Mon Sep 17 00:00:00 2001 From: chrboesch Date: Wed, 11 Sep 2024 17:49:54 +0000 Subject: [PATCH 017/118] Update README.md Added new todo for core lang --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5853d7e..d33754c 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,7 @@ Zig Core Language * [X] Bit manipulation * [X] Working with C * [X] Threading +* [ ] Labeled switch (#21257) Zig Standard Library From 335a78f8f5ef8b86922dc241422acb033e0b3b2a Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Sun, 15 Sep 2024 20:14:49 +0200 Subject: [PATCH 018/118] 108: Add a exercise for a labeled switch --- build.zig | 6 ++++++ exercises/108_labeled_switch.zig | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 exercises/108_labeled_switch.zig diff --git a/build.zig b/build.zig index 0ddc23f..06d6483 100644 --- a/build.zig +++ b/build.zig @@ -1197,6 +1197,12 @@ const exercises = [_]Exercise{ \\Successfully Read 18 bytes: It's zigling time! , }, + .{ + .main_file = "108_labeled_switch.zig", + .output = + \\The pull request has been merged + , + }, .{ .main_file = "999_the_end.zig", .output = diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig new file mode 100644 index 0000000..623e359 --- /dev/null +++ b/exercises/108_labeled_switch.zig @@ -0,0 +1,34 @@ +// +// A labeled switch in zig allows the usage of continue and break +// just like loops, these allow you to create very concise +// Finite State Automata to represent state transitions +// +// foo: switch (state) { +// 1 => continue :foo 2, +// 2 => continue :foo 3, +// 3 => return, +// 4 => {}, +// ... +// } +// +const std = @import("std"); + +const PullRequestState = enum { + Draft, + InReview, + Approved, + Rejected, + Merged, +}; + +pub fn main() void { + // Something is wrong, it seems your Pull Request can never be merged + // try to fix it! + pr: switch (@as(PullRequestState, PullRequestState.Draft)) { + PullRequestState.Draft => continue :pr PullRequestState.InReview, + PullRequestState.InReview => continue :pr PullRequestState.Rejected, + PullRequestState.Approved => continue :pr PullRequestState.Merged, + PullRequestState.Rejected => std.debug.print("The pull request has been rejected", .{}), + PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), + } +} From 580e126266b2ccef8f73c1b5aa49f2983339641b Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Sun, 15 Sep 2024 20:16:57 +0200 Subject: [PATCH 019/118] Add .patch for 108_labeled_switch --- patches/patches/108_labeled_switch.patch | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 patches/patches/108_labeled_switch.patch diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch new file mode 100644 index 0000000..dfb65dd --- /dev/null +++ b/patches/patches/108_labeled_switch.patch @@ -0,0 +1,11 @@ +--- a/exercises/108_labeled_switch.zig ++++ b/exercises/108_labeled_switch.zig +@@ -26,7 +26,7 @@ pub fn main() void { + // try to fix it! + pr: switch (@as(PullRequestState, PullRequestState.Draft)) { + PullRequestState.Draft => continue :pr PullRequestState.InReview, +- PullRequestState.InReview => continue :pr PullRequestState.Rejected, ++ PullRequestState.InReview => continue :pr PullRequestState.Approved, + PullRequestState.Approved => continue :pr PullRequestState.Merged, + PullRequestState.Rejected => std.debug.print("The pull request has been rejected", .{}), + PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), From 798bb403963f15028db7d0325d93ab1af6dde684 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:34:35 +0200 Subject: [PATCH 020/118] update zig version in build and readme --- README.md | 5 +++-- build.zig | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d33754c..6d15f9f 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.1224 +Version-0.14.0-dev.1575 +* *2024-09-16* zig 0.14.0-dev.1575 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) @@ -229,7 +230,7 @@ Zig Core Language * [X] Bit manipulation * [X] Working with C * [X] Threading -* [ ] Labeled switch (#21257) +* [x] Labeled switch Zig Standard Library diff --git a/build.zig b/build.zig index 06d6483..dbd08d5 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.1409"; + const required_zig = "0.14.0-dev.1575"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From db569a1478d11c1014ce9569ad65fc5cea9a09c9 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:38:43 +0200 Subject: [PATCH 021/118] update labeled switch to also have a break statement --- exercises/108_labeled_switch.zig | 16 ++++++++++------ patches/patches/108_labeled_switch.patch | 15 +++++++++++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 623e359..dfc061a 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -6,14 +6,14 @@ // foo: switch (state) { // 1 => continue :foo 2, // 2 => continue :foo 3, -// 3 => return, +// 3 => break :foo, // 4 => {}, // ... // } // const std = @import("std"); -const PullRequestState = enum { +const PullRequestState = enum(u8) { Draft, InReview, Approved, @@ -22,13 +22,17 @@ const PullRequestState = enum { }; pub fn main() void { - // Something is wrong, it seems your Pull Request can never be merged - // try to fix it! + // Oh no, your pull request keeps being rejected, + // how would you fix it? pr: switch (@as(PullRequestState, PullRequestState.Draft)) { PullRequestState.Draft => continue :pr PullRequestState.InReview, PullRequestState.InReview => continue :pr PullRequestState.Rejected, PullRequestState.Approved => continue :pr PullRequestState.Merged, - PullRequestState.Rejected => std.debug.print("The pull request has been rejected", .{}), - PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), + PullRequestState.Rejected => { + std.debug.print("The pull request has been rejected", .{}); + return; + }, + PullRequestState.Merged => break, // Would you know where to break to? } + std.debug.print("The pull request has been merged", .{}); } diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch index dfb65dd..230b8fb 100644 --- a/patches/patches/108_labeled_switch.patch +++ b/patches/patches/108_labeled_switch.patch @@ -1,11 +1,18 @@ --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig -@@ -26,7 +26,7 @@ pub fn main() void { - // try to fix it! +@@ -26,13 +26,13 @@ pub fn main() void { + // how would you fix it? pr: switch (@as(PullRequestState, PullRequestState.Draft)) { PullRequestState.Draft => continue :pr PullRequestState.InReview, - PullRequestState.InReview => continue :pr PullRequestState.Rejected, + PullRequestState.InReview => continue :pr PullRequestState.Approved, PullRequestState.Approved => continue :pr PullRequestState.Merged, - PullRequestState.Rejected => std.debug.print("The pull request has been rejected", .{}), - PullRequestState.Merged => std.debug.print("The pull request has been merged", .{}), + PullRequestState.Rejected => { + std.debug.print("The pull request has been rejected", .{}); + return; + }, +- PullRequestState.Merged => break, // Would you know where to break to? ++ PullRequestState.Merged => break :pr, // Would you know where to break to? + } + std.debug.print("The pull request has been merged", .{}); + } From d9ce18631d160a011a64bbdea19b64a2fd65a523 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:44:36 +0200 Subject: [PATCH 022/118] downgrade zig version to eowyn version It is just 2 days behind so all features are already present for the new labeled switch test --- README.md | 4 ++-- build.zig | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6d15f9f..eb3036a 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.1575 -* *2024-09-16* zig 0.14.0-dev.1575 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) +Version-0.14.0-dev.1573 +* *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) diff --git a/build.zig b/build.zig index dbd08d5..8041e07 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.1575"; + const required_zig = "0.14.0-dev.1573"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From ed1a20d51b4d319a32adb7d1552f7316599c3d60 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:26:33 +0200 Subject: [PATCH 023/118] improve explanantions in labeled switch --- exercises/108_labeled_switch.zig | 59 ++++++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index dfc061a..0748d9d 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -1,15 +1,54 @@ // -// A labeled switch in zig allows the usage of continue and break -// just like loops, these allow you to create very concise -// Finite State Automata to represent state transitions +// You've heard of while loops in exercises 011,012,013 and 014 +// You've also heard of switch expressions in exercises 030 and 31. +// You've also seen how labels can be used in exercise 063. // -// foo: switch (state) { -// 1 => continue :foo 2, -// 2 => continue :foo 3, -// 3 => break :foo, -// 4 => {}, -// ... -// } +// By combining while loops and switch statements with continue and break statements +// one can create very concise State Machines. +// +// One such example would be: +// +// pub fn main() void { +// var op: u8 = 1; +// while (true) { +// switch (op) { +// 1 => { op = 2; continue; }, +// 2 => { op = 3; continue; }, +// 3 => return, +// 4 => {}, +// } +// break; +// } +// std.debug.print("This statement cannot be reached"); +// } +// +// By combining all we've learned so far, we can now proceed with a labeled switch +// +// A labeled switch is some extra syntatic sugar, which comes with all sorts of +// candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367 +// +// Here is the previous excerpt implemented as a labeled switch instead: +// +// pub fn main() void { +// foo: switch (@as(u8, 1)) { +// 1 => continue :foo 2, +// 2 => continue :foo 3, +// 3 => return, +// 4 => {}, +// } +// std.debug.print("This statement cannot be reached"); +// } +// +// The flow of execution on this second case is: +// 1. The switch starts with value '1'; +// 2. The switch evaluates to case '1' which in turn uses the continue statement +// to re-evaluate the labeled switch again, now providing the value '2'; +// 3. In the case '2' we repeat the same pattern as case '1' +// but instead the value to be evaluated is now '3'; +// 4. Finally we get to case '3', where we return from the function as a whole. +// +// Since step 4 or a break stament do not exist in this switch, the debug statement is +// never executed // const std = @import("std"); From f0c2c56087bfd4398b896d3a8304a90cddbb3583 Mon Sep 17 00:00:00 2001 From: Nuno Mendes <98030270+nm-remarkable@users.noreply.github.com> Date: Wed, 18 Sep 2024 23:29:08 +0200 Subject: [PATCH 024/118] update108 .patch due to line change --- patches/patches/108_labeled_switch.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch index 230b8fb..467540c 100644 --- a/patches/patches/108_labeled_switch.patch +++ b/patches/patches/108_labeled_switch.patch @@ -1,6 +1,6 @@ --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig -@@ -26,13 +26,13 @@ pub fn main() void { +@@ -65,13 +65,13 @@ pub fn main() void { // how would you fix it? pr: switch (@as(PullRequestState, PullRequestState.Draft)) { PullRequestState.Draft => continue :pr PullRequestState.InReview, From d1b49f353eaa7358a4041a3090e87f49dc0a4bf6 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 20 Sep 2024 12:10:55 +0200 Subject: [PATCH 025/118] Minor improvements. --- build.zig | 4 +--- exercises/108_labeled_switch.zig | 6 +++--- patches/patches/108_labeled_switch.patch | 12 ++++++------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/build.zig b/build.zig index 8041e07..a1f6029 100644 --- a/build.zig +++ b/build.zig @@ -1199,9 +1199,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "108_labeled_switch.zig", - .output = - \\The pull request has been merged - , + .output = "The pull request has been merged.", }, .{ .main_file = "999_the_end.zig", diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 0748d9d..88cb196 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -63,15 +63,15 @@ const PullRequestState = enum(u8) { pub fn main() void { // Oh no, your pull request keeps being rejected, // how would you fix it? - pr: switch (@as(PullRequestState, PullRequestState.Draft)) { + pr: switch (PullRequestState.Draft) { PullRequestState.Draft => continue :pr PullRequestState.InReview, PullRequestState.InReview => continue :pr PullRequestState.Rejected, PullRequestState.Approved => continue :pr PullRequestState.Merged, PullRequestState.Rejected => { - std.debug.print("The pull request has been rejected", .{}); + std.debug.print("The pull request has been rejected.\n", .{}); return; }, PullRequestState.Merged => break, // Would you know where to break to? } - std.debug.print("The pull request has been merged", .{}); + std.debug.print("The pull request has been merged.\n", .{}); } diff --git a/patches/patches/108_labeled_switch.patch b/patches/patches/108_labeled_switch.patch index 467540c..fa9dd67 100644 --- a/patches/patches/108_labeled_switch.patch +++ b/patches/patches/108_labeled_switch.patch @@ -1,18 +1,18 @@ ---- a/exercises/108_labeled_switch.zig -+++ b/exercises/108_labeled_switch.zig -@@ -65,13 +65,13 @@ pub fn main() void { +--- exercises/108_labeled_switch.zig 2024-09-20 12:09:24.370066539 +0200 ++++ answers/108_labeled_switch.zig 2024-09-20 12:09:06.499711739 +0200 +@@ -65,13 +65,13 @@ // how would you fix it? - pr: switch (@as(PullRequestState, PullRequestState.Draft)) { + pr: switch (PullRequestState.Draft) { PullRequestState.Draft => continue :pr PullRequestState.InReview, - PullRequestState.InReview => continue :pr PullRequestState.Rejected, + PullRequestState.InReview => continue :pr PullRequestState.Approved, PullRequestState.Approved => continue :pr PullRequestState.Merged, PullRequestState.Rejected => { - std.debug.print("The pull request has been rejected", .{}); + std.debug.print("The pull request has been rejected.\n", .{}); return; }, - PullRequestState.Merged => break, // Would you know where to break to? + PullRequestState.Merged => break :pr, // Would you know where to break to? } - std.debug.print("The pull request has been merged", .{}); + std.debug.print("The pull request has been merged.\n", .{}); } From 96df8ba3047f12b54612597a49c8ecb687ec9455 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 20 Sep 2024 12:45:23 +0200 Subject: [PATCH 026/118] Added Dave as initiator of Ziglings. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index eb3036a..2aa52cd 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This project was directly inspired by the brilliant and fun project for the [Rust](https://www.rust-lang.org/) language. Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/) and the Little LISPer/Little Schemer series of books. +Ziglings was initiated by [Dave Gauer](https://ratfactor.com/). ## Intended Audience From 9d1da38d38f2f081c4fb61369a70e07dfe080b82 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 20 Sep 2024 18:48:30 +0200 Subject: [PATCH 027/118] Deleted .devcontainer because ist was a test. --- .devcontainer/devcontainer.json | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index beea353..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,31 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/debian -{ - "name": "Ziglings", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/base:bullseye", - "features": { - "ghcr.io/devcontainers-contrib/features/zig:1": { - "version": "master" - } - }, - "customizations": { - "vscode": { - "extensions": [ - "ziglang.vscode-zig" - ] - } - } - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" -} From 02478759b4f759cd19f0869b5e2ca2aa3e3a8624 Mon Sep 17 00:00:00 2001 From: factormystic Date: Sat, 26 Oct 2024 20:43:47 +0000 Subject: [PATCH 028/118] Rephrase instruction for clarity --- exercises/058_quiz7.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/058_quiz7.zig b/exercises/058_quiz7.zig index cf32fc3..fda83fc 100644 --- a/exercises/058_quiz7.zig +++ b/exercises/058_quiz7.zig @@ -190,7 +190,7 @@ const TripItem = union(enum) { fn printMe(self: TripItem) void { switch (self) { // Oops! The hermit forgot how to capture the union values - // in a switch statement. Please capture both values as + // in a switch statement. Please capture each value as // 'p' so the print statements work! .place => print("{s}", .{p.name}), .path => print("--{}->", .{p.dist}), From 8f49400aa1caa05ed120e9661287aa2e92da00d3 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 28 Oct 2024 09:40:17 +0100 Subject: [PATCH 029/118] Fixed patch from quiz7 after text changes #Please enter the commit message for your changes. Lines starting --- patches/patches/058_quiz7.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/patches/058_quiz7.patch b/patches/patches/058_quiz7.patch index 265b9e3..978fbb1 100644 --- a/patches/patches/058_quiz7.patch +++ b/patches/patches/058_quiz7.patch @@ -1,8 +1,8 @@ ---- exercises/058_quiz7.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/058_quiz7.zig 2023-10-05 20:04:07.106101152 +0200 +--- exercises/058_quiz7.zig 2024-10-28 09:06:49.448505460 +0100 ++++ answers/058_quiz7.zig 2024-10-28 09:35:14.631932322 +0100 @@ -192,8 +192,8 @@ // Oops! The hermit forgot how to capture the union values - // in a switch statement. Please capture both values as + // in a switch statement. Please capture each value as // 'p' so the print statements work! - .place => print("{s}", .{p.name}), - .path => print("--{}->", .{p.dist}), From f629d78268e8003437807eac34e0aa461e081cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Fro=C5=82ow?= Date: Sat, 2 Nov 2024 10:48:50 +0100 Subject: [PATCH 030/118] reuse fields --- exercises/065_builtins2.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index 0790db4..db0ea30 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -110,15 +110,15 @@ pub fn main() void { // name will not be printed if the field is of type 'void' // (which is a zero-bit type that takes up no space at all!): if (fields[0].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[0].name}); + print(" {s}", .{fields.name}); } if (fields[1].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[1].name}); + print(" {s}", .{fields[1].name}); } if (fields[2].??? != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[2].name}); + print(" {s}", .{fields[2].name}); } // Yuck, look at all that repeated code above! I don't know From 286439cddc81fb80fc7b5a8adb17afbcc4623c2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Fro=C5=82ow?= Date: Sat, 2 Nov 2024 14:37:41 +0100 Subject: [PATCH 031/118] zero --- exercises/065_builtins2.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index db0ea30..21a3911 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -111,6 +111,7 @@ pub fn main() void { // (which is a zero-bit type that takes up no space at all!): if (fields[0].??? != void) { print(" {s}", .{fields.name}); + print(" {s}", .{fields[0].name}); } if (fields[1].??? != void) { From 530dcde3d413849dc2fea18eddcfb8cf85a76cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Fro=C5=82ow?= Date: Sat, 2 Nov 2024 14:38:53 +0100 Subject: [PATCH 032/118] patch --- patches/patches/065_builtins2.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/patches/065_builtins2.patch b/patches/patches/065_builtins2.patch index d5da950..d6f0839 100644 --- a/patches/patches/065_builtins2.patch +++ b/patches/patches/065_builtins2.patch @@ -24,16 +24,16 @@ // (which is a zero-bit type that takes up no space at all!): - if (fields[0].??? != void) { + if (fields[0].type != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[0].name}); + print(" {s}", .{fields[0].name}); } - if (fields[1].??? != void) { + if (fields[1].type != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[1].name}); + print(" {s}", .{fields[1].name}); } - if (fields[2].??? != void) { + if (fields[2].type != void) { - print(" {s}", .{@typeInfo(Narcissus).@"struct".fields[2].name}); + print(" {s}", .{fields[2].name}); } From fb018d212c1e6d8efc42740c6b99d38c62e52d92 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sat, 2 Nov 2024 17:03:46 +0100 Subject: [PATCH 033/118] Improved maximumNarcissism --- exercises/065_builtins2.zig | 15 ++++++++------- patches/patches/065_builtins2.patch | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index 21a3911..6b8168c 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -110,7 +110,6 @@ pub fn main() void { // name will not be printed if the field is of type 'void' // (which is a zero-bit type that takes up no space at all!): if (fields[0].??? != void) { - print(" {s}", .{fields.name}); print(" {s}", .{fields[0].name}); } @@ -137,14 +136,16 @@ pub fn main() void { // But a change after Zig 0.10.0 added the source file name to the // type. "Narcissus" became "065_builtins2.Narcissus". // -// To fix this, I've added this function to strip the filename from -// the front of the type name in the dumbest way possible. (It returns -// a slice of the type name starting at character 14 (assuming -// single-byte characters). +// To fix this, we've added this function to strip the filename from +// the front of the type name. (It returns a slice of the type name +// starting at the index + 1 of character ".") // // We'll be seeing @typeName again in Exercise 070. For now, you can // see that it takes a Type and returns a u8 "string". fn maximumNarcissism(myType: anytype) []const u8 { - // Turn '065_builtins2.Narcissus' into 'Narcissus' - return @typeName(myType)[14..]; + const indexOf = @import("std").mem.indexOf; + + // Turn "065_builtins2.Narcissus" into "Narcissus" + const name = @typeName(myType); + return name[indexOf(u8, name, ".").? + 1 ..]; } diff --git a/patches/patches/065_builtins2.patch b/patches/patches/065_builtins2.patch index d6f0839..e5e6410 100644 --- a/patches/patches/065_builtins2.patch +++ b/patches/patches/065_builtins2.patch @@ -1,5 +1,5 @@ ---- exercises/065_builtins2.zig 2024-09-02 19:15:56.569952315 +0200 -+++ answers/065_builtins2.zig 2024-09-02 19:13:44.280600350 +0200 +--- exercises/065_builtins2.zig 2024-11-02 16:58:30.607829441 +0100 ++++ answers/065_builtins2.zig 2024-11-02 16:58:33.821220588 +0100 @@ -58,7 +58,7 @@ // Oops! We cannot leave the 'me' and 'myself' fields // undefined. Please set them here: From c90d6015e3c5405d3ac0c6d225d8a6041035f1b9 Mon Sep 17 00:00:00 2001 From: bgthompson Date: Sun, 3 Nov 2024 11:16:00 +1000 Subject: [PATCH 034/118] created a new exercise about vectors in zig, gave it number 109 --- build.zig | 7 ++ exercises/109_vectors.zig | 149 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 exercises/109_vectors.zig diff --git a/build.zig b/build.zig index a1f6029..e528552 100644 --- a/build.zig +++ b/build.zig @@ -1201,6 +1201,13 @@ const exercises = [_]Exercise{ .main_file = "108_labeled_switch.zig", .output = "The pull request has been merged.", }, + .{ + .main_file = "109_vectors.zig", + .output = + \\Max difference (old fn): 0.014 + \\Max difference (new fn): 0.014 + , + }, .{ .main_file = "999_the_end.zig", .output = diff --git a/exercises/109_vectors.zig b/exercises/109_vectors.zig new file mode 100644 index 0000000..9e4a2a0 --- /dev/null +++ b/exercises/109_vectors.zig @@ -0,0 +1,149 @@ +// So far in Ziglings, we've seen how for loops can be used to +// repeat calculations across an array in several ways. +// +// For loops are generally great for this kind of task, but +// sometimes they don't fully utilize the capabilities of the +// CPU. +// +// Most modern CPUs can execute instructions in which SEVERAL +// calculations are performed WITHIN registers at the SAME TIME. +// These are known as "single instruction, multiple data" (SIMD) +// instructions. SIMD instructions can make code significantly +// more performant. +// +// To see why, imagine we have a program in which we take the +// square root of four (changing) f32 floats. +// +// A simple compiler would take the program and produce machine code +// which calculates each square root sequentially. Most registers on +// modern CPUs have 64 bits, so we could imagine that each float moves +// into a 64-bit register, and the following happens four times: +// +// 32 bits 32 bits +// +-------------------+ +// register | 0 | x | +// +-------------------+ +// +// | +// [SQRT instruction] +// V +// +// +-------------------+ +// | 0 | sqrt(x) | +// +-------------------+ +// +// Notice that half of the register contains blank data to which +// nothing happened. What a waste! What if we were able to use +// that space instead? This is the idea at the core of SIMD. +// +// Most modern CPUs contain specialized registers with at least 128 bits +// for performing SIMD instructions. On a machine with 128-bit SIMD +// registers, a smart compiler would probably NOT issue four sqrt +// instructions as above, but instead pack the floats into a single +// 128-bit register, then execute a single "packed" sqrt +// instruction to do ALL the square root calculations at once. +// +// For example: +// +// +// 32 bits 32 bits 32 bits 32 bits +// +---------------------------------------+ +// register | 4.0 | 9.0 | 25.0 | 49.0 | +// +---------------------------------------+ +// +// | +// [SIMD SQRT instruction] +// V +// +// +---------------------------------------+ +// register | 2.0 | 3.0 | 5.0 | 7.0 | +// +---------------------------------------+ +// +// Pretty cool, right? +// +// Code with SIMD instructions is usually more performant than code +// without SIMD instructions. Zig cares a lot about performance, +// so it has built-in support for SIMD! It has a data structure that +// directly supports SIMD instructions: +// +// +-----------+ +// | Vectors | +// +-----------+ +// +// Operations performed on vectors in Zig will be done in parallel using +// SIMD instructions, whenever possible. +// +// Defining vectors in Zig is straightforwards. No library import is needed. +const v1 = @Vector(3, i32) { 1, 10, 100}; +const v2 = @Vector(3, f32) {2.0, 3.0, 5.0}; + +// Vectors support the same builtin operators as their underlying base types. +const v3 = v1 + v1; // { 2, 20, 200}; +const v4 = v2 * v2; // { 4.0, 9.0, 25.0}; + +// Intrinsics that apply to base types usually extend to vectors. +const v5 : @Vector(3, f32) = @floatFromInt(v3); // { 2.0, 20.0, 200.0} +const v6 = v4 - v5; // { 2.0, -11.0, -175.0} +const v7 = @abs(v6); // { 2.0, 11.0, 175.0} + +// We can make constant vectors, and reduce vectors. +const v8 : @Vector(4, u8) = @splat(2); // { 2, 2, 2, 2} +const v8_sum = @reduce(.Add, v8); // 8 +const v8_min = @reduce(.Min, v8); // 2 + +// Fixed-length arrays can be automatically assigned to vectors (and vice-versa). +const single_digit_primes = [4] i8 {2, 3, 5, 7}; +const prime_vector : @Vector(4, i8) = single_digit_primes; + +// Now let's use vectors to simplify and optimize some code! +// +// Ewa is writing a program in which they frequently want to compare +// two lists of four f32s. Ewa expects the lists to be similar, and +// wants to determine the largest pairwise difference between the lists. +// +// Ewa wrote the following function to figure this out. + +fn calcMaxPairwiseDiffOld( list1 : [4] f32, list2 : [4] f32) f32 { + var max_diff : f32 = 0; + for (list1, list2) |n1, n2| { + const abs_diff = @abs(n1 - n2); + if (abs_diff > max_diff) { + max_diff = abs_diff; + } + } + return max_diff; +} + +// Ewa heard about vectors in Zig, and started writing a new vector +// version of the function, but has got stuck! +// +// Help Ewa finish the vector version! The examples above should help. + +const Vec4 = @Vector(4, f32); +fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { +// const abs_diff_vec = ???; + const abs_diff_vec = @abs(a - b); +// const max_diff = @reduce(???, abs_diff_vec); + const max_diff = @reduce(.Max, abs_diff_vec); + return max_diff; +} + +// Quite the simplification! We could even write the function in one line +// and it would still be readable. +// +// Since the entire function is now expressed in terms of vector operations, +// the Zig compiler will easily be able to compile it down to machine code +// which utilizes the all-powerful SIMD instructions and does a lot of the +// computation in parallel. + +const std = @import("std"); +const print = std.debug.print; + +pub fn main() void { + const l1 = [4] f32 { 3.141, 2.718, 0.577, 1.000}; + const l2 = [4] f32 { 3.154, 2.707, 0.591, 0.993}; + const mpd_old = calcMaxPairwiseDiffOld(l1, l2); + const mpd_new = calcMaxPairwiseDiffNew(l1, l2); + print("Max difference (old fn): {d: >5.3}\n", .{mpd_old}); + print("Max difference (new fn): {d: >5.3}\n", .{mpd_new}); +} From 75e5e534979d95087709b0cccf4fdf64e74d43d3 Mon Sep 17 00:00:00 2001 From: bgthompson Date: Sun, 3 Nov 2024 11:18:18 +1000 Subject: [PATCH 035/118] removed commented solution lines in vectors exercise, added ??? into lines instead --- exercises/109_vectors.zig | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/exercises/109_vectors.zig b/exercises/109_vectors.zig index 9e4a2a0..106937e 100644 --- a/exercises/109_vectors.zig +++ b/exercises/109_vectors.zig @@ -121,10 +121,8 @@ fn calcMaxPairwiseDiffOld( list1 : [4] f32, list2 : [4] f32) f32 { const Vec4 = @Vector(4, f32); fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { -// const abs_diff_vec = ???; - const abs_diff_vec = @abs(a - b); -// const max_diff = @reduce(???, abs_diff_vec); - const max_diff = @reduce(.Max, abs_diff_vec); + const abs_diff_vec = ???; + const max_diff = @reduce(???, abs_diff_vec); return max_diff; } From 8cce587d3ba60d8073a38a87a71caa5bfaa859c6 Mon Sep 17 00:00:00 2001 From: bgthompson Date: Thu, 7 Nov 2024 13:31:32 +1000 Subject: [PATCH 036/118] added patch file for 109_vectors --- patches/patches/109_vectors.patch | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 patches/patches/109_vectors.patch diff --git a/patches/patches/109_vectors.patch b/patches/patches/109_vectors.patch new file mode 100644 index 0000000..ec2189e --- /dev/null +++ b/patches/patches/109_vectors.patch @@ -0,0 +1,13 @@ +--- exercises/109_vectors.zig 2024-11-03 11:17:00.928652000 +1000 ++++ answers/109_vectors.zig 2024-11-07 13:11:23.838667200 +1000 +@@ -121,8 +121,8 @@ + + const Vec4 = @Vector(4, f32); + fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { +- const abs_diff_vec = ???; +- const max_diff = @reduce(???, abs_diff_vec); ++ const abs_diff_vec = @abs(a - b); ++ const max_diff = @reduce(.Max, abs_diff_vec); + return max_diff; + } + From 46e8fc0b614bd3187ab6b2c6b4cc83996fb8bf56 Mon Sep 17 00:00:00 2001 From: bgthompson Date: Thu, 7 Nov 2024 13:42:53 +1000 Subject: [PATCH 037/118] line ending format patch attempt --- patches/patches/109_vectors.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/patches/109_vectors.patch b/patches/patches/109_vectors.patch index ec2189e..4b11da9 100644 --- a/patches/patches/109_vectors.patch +++ b/patches/patches/109_vectors.patch @@ -6,7 +6,7 @@ fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { - const abs_diff_vec = ???; - const max_diff = @reduce(???, abs_diff_vec); -+ const abs_diff_vec = @abs(a - b); ++ const abs_diff_vec = @abs( a - b ); + const max_diff = @reduce(.Max, abs_diff_vec); return max_diff; } From bfed6600205504a3fd2e3d3922ca5da6995224a7 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 7 Nov 2024 15:01:59 +0100 Subject: [PATCH 038/118] Fixed formating, created patch file. --- exercises/109_vectors.zig | 42 +++++++++++++++---------------- patches/patches/109_vectors.patch | 8 +++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/exercises/109_vectors.zig b/exercises/109_vectors.zig index 106937e..96892ca 100644 --- a/exercises/109_vectors.zig +++ b/exercises/109_vectors.zig @@ -10,16 +10,16 @@ // These are known as "single instruction, multiple data" (SIMD) // instructions. SIMD instructions can make code significantly // more performant. -// +// // To see why, imagine we have a program in which we take the // square root of four (changing) f32 floats. -// +// // A simple compiler would take the program and produce machine code // which calculates each square root sequentially. Most registers on // modern CPUs have 64 bits, so we could imagine that each float moves // into a 64-bit register, and the following happens four times: // -// 32 bits 32 bits +// 32 bits 32 bits // +-------------------+ // register | 0 | x | // +-------------------+ @@ -35,7 +35,7 @@ // Notice that half of the register contains blank data to which // nothing happened. What a waste! What if we were able to use // that space instead? This is the idea at the core of SIMD. -// +// // Most modern CPUs contain specialized registers with at least 128 bits // for performing SIMD instructions. On a machine with 128-bit SIMD // registers, a smart compiler would probably NOT issue four sqrt @@ -50,11 +50,11 @@ // +---------------------------------------+ // register | 4.0 | 9.0 | 25.0 | 49.0 | // +---------------------------------------+ -// +// // | // [SIMD SQRT instruction] // V -// +// // +---------------------------------------+ // register | 2.0 | 3.0 | 5.0 | 7.0 | // +---------------------------------------+ @@ -74,26 +74,26 @@ // SIMD instructions, whenever possible. // // Defining vectors in Zig is straightforwards. No library import is needed. -const v1 = @Vector(3, i32) { 1, 10, 100}; -const v2 = @Vector(3, f32) {2.0, 3.0, 5.0}; +const v1 = @Vector(3, i32){ 1, 10, 100 }; +const v2 = @Vector(3, f32){ 2.0, 3.0, 5.0 }; // Vectors support the same builtin operators as their underlying base types. const v3 = v1 + v1; // { 2, 20, 200}; const v4 = v2 * v2; // { 4.0, 9.0, 25.0}; // Intrinsics that apply to base types usually extend to vectors. -const v5 : @Vector(3, f32) = @floatFromInt(v3); // { 2.0, 20.0, 200.0} -const v6 = v4 - v5; // { 2.0, -11.0, -175.0} -const v7 = @abs(v6); // { 2.0, 11.0, 175.0} +const v5: @Vector(3, f32) = @floatFromInt(v3); // { 2.0, 20.0, 200.0} +const v6 = v4 - v5; // { 2.0, -11.0, -175.0} +const v7 = @abs(v6); // { 2.0, 11.0, 175.0} // We can make constant vectors, and reduce vectors. -const v8 : @Vector(4, u8) = @splat(2); // { 2, 2, 2, 2} -const v8_sum = @reduce(.Add, v8); // 8 -const v8_min = @reduce(.Min, v8); // 2 +const v8: @Vector(4, u8) = @splat(2); // { 2, 2, 2, 2} +const v8_sum = @reduce(.Add, v8); // 8 +const v8_min = @reduce(.Min, v8); // 2 // Fixed-length arrays can be automatically assigned to vectors (and vice-versa). -const single_digit_primes = [4] i8 {2, 3, 5, 7}; -const prime_vector : @Vector(4, i8) = single_digit_primes; +const single_digit_primes = [4]i8{ 2, 3, 5, 7 }; +const prime_vector: @Vector(4, i8) = single_digit_primes; // Now let's use vectors to simplify and optimize some code! // @@ -103,8 +103,8 @@ const prime_vector : @Vector(4, i8) = single_digit_primes; // // Ewa wrote the following function to figure this out. -fn calcMaxPairwiseDiffOld( list1 : [4] f32, list2 : [4] f32) f32 { - var max_diff : f32 = 0; +fn calcMaxPairwiseDiffOld(list1: [4]f32, list2: [4]f32) f32 { + var max_diff: f32 = 0; for (list1, list2) |n1, n2| { const abs_diff = @abs(n1 - n2); if (abs_diff > max_diff) { @@ -120,7 +120,7 @@ fn calcMaxPairwiseDiffOld( list1 : [4] f32, list2 : [4] f32) f32 { // Help Ewa finish the vector version! The examples above should help. const Vec4 = @Vector(4, f32); -fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { +fn calcMaxPairwiseDiffNew(a: Vec4, b: Vec4) f32 { const abs_diff_vec = ???; const max_diff = @reduce(???, abs_diff_vec); return max_diff; @@ -138,8 +138,8 @@ const std = @import("std"); const print = std.debug.print; pub fn main() void { - const l1 = [4] f32 { 3.141, 2.718, 0.577, 1.000}; - const l2 = [4] f32 { 3.154, 2.707, 0.591, 0.993}; + const l1 = [4]f32{ 3.141, 2.718, 0.577, 1.000 }; + const l2 = [4]f32{ 3.154, 2.707, 0.591, 0.993 }; const mpd_old = calcMaxPairwiseDiffOld(l1, l2); const mpd_new = calcMaxPairwiseDiffNew(l1, l2); print("Max difference (old fn): {d: >5.3}\n", .{mpd_old}); diff --git a/patches/patches/109_vectors.patch b/patches/patches/109_vectors.patch index 4b11da9..bf18cc0 100644 --- a/patches/patches/109_vectors.patch +++ b/patches/patches/109_vectors.patch @@ -1,12 +1,12 @@ ---- exercises/109_vectors.zig 2024-11-03 11:17:00.928652000 +1000 -+++ answers/109_vectors.zig 2024-11-07 13:11:23.838667200 +1000 +--- exercises/109_vectors.zig 2024-11-07 14:57:09.673383618 +0100 ++++ answers/109_vectors.zig 2024-11-07 14:22:59.069150138 +0100 @@ -121,8 +121,8 @@ const Vec4 = @Vector(4, f32); - fn calcMaxPairwiseDiffNew( a : Vec4, b : Vec4) f32 { + fn calcMaxPairwiseDiffNew(a: Vec4, b: Vec4) f32 { - const abs_diff_vec = ???; - const max_diff = @reduce(???, abs_diff_vec); -+ const abs_diff_vec = @abs( a - b ); ++ const abs_diff_vec = @abs(a - b); + const max_diff = @reduce(.Max, abs_diff_vec); return max_diff; } From 97c2ea2f498933cbf46e154acf14126b3821b0e3 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 7 Nov 2024 15:30:13 +0100 Subject: [PATCH 039/118] Added SIMD. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2aa52cd..c1ace19 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ Zig Core Language * [X] Working with C * [X] Threading * [x] Labeled switch +* [x] Vector operations (SIMD) Zig Standard Library From 37a0f4262155dc91e4d02ef593e86dd7050ff814 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 7 Nov 2024 21:45:47 +0100 Subject: [PATCH 040/118] Fixed link to format source code. --- exercises/099_formatting.zig | 2 +- patches/patches/099_formatting.patch | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/099_formatting.zig b/exercises/099_formatting.zig index 4b64209..37fab45 100644 --- a/exercises/099_formatting.zig +++ b/exercises/099_formatting.zig @@ -16,7 +16,7 @@ // Therefore, the comments for the format() function are the only // way to definitively learn how to format strings in Zig: // -// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29 +// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L33 // // Zig already has a very nice selection of formatting options. // These can be used in different ways, but generally to convert diff --git a/patches/patches/099_formatting.patch b/patches/patches/099_formatting.patch index 384bf86..a56b556 100644 --- a/patches/patches/099_formatting.patch +++ b/patches/patches/099_formatting.patch @@ -1,5 +1,5 @@ ---- exercises/099_formatting.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/099_formatting.zig 2023-10-05 20:04:07.292771311 +0200 +--- exercises/099_formatting.zig 2024-11-07 21:45:10.459123650 +0100 ++++ answers/099_formatting.zig 2024-11-07 21:43:55.154345991 +0100 @@ -131,7 +131,7 @@ for (0..size) |b| { // What formatting is needed here to make our columns From e55f8e8699b6353e0f0f4ff038ad10e456dd6ff6 Mon Sep 17 00:00:00 2001 From: innerviewer Date: Thu, 7 Nov 2024 22:05:00 +0100 Subject: [PATCH 041/118] Added missing space after a sentence. --- exercises/105_threading2.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/105_threading2.zig b/exercises/105_threading2.zig index 7ca8f5c..7e16a1c 100644 --- a/exercises/105_threading2.zig +++ b/exercises/105_threading2.zig @@ -39,7 +39,7 @@ // in practice. Because either you don't need the precision, or you use a // calculator in which the number is stored as a very precise constant. // But at some point this constant was calculated and we are doing the same -// now.The question at this point is, how many partial values do we have +// now. The question at this point is, how many partial values do we have // to calculate for which accuracy? // // The answer is chewing, to get 8 digits after the decimal point we need From 33d61cb3c9a0d7572937dea875037f0a1e817939 Mon Sep 17 00:00:00 2001 From: innerviewer Date: Fri, 8 Nov 2024 13:29:44 +0100 Subject: [PATCH 042/118] Minor case-related changes. --- exercises/106_files.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/106_files.zig b/exercises/106_files.zig index f5fd1ac..b224508 100644 --- a/exercises/106_files.zig +++ b/exercises/106_files.zig @@ -9,7 +9,7 @@ // by organizing them into directories, which hold files and other directories, // thus creating a tree structure that can be navigated. // -// Fortunately, the Zig standard library provides a simple API for interacting +// Fortunately, the Zig Standard Library provides a simple API for interacting // with the file system, see the detail documentation here: // // https://ziglang.org/documentation/master/std/#std.fs From 0d9458807e88235fcd3511fc044ed43833c0fa56 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 8 Nov 2024 22:48:37 +0100 Subject: [PATCH 043/118] Deleted unnecessary pointer. --- exercises/046_optionals2.zig | 2 +- patches/patches/046_optionals2.patch | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/046_optionals2.zig b/exercises/046_optionals2.zig index a5436d9..b5fffbb 100644 --- a/exercises/046_optionals2.zig +++ b/exercises/046_optionals2.zig @@ -48,7 +48,7 @@ pub fn main() void { // If e1 and e2 are valid pointers to elephants, // this function links the elephants so that e1's tail "points" to e2. fn linkElephants(e1: ?*Elephant, e2: ?*Elephant) void { - e1.?.*.tail = e2.?; + e1.?.tail = e2.?; } // This function visits all elephants once, starting with the diff --git a/patches/patches/046_optionals2.patch b/patches/patches/046_optionals2.patch index 1b364a6..8fa01a2 100644 --- a/patches/patches/046_optionals2.patch +++ b/patches/patches/046_optionals2.patch @@ -1,5 +1,5 @@ ---- exercises/046_optionals2.zig 2024-09-04 20:51:36.766783971 +0200 -+++ answers/046_optionals2.zig 2024-09-04 20:51:01.389400985 +0200 +--- exercises/046_optionals2.zig 2024-11-08 22:46:25.592875338 +0100 ++++ answers/046_optionals2.zig 2024-11-08 22:46:20.699447951 +0100 @@ -22,7 +22,7 @@ const Elephant = struct { From 83e00872b822a853587b7bf75bf481d1fc6724f0 Mon Sep 17 00:00:00 2001 From: innerviewer Date: Sat, 9 Nov 2024 20:36:47 +0100 Subject: [PATCH 044/118] Added patch file. --- patches/patches/106_files.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/patches/patches/106_files.patch b/patches/patches/106_files.patch index 5eb5a19..89f37ad 100644 --- a/patches/patches/106_files.patch +++ b/patches/patches/106_files.patch @@ -1,5 +1,5 @@ ---- exercises/106_files.zig 2024-06-17 10:11:53.651439869 +0200 -+++ answers/106_files.zig 2024-06-17 10:21:50.697337653 +0200 +--- exercises/106_files.zig 2024-11-09 20:33:07.455580904 +0100 ++++ answers/106_files.zig 2024-11-09 20:33:30.394785215 +0100 @@ -1,22 +1,22 @@ // // Until now, we've only been printing our output in the console, @@ -17,9 +17,9 @@ +// by organizing files into directories, which hold files and other directories, +// thus creating a tree structure for navigating. // --// Fortunately, the Zig standard library provides a simple API for interacting +-// Fortunately, the Zig Standard Library provides a simple API for interacting -// with the file system, see the detail documentation here: -+// Fortunately, zig standard library provide a simple api for interacting ++// Fortunately, the Zig Standard Library provide a simple api for interacting +// with the file system, see the detail documentation here // // https://ziglang.org/documentation/master/std/#std.fs From f446402105853a87ce2289178a578d134f9fe6ba Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 22 Dec 2024 15:52:52 +0100 Subject: [PATCH 045/118] Updated credits --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c1ace19..ae2a4c4 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,10 @@ Those broken programs need your help! (You'll also save the planet from evil aliens and help some friendly elephants stick together, which is very sweet of you.) -This project was directly inspired by the brilliant and fun -[rustlings](https://github.com/rust-lang/rustlings) -project for the [Rust](https://www.rust-lang.org/) language. -Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/) -and the Little LISPer/Little Schemer series of books. -Ziglings was initiated by [Dave Gauer](https://ratfactor.com/). +This project was initiated by [Dave Gauer]()https://ratfactor.com/ and is directly inspired +by the brilliant and fun [rustlings](https://github.com/rust-lang/rustlings) project. +Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/) and the Little LISPer/Little +Schemer series of books. ## Intended Audience From 105c98782c9534aeca7245cbb3ae2be8b17e7534 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 22 Dec 2024 15:59:21 +0100 Subject: [PATCH 046/118] Updated credits --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ae2a4c4..f478944 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Those broken programs need your help! (You'll also save the planet from evil aliens and help some friendly elephants stick together, which is very sweet of you.) -This project was initiated by [Dave Gauer]()https://ratfactor.com/ and is directly inspired +This project was initiated by [Dave Gauer](https://ratfactor.com/) and is directly inspired by the brilliant and fun [rustlings](https://github.com/rust-lang/rustlings) project. Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/) and the Little LISPer/Little Schemer series of books. From de353bcb3b6d7ef59bcf1ceb0a326ab6e5a4139f Mon Sep 17 00:00:00 2001 From: mikkurogue Date: Sat, 4 Jan 2025 11:56:25 +0000 Subject: [PATCH 047/118] Update: 108 Labeled switch example to contain default case for exhaustion Update example text to give clarity on default/exhaustive case. Reasoning: The input for the example will not compile if user would want to test this for the logic of a labeled switch. Due the input not being an exhaustive input but rather "any u8 integer" (for the lack of better terminology) we need to use the else branch to indicate that the default case is handled, in this case by just emulating the '4' branch, but this could return an error.InvalidCaseProvided for example. Signed-off-by: mikkurogue --- exercises/108_labeled_switch.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 88cb196..d506cac 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -35,6 +35,7 @@ // 2 => continue :foo 3, // 3 => return, // 4 => {}, +// else => {}, // } // std.debug.print("This statement cannot be reached"); // } @@ -46,6 +47,9 @@ // 3. In the case '2' we repeat the same pattern as case '1' // but instead the value to be evaluated is now '3'; // 4. Finally we get to case '3', where we return from the function as a whole. +// 5. In this example as the input has no clear exhaustive patterns but a essentially +// any u8 integer, we need do need to handle any case that is not explicitly handled +// by using the `else => {}` branch as a default case. // // Since step 4 or a break stament do not exist in this switch, the debug statement is // never executed From 26978cb2d388c2990ba9e2658a14edbc42ccce64 Mon Sep 17 00:00:00 2001 From: David Pape Date: Sat, 4 Jan 2025 21:40:19 +0100 Subject: [PATCH 048/118] =?UTF-8?q?Fix=20typo=20vaild=20=E2=86=92=20valid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- exercises/107_files2.zig | 2 +- patches/patches/107_files2.patch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/107_files2.zig b/exercises/107_files2.zig index 45e12f5..6768898 100644 --- a/exercises/107_files2.zig +++ b/exercises/107_files2.zig @@ -40,7 +40,7 @@ pub fn main() !void { // okay, seems like a threat of violence is not the answer in this case // can you go here to find a way to read the content? // https://ziglang.org/documentation/master/std/#std.fs.File - // hint: you might find two answers that are both vaild in this case + // hint: you might find two answers that are both valid in this case const bytes_read = zig_read_the_file_or_i_will_fight_you(&content); // Woah, too screamy. I know you're excited for zigling time but tone it down a bit. diff --git a/patches/patches/107_files2.patch b/patches/patches/107_files2.patch index ebf8a7c..f03a2e8 100644 --- a/patches/patches/107_files2.patch +++ b/patches/patches/107_files2.patch @@ -42,7 +42,7 @@ - // can you go here to find a way to read the content? + // can you go here to find a way to read the content ? // https://ziglang.org/documentation/master/std/#std.fs.File - // hint: you might find two answers that are both vaild in this case + // hint: you might find two answers that are both valid in this case - const bytes_read = zig_read_the_file_or_i_will_fight_you(&content); + const bytes_read = try file.read(&content); From 5cdaee74205e97da127d749b07cbe6e64ba6a940 Mon Sep 17 00:00:00 2001 From: mikkurogue Date: Tue, 7 Jan 2025 10:15:59 +0000 Subject: [PATCH 049/118] Update: Remove the 4th branch in favour of just making that the else branch Probably easier to not have an "unused" branch that returns the same as the else branch in the example. Signed-off-by: mikkurogue --- exercises/108_labeled_switch.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index d506cac..bd0b478 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -34,7 +34,6 @@ // 1 => continue :foo 2, // 2 => continue :foo 3, // 3 => return, -// 4 => {}, // else => {}, // } // std.debug.print("This statement cannot be reached"); From c2dcaf309953cfa89947e359db93c2c2b13f19ba Mon Sep 17 00:00:00 2001 From: Zorgatone Date: Tue, 7 Jan 2025 15:21:36 +0000 Subject: [PATCH 050/118] Use print alias in exercise 100_for4.zig --- exercises/100_for4.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/100_for4.zig b/exercises/100_for4.zig index e0fa602..c8a1161 100644 --- a/exercises/100_for4.zig +++ b/exercises/100_for4.zig @@ -41,12 +41,12 @@ pub fn main() void { for (hex_nums, ???) |hn, ???| { if (hn != dn) { - std.debug.print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn }); + print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn }); return; } } - std.debug.print("Arrays match!\n", .{}); + print("Arrays match!\n", .{}); } // // You are perhaps wondering what happens if one of the two lists From 6b29634279f2a82ee71159f49d93ceea19869e8d Mon Sep 17 00:00:00 2001 From: Zorgatone Date: Tue, 7 Jan 2025 15:26:04 +0000 Subject: [PATCH 051/118] Fix patch after print alias fix in 100_fo4.zig --- patches/patches/100_for4.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/patches/100_for4.patch b/patches/patches/100_for4.patch index 3539be2..ad73e9a 100644 --- a/patches/patches/100_for4.patch +++ b/patches/patches/100_for4.patch @@ -7,5 +7,5 @@ - for (hex_nums, ???) |hn, ???| { + for (hex_nums, dec_nums) |hn, dn| { if (hn != dn) { - std.debug.print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn }); + print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn }); return; From 87b258d0a90af4cf5e16986226b589c2a541db32 Mon Sep 17 00:00:00 2001 From: mikkurogue Date: Tue, 7 Jan 2025 18:00:16 +0000 Subject: [PATCH 052/118] Fix a typo: we need do we need to -> we need to Morning delirium does not help when looking at lots of words --- exercises/108_labeled_switch.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index bd0b478..1e39935 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -47,7 +47,7 @@ // but instead the value to be evaluated is now '3'; // 4. Finally we get to case '3', where we return from the function as a whole. // 5. In this example as the input has no clear exhaustive patterns but a essentially -// any u8 integer, we need do need to handle any case that is not explicitly handled +// any u8 integer, we need to handle any case that is not explicitly handled // by using the `else => {}` branch as a default case. // // Since step 4 or a break stament do not exist in this switch, the debug statement is From 54f743ba43630a452f8104b5b21fbbcdeefe866f Mon Sep 17 00:00:00 2001 From: chrboesch Date: Wed, 8 Jan 2025 12:18:25 +0000 Subject: [PATCH 053/118] Update exercises/108_labeled_switch.zig The sentence was slightly unclear Signed-off-by: chrboesch --- exercises/108_labeled_switch.zig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 1e39935..24cf2fa 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -46,9 +46,10 @@ // 3. In the case '2' we repeat the same pattern as case '1' // but instead the value to be evaluated is now '3'; // 4. Finally we get to case '3', where we return from the function as a whole. -// 5. In this example as the input has no clear exhaustive patterns but a essentially -// any u8 integer, we need to handle any case that is not explicitly handled -// by using the `else => {}` branch as a default case. +// 5. In this example, since the input does not have clear, exhaustive patterns and +// can essentially be any `u8` integer, we need to handle all cases not explicitly +// covered by using the `else => {}` branch as the default case. + // // Since step 4 or a break stament do not exist in this switch, the debug statement is // never executed From 90d05995b5d5453bfed4eef2547dd31efa3af412 Mon Sep 17 00:00:00 2001 From: chrboesch Date: Wed, 8 Jan 2025 13:22:29 +0000 Subject: [PATCH 054/118] Update exercises/108_labeled_switch.zig Fixed an error in the debug statement and made the text a bit more coherent. Signed-off-by: chrboesch --- exercises/108_labeled_switch.zig | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 24cf2fa..16a5879 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -15,11 +15,11 @@ // 1 => { op = 2; continue; }, // 2 => { op = 3; continue; }, // 3 => return, -// 4 => {}, +// else => {}, // } // break; // } -// std.debug.print("This statement cannot be reached"); +// std.debug.print("This statement cannot be reached\n", .{}); // } // // By combining all we've learned so far, we can now proceed with a labeled switch @@ -36,23 +36,21 @@ // 3 => return, // else => {}, // } -// std.debug.print("This statement cannot be reached"); +// std.debug.print("This statement cannot be reached\n", .{}); // } // // The flow of execution on this second case is: // 1. The switch starts with value '1'; // 2. The switch evaluates to case '1' which in turn uses the continue statement -// to re-evaluate the labeled switch again, now providing the value '2'; +// to re-evaluate the labeled switch again, now providing the value '2'; // 3. In the case '2' we repeat the same pattern as case '1' -// but instead the value to be evaluated is now '3'; -// 4. Finally we get to case '3', where we return from the function as a whole. +// but instead the value to be evaluated is now '3'; +// 4. Finally we get to case '3', where we return from the function as a whole, +// so the debug statement is never executed. // 5. In this example, since the input does not have clear, exhaustive patterns and -// can essentially be any `u8` integer, we need to handle all cases not explicitly -// covered by using the `else => {}` branch as the default case. - +// can essentially be any 'u8' integer, we need to handle all cases not explicitly +// covered by using the 'else => {}' branch as the default case. // -// Since step 4 or a break stament do not exist in this switch, the debug statement is -// never executed // const std = @import("std"); From 3faad6e17b03f13e91d4b93a525e6608c72c8ace Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:01:25 -0800 Subject: [PATCH 055/118] Suggesting a third exercise for bit manipulation --- build.zig | 32 ++ exercises/110_bit_manipulation3.zig | 443 ++++++++++++++++++++++++++++ 2 files changed, 475 insertions(+) create mode 100644 exercises/110_bit_manipulation3.zig diff --git a/build.zig b/build.zig index e528552..9774833 100644 --- a/build.zig +++ b/build.zig @@ -1208,6 +1208,38 @@ const exercises = [_]Exercise{ \\Max difference (new fn): 0.014 , }, + .{ .main_file = "110_bit_manipulation3.zig", .output = + \\Set pins with OR on PORTB + \\------------------------- + \\ 1001 // (initial state of PORTB) + \\| 0100 // (bitmask) + \\= 1101 + \\ + \\ 1001 // (reset state) + \\| 0100 // (bitmask) + \\= 1101 + \\ + \\Clear pins with AND and NOT on PORTB + \\------------------------------------ + \\ 1110 // (initial state of PORTB) + \\& 1011 // (bitmask) + \\= 1010 + \\ + \\ 0111 // (reset state) + \\& 1110 // (bitmask) + \\= 0110 + \\ + \\ + \\Toggle pins with XOR on PORTB + \\----------------------------- + \\ 1100 // (initial state of PORTB) + \\^ 0101 // (bitmask) + \\= 1001 + \\ + \\ 1100 // (initial state of PORTB) + \\^ 0011 // (bitmask) + \\= 1111 + }, .{ .main_file = "999_the_end.zig", .output = diff --git a/exercises/110_bit_manipulation3.zig b/exercises/110_bit_manipulation3.zig new file mode 100644 index 0000000..930f78a --- /dev/null +++ b/exercises/110_bit_manipulation3.zig @@ -0,0 +1,443 @@ +// ---------------------------------------------------------------------------- +// Setting, Clearing, and Toggling Bits +// ---------------------------------------------------------------------------- +// +// Another exciting thing about Zig is its suitability for embedded +// programming. Your Zig code doesn't have to remain on your laptop. You can +// also deploy your code to microcontrollers! This means you can write Zig to +// drive your next robot or greenhouse climate control system! Ready to enter +// the exciting world of embedded programming? This exercise is designed to +// give you a taste of what it's like to control registers in a +// microcontroller. Let's get started! +// +// A common activity in microcontroller programming is setting and clearing +// bits on input and output pins. This lets you control LEDs, sensors, motors +// and more! In a previous exercise (097_bit_manipulation.zig) you learned how +// to swap two bytes using the ^ (XOR - exclusive or) operator. In this +// exercise, we'll take a closer look at bit manipulation and how we can write +// code that sets and clears specific bits as we would if we were programming +// the pins on a real microcontroller. Included at the end of this exercise are +// some helper functions that demonstrate how we might make our code a little +// more readable. +// +// Below is a pinout diagram for the famous ATmega328 AVR microcontroller used +// as the primary microchip on popular microcontroller platforms like the +// Arduino UNO. +// +// ============ PINOUT DIAGRAM FOR ATMEGA328 MICROCONTROLLER ============ +// _____ _____ +// | U | +// (RESET) PC6 --| 1 28 |-- PC5 +// PD0 --| 2 27 |-- PC4 +// PD1 --| 3 26 |-- PC3 +// PD2 --| 4 25 |-- PC2 +// PD3 --| 5 24 |-- PC1 +// PD4 --| 6 23 |-- PC0 +// VCC --| 7 22 |-- GND +// GND --| 8 21 |-- AREF +// |-- PB6 --| 9 20 |-- AVCC +// |-- PB7 --| 10 19 |-- PB5 --| +// | PD5 --| 11 18 |-- PB4 --| +// | PD6 --| 12 17 |-- PB3 --| +// | PD7 --| 13 16 |-- PB2 --| +// |-- PB0 --| 14 15 |-- PB1 --| +// | |___________| | +// \_______________________________/ +// | +// PORTB +// +// Drawing inspiration from this diagram, we'll use the pins for PORTB as our +// mental model for this exercise in bit manipulation. It should be noted that +// in the following examples we are using ordinary variables, one of which we +// have named PORTB, to simulate modifying the bits of real hardware registers. +// But in actual microcontroller code, PORTB would be defined something like +// this: +// pub const PORTB = @as(*volatile u8, @ptrFromInt(0x25)); +// +// This lets the compiler know not to make any optimizations to PORTB so that +// the IO pins are properly mapped to our code. +// +// NOTE : To keep things simple, the following examples are given using type +// u4, so applying the output to PORTB would only affect the lower four pins +// PB0..PB3. Of course, there is nothing to prevent you from swapping the u4 +// with a u8 so you can control all 8 of PORTB's IO pins. + +const std = @import("std"); +const print = std.debug.print; +const testing = std.testing; + +pub fn main() !void { + var PORTB: u4 = 0b0000; // only 4 bits wide for simplicity + // + // ------------------------------------------------------------------------ + // Setting bits with OR: + // ------------------------------------------------------------------------ + // We can set bits on PORTB with the | (OR) operator, like so: + // + // var PORTB: u4 = 0b1001; + // PORTB = PORTB | 0b0010; + // print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 + // + // -OR op- ---expanded--- + // _ Set only this bit. + // / + // 1001 1 0 0 1 + // | 0010 0 0 1 0 (bit mask) + // ------ - - - - + // = 1011 1 0 1 1 + // \___\_______\ + // \ + // These bits remain untouched because OR-ing with + // a 0 effects no change. + // + // ------------------------------------------------------------------------ + // To create a bit mask like 0b0010 used above: + // + // 1. First, shift the value 1 over one place with the bitwise << (shift + // left) operator as indicated below: + // 1 << 0 -> 0001 + // 1 << 1 -> 0010 <-- Shift 1 one place to the left + // 1 << 2 -> 0100 + // 1 << 3 -> 1000 + // + // This allows us to rewrite the above code like this: + // + // var PORTB: u4 = 0b1001; + // PORTB = PORTB | (1 << 1); + // print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 + // + // Finally, as in the C language, Zig allows us to use the |= operator, so + // we can rewrite our code again in an even more compact and idiomatic + // form: PORTB |= (1 << 1) + + print("Set pins with OR on PORTB\n", .{}); + print("-------------------------\n", .{}); + + PORTB = 0b1001; // reset PORTB + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("| {b:0>4} // (bitmask)\n", .{0b0100}); + PORTB = PORTB ??? (1 << 2); // What's missing here? + checkAnswer(0b1101, PORTB); + + newline(); + + PORTB = 0b1001; // reset PORTB + print(" {b:0>4} // (reset state)\n", .{PORTB}); + print("| {b:0>4} // (bitmask)\n", .{0b0100}); + PORTB ??? (1 << 2); // What's missing here? + checkAnswer(0b1101, PORTB); + + newline(); + + // ------------------------------------------------------------------------ + // Clearing bits with AND and NOT: + // ------------------------------------------------------------------------ + // We can clear bits with the & (AND) bitwise operator, like so: + + // PORTB = 0b1110; // reset PORTB + // PORTB = PORTB & 0b1011; + // print("PORTB: {b:0>4}\n", .{PORTB}); // output -> 1010 + // + // - 0s clear bits when used in conjuction with a bitwise AND. + // - 1s do nothing, thus preserving the original bits. + // + // -AND op- ---expanded--- + // __________ Clear only this bit. + // / + // 1110 1 1 1 0 + // & 1011 1 0 1 1 (bit mask) + // ------ - - - - + // = 1010 1 0 1 0 <- This bit was already cleared. + // \_______\ + // \ + // These bits remain untouched because AND-ing with a + // 1 preserves the original bit value whether 0 or 1. + // + // ------------------------------------------------------------------------ + // We can use the ~ (NOT) operator to easily create a bit mask like 1011: + // + // 1. First, shift the value 1 over two places with the bit-wise << (shift + // left) operator as indicated below: + // 1 << 0 -> 0001 + // 1 << 1 -> 0010 + // 1 << 2 -> 0100 <- The 1 has been shifted two places to the left + // 1 << 3 -> 1000 + // + // 2. The second step in creating our bit mask is to invert the bits + // ~0100 -> 1011 + // we can write this as: + // ~(1 << 2) -> 1011 + // + // But if we try to compile ~(1 << 2), we'll get an error: + // unable to perform binary not operation on type 'comptime_int' + // + // Before Zig can invert our bits, it needs to know the number of + // bits it's being asked to invert. + // + // We do this with the @as (cast as) built-in like this: + // @as(u4, 1 << 2) -> 0100 + // + // Finally, we can invert our new mask by placing the NOT ~ operator + // before our expression, like this: + // ~@as(u4, 1 << 2) -> 1011 + // + // If you are offput by the fact that you can't simply invert bits like + // you can in languages such as C without casting to a particular size + // of integer, you're not alone. However, this is actually another + // instance where Zig is really helpful because it protects you from + // difficult to debug integer overflow bugs that can have you tearing + // your hair out. In the interest of keeping things sane, Zig requires + // you simply to tell it the size of number you are inverting. In the + // words of Andrew Kelley, "If you want to invert the bits of an + // integer, zig has to know how many bits there are." + // + // For more insight into the Zig team's position on why the language + // takes the approach it does with the ~ operator, take a look at + // Andrew's comments on the following github issue: + // https://github.com/ziglang/zig/issues/1382#issuecomment-414459529 + // + // Whew, so after all that what we end up with is: + // PORTB = PORTB & ~@as(u4, 1 << 2); + // + // We can shorten this with the &= combined AND and assignment operator, + // which applies the AND operator on PORTB and then reassigns PORTB. Here's + // what that looks like: + // PORTB &= ~@as(u4, 1 << 2); + // + + print("Clear pins with AND and NOT on PORTB\n", .{}); + print("------------------------------------\n", .{}); + + PORTB = 0b1110; // reset PORTB + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("& {b:0>4} // (bitmask)\n", .{0b1011}); + PORTB = PORTB & ???@as(u4, 1 << 2); // What character is missing here? + checkAnswer(0b1010, PORTB); + + newline(); + + PORTB = 0b0111; // reset PORTB + print(" {b:0>4} // (reset state)\n", .{PORTB}); + print("& {b:0>4} // (bitmask)\n", .{0b1110}); + PORTB &= ~(1 << 0); // What's missing here? + checkAnswer(0b0110, PORTB); + + newline(); + newline(); + + + // + // ------------------------------------------------------------------------ + // Toggling bits with XOR: + // ------------------------------------------------------------------------ + // XOR stands for "exclusive or". We can toggle bits with the ^ (XOR) + // bitwise operator, like so: + // + // + // In order to output a 1, the logic of an XOR operation requires that the + // two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will + // both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior + // of outputing a 0 when both inputs are 1s is what makes it different from + // the OR operator; it also gives us the ability to toggle bits by putting + // 1s into our bitmask. + // + // - 1s in our bitmask operand, can be thought of as causing the + // corresponding bits in the other operand to flip to the opposite value. + // - 0s cause no change. + // + // The 0s in our bitmask preserve these values + // -XOR op- ---expanded--- in the output. + // _______________/ + // / / + // 0110 1 1 0 0 + // ^ 1111 0 1 0 1 (bitmask) + // ------ - - - - + // = 1001 1 0 0 1 <- This bit was already cleared. + // \_______\ + // \ + // We can think of these bits having flipped + // because of the presence of 1s in those columns + // of our bitmask. + + print("Toggle pins with XOR on PORTB\n", .{}); + print("-----------------------------\n", .{}); + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0101}); + PORTB ^= (1 << 1) | (1 << 0); // What's wrong here? + checkAnswer(0b1001, PORTB); + + newline(); + + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0011}); + PORTB ^= (1 << 1) & (1 << 0); // What's wrong here? + checkAnswer(0b1111, PORTB); + + // While the examples in this exercise have used only 4-bit wide variables, + // working with 8 bits is no different. Here's a an example where we set + // every other bit beginning with the two's place: + + // var PORTD: u8 = 0b0000_0000; + // print("PORTD: {b:0>8}\n", .{PORTD}); + // PORTD |= (1 << 1); + // PORTD = setBit(u8, PORTD, 3); + // PORTD |= (1 << 5) | (1 << 7); + // print("PORTD: {b:0>8} // set every other bit\n", .{PORTD}); + // PORTD = ~PORTD; + // print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); + // newline(); + // + // // Here we clear every other bit beginning with the two's place. + // + // PORTD = 0b1111_1111; + // print("PORTD: {b:0>8}\n", .{PORTD}); + // PORTD &= ~@as(u8, 1 << 1); + // PORTD = clearBit(u8, PORTD, 3); + // PORTD &= ~@as(u8, (1 << 5) | (1 << 7)); + // print("PORTD: {b:0>8} // clear every other bit\n", .{PORTD}); + // PORTD = ~PORTD; + // print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); + // newline(); +} + +// ---------------------------------------------------------------------------- +// Here are some helper functions for manipulating bits +// ---------------------------------------------------------------------------- + +// Functions for setting, clearing, and toggling a single bit +fn setBit(comptime T: type, byte: T, comptime bit_pos: T) !T { + return byte | (1 << bit_pos); +} + +test "setBit" { + try testing.expectEqual(setBit(u8, 0b0000_0000, 3), 0b0000_1000); +} + +fn clearBit(comptime T: type, byte: T, comptime bit_pos: T) T { + return byte & ~@as(T, (1 << bit_pos)); +} + +test "clearBit" { + try testing.expectEqual(clearBit(u8, 0b1111_1111, 0), 0b1111_1110); +} + +fn toggleBit(comptime T: type, byte: T, comptime bit_pos: T) T { + return byte ^ (1 << bit_pos); +} + +test "toggleBit" { + var byte = toggleBit(u8, 0b0000_0000, 0); + try testing.expectEqual(byte, 0b0000_0001); + byte = toggleBit(u8, byte, 0); + try testing.expectEqual(byte, 0b0000_0000); +} + +// ---------------------------------------------------------------------------- +// Some additional functions for setting, clearing, and toggling multiple bits +// at once with a tuple because, hey, why not? +// ---------------------------------------------------------------------------- +// + +fn createBitmask(comptime T: type, comptime bits: anytype) !T { + comptime var bitmask: T = 0; + inline for (bits) |bit| { + if (bit >= @bitSizeOf(T)) return error.BitPosTooLarge; + if (bit < 0) return error.BitPosTooSmall; + + bitmask |= (1 << bit); + } + return bitmask; +} + +test "creating bitmasks from a tuple" { + try testing.expectEqual(createBitmask(u8, .{0}), 0b0000_0001); + try testing.expectEqual(createBitmask(u8, .{1}), 0b0000_0010); + try testing.expectEqual(createBitmask(u8, .{2}), 0b0000_0100); + try testing.expectEqual(createBitmask(u8, .{3}), 0b0000_1000); + // + try testing.expectEqual(createBitmask(u8, .{ 0, 4 }), 0b0001_0001); + try testing.expectEqual(createBitmask(u8, .{ 1, 5 }), 0b0010_0010); + try testing.expectEqual(createBitmask(u8, .{ 2, 6 }), 0b0100_0100); + try testing.expectEqual(createBitmask(u8, .{ 3, 7 }), 0b1000_1000); + + try testing.expectError(error.BitPosTooLarge, createBitmask(u4, .{4})); +} + +fn setBits(byte: u8, bits: anytype) !u8 { + const bitmask = try createBitmask(u8, bits); + return byte | bitmask; +} + +test "setBits" { + try testing.expectEqual(setBits(0b0000_0000, .{0}), 0b0000_0001); + try testing.expectEqual(setBits(0b0000_0000, .{7}), 0b1000_0000); + + try testing.expectEqual(setBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111); + try testing.expectEqual(setBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111); + + try testing.expectEqual(setBits(0b0000_0000, .{ 2, 3, 4, 5 }), 0b0011_1100); + + try testing.expectError(error.BitPosTooLarge, setBits(0b1111_1111, .{8})); + try testing.expectError(error.BitPosTooSmall, setBits(0b1111_1111, .{-1})); +} + +fn clearBits(comptime byte: u8, comptime bits: anytype) !u8 { + const bitmask: u8 = try createBitmask(u8, bits); + return byte & ~@as(u8, bitmask); +} + +test "clearBits" { + try testing.expectEqual(clearBits(0b1111_1111, .{0}), 0b1111_1110); + try testing.expectEqual(clearBits(0b1111_1111, .{7}), 0b0111_1111); + + try testing.expectEqual(clearBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000); + try testing.expectEqual(clearBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000); + + try testing.expectEqual(clearBits(0b1111_1111, .{ 0, 1, 6, 7 }), 0b0011_1100); + + try testing.expectError(error.BitPosTooLarge, clearBits(0b1111_1111, .{8})); + try testing.expectError(error.BitPosTooSmall, clearBits(0b1111_1111, .{-1})); +} + +fn toggleBits(comptime byte: u8, comptime bits: anytype) !u8 { + const bitmask = try createBitmask(u8, bits); + return byte ^ bitmask; +} + +test "toggleBits" { + try testing.expectEqual(toggleBits(0b0000_0000, .{0}), 0b0000_0001); + try testing.expectEqual(toggleBits(0b0000_0000, .{7}), 0b1000_0000); + + try testing.expectEqual(toggleBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000); + try testing.expectEqual(toggleBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111); + + try testing.expectEqual(toggleBits(0b0000_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_0000); + try testing.expectEqual(toggleBits(0b0000_1111, .{ 0, 1, 2, 3 }), 0b0000_0000); + + try testing.expectEqual(toggleBits(0b0000_0000, .{ 0, 2, 4, 6 }), 0b0101_0101); + + try testing.expectError(error.BitPosTooLarge, toggleBits(0b1111_1111, .{8})); + try testing.expectError(error.BitPosTooSmall, toggleBits(0b1111_1111, .{-1})); +} + +// ---------------------------------------------------------------------------- +// Utility functions +// ---------------------------------------------------------------------------- + +fn newline() void { + print("\n", .{}); +} + +fn checkAnswer(expected: u4, answer: u4) void { + if (expected != answer) { + print("*************************************************************\n", .{}); + print("= {b:0>4} <- INCORRECT! THE EXPECTED OUTPUT IS {b:0>4}\n", .{ answer, expected }); + print("*************************************************************\n", .{}); + } else { + print("= {b:0>4}", .{answer}); + } + newline(); +} + From 657fd6aff065b900d55c6e6f037fe4dc3dc6e7f6 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:57:23 -0800 Subject: [PATCH 056/118] changed the order of the sections to improve flow --- exercises/110_bit_manipulation3.zig | 110 +++++++++++++++------------- 1 file changed, 60 insertions(+), 50 deletions(-) diff --git a/exercises/110_bit_manipulation3.zig b/exercises/110_bit_manipulation3.zig index 930f78a..baf4045 100644 --- a/exercises/110_bit_manipulation3.zig +++ b/exercises/110_bit_manipulation3.zig @@ -1,5 +1,5 @@ // ---------------------------------------------------------------------------- -// Setting, Clearing, and Toggling Bits +// Toggling, Setting, and Clearing Bits // ---------------------------------------------------------------------------- // // Another exciting thing about Zig is its suitability for embedded @@ -69,6 +69,58 @@ const testing = std.testing; pub fn main() !void { var PORTB: u4 = 0b0000; // only 4 bits wide for simplicity // + // Let's first take a look at toggling bits. + // + // ------------------------------------------------------------------------ + // Toggling bits with XOR: + // ------------------------------------------------------------------------ + // XOR stands for "exclusive or". We can toggle bits with the ^ (XOR) + // bitwise operator, like so: + // + // + // In order to output a 1, the logic of an XOR operation requires that the + // two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will + // both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior + // of outputing a 0 when both inputs are 1s is what makes it different from + // the OR operator; it also gives us the ability to toggle bits by putting + // 1s into our bitmask. + // + // - 1s in our bitmask operand, can be thought of as causing the + // corresponding bits in the other operand to flip to the opposite value. + // - 0s cause no change. + // + // The 0s in our bitmask preserve these values + // -XOR op- ---expanded--- in the output. + // _______________/ + // / / + // 0110 1 1 0 0 + // ^ 1111 0 1 0 1 (bitmask) + // ------ - - - - + // = 1001 1 0 0 1 <- This bit was already cleared. + // \_______\ + // \ + // We can think of these bits having flipped + // because of the presence of 1s in those columns + // of our bitmask. + + print("Toggle pins with XOR on PORTB\n", .{}); + print("-----------------------------\n", .{}); + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0101}); + PORTB ^= (1 << 1) | (1 << 0); // What's wrong here? + checkAnswer(0b1001, PORTB); + + newline(); + + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0011}); + PORTB ^= (1 << 1) & (1 << 0); // What's wrong here? + checkAnswer(0b1111, PORTB); + + // Now let's take a look at setting bits with the | operator. + // // ------------------------------------------------------------------------ // Setting bits with OR: // ------------------------------------------------------------------------ @@ -129,6 +181,10 @@ pub fn main() !void { newline(); + // So now we've covered how to toggle and set bits. What about clearing + // them? Well, this is where Zig throws us a curve ball. Don't worry we'll + // go through it step by step. + // ------------------------------------------------------------------------ // Clearing bits with AND and NOT: // ------------------------------------------------------------------------ @@ -165,10 +221,10 @@ pub fn main() !void { // // 2. The second step in creating our bit mask is to invert the bits // ~0100 -> 1011 - // we can write this as: + // in C we would write this as: // ~(1 << 2) -> 1011 // - // But if we try to compile ~(1 << 2), we'll get an error: + // But if we try to compile ~(1 << 2) in Zig, we'll get an error: // unable to perform binary not operation on type 'comptime_int' // // Before Zig can invert our bits, it needs to know the number of @@ -225,56 +281,10 @@ pub fn main() !void { newline(); newline(); - - // // ------------------------------------------------------------------------ - // Toggling bits with XOR: + // Conclusion // ------------------------------------------------------------------------ - // XOR stands for "exclusive or". We can toggle bits with the ^ (XOR) - // bitwise operator, like so: // - // - // In order to output a 1, the logic of an XOR operation requires that the - // two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will - // both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior - // of outputing a 0 when both inputs are 1s is what makes it different from - // the OR operator; it also gives us the ability to toggle bits by putting - // 1s into our bitmask. - // - // - 1s in our bitmask operand, can be thought of as causing the - // corresponding bits in the other operand to flip to the opposite value. - // - 0s cause no change. - // - // The 0s in our bitmask preserve these values - // -XOR op- ---expanded--- in the output. - // _______________/ - // / / - // 0110 1 1 0 0 - // ^ 1111 0 1 0 1 (bitmask) - // ------ - - - - - // = 1001 1 0 0 1 <- This bit was already cleared. - // \_______\ - // \ - // We can think of these bits having flipped - // because of the presence of 1s in those columns - // of our bitmask. - - print("Toggle pins with XOR on PORTB\n", .{}); - print("-----------------------------\n", .{}); - PORTB = 0b1100; - print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); - print("^ {b:0>4} // (bitmask)\n", .{0b0101}); - PORTB ^= (1 << 1) | (1 << 0); // What's wrong here? - checkAnswer(0b1001, PORTB); - - newline(); - - PORTB = 0b1100; - print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); - print("^ {b:0>4} // (bitmask)\n", .{0b0011}); - PORTB ^= (1 << 1) & (1 << 0); // What's wrong here? - checkAnswer(0b1111, PORTB); - // While the examples in this exercise have used only 4-bit wide variables, // working with 8 bits is no different. Here's a an example where we set // every other bit beginning with the two's place: From 0fa86eb8c8fc76f8f1bb396b83d1d453edd870d1 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:06:23 -0800 Subject: [PATCH 057/118] rearranged order of expected output in build.zig --- build.zig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/build.zig b/build.zig index 9774833..c8f26fd 100644 --- a/build.zig +++ b/build.zig @@ -1209,6 +1209,16 @@ const exercises = [_]Exercise{ , }, .{ .main_file = "110_bit_manipulation3.zig", .output = + \\Toggle pins with XOR on PORTB + \\----------------------------- + \\ 1100 // (initial state of PORTB) + \\^ 0101 // (bitmask) + \\= 1001 + \\ + \\ 1100 // (initial state of PORTB) + \\^ 0011 // (bitmask) + \\= 1111 + \\ \\Set pins with OR on PORTB \\------------------------- \\ 1001 // (initial state of PORTB) @@ -1228,17 +1238,6 @@ const exercises = [_]Exercise{ \\ 0111 // (reset state) \\& 1110 // (bitmask) \\= 0110 - \\ - \\ - \\Toggle pins with XOR on PORTB - \\----------------------------- - \\ 1100 // (initial state of PORTB) - \\^ 0101 // (bitmask) - \\= 1001 - \\ - \\ 1100 // (initial state of PORTB) - \\^ 0011 // (bitmask) - \\= 1111 }, .{ .main_file = "999_the_end.zig", From 502ac8711e29bae3d0d9e4b1489b6e475369f321 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:31:29 -0800 Subject: [PATCH 058/118] added newline between toggle and set sections to make the expected output match --- exercises/110_bit_manipulation3.zig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/110_bit_manipulation3.zig b/exercises/110_bit_manipulation3.zig index baf4045..620df3f 100644 --- a/exercises/110_bit_manipulation3.zig +++ b/exercises/110_bit_manipulation3.zig @@ -119,6 +119,8 @@ pub fn main() !void { PORTB ^= (1 << 1) & (1 << 0); // What's wrong here? checkAnswer(0b1111, PORTB); + newline(); + // Now let's take a look at setting bits with the | operator. // // ------------------------------------------------------------------------ From 4ac1d70f93eeaf6e724823329a3a25585bdf2b24 Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 15:35:14 -0500 Subject: [PATCH 059/118] reset and completed exercise tracking wired in --- build.zig | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/build.zig b/build.zig index e528552..c701efd 100644 --- a/build.zig +++ b/build.zig @@ -162,6 +162,8 @@ pub fn build(b: *Build) !void { const exno: ?usize = b.option(usize, "n", "Select exercise"); const rand: ?bool = b.option(bool, "random", "Select random exercise"); const start: ?usize = b.option(usize, "s", "Start at exercise"); + // flag to reset the exercise progress + const reset: ?bool = b.option(bool, "reset", "Reset exercise progress"); const sep = std.fs.path.sep_str; const healed_path = if (override_healed_path) |path| @@ -242,13 +244,34 @@ pub fn build(b: *Build) !void { return; } + if (reset) |_| { + + const progress_file = ".progress.txt"; + + std.fs.cwd().deleteFile(progress_file) catch |err| { + switch (err) { + std.fs.Dir.DeleteFileError.FileNotFound => {}, + else => { + print("Unable to remove progress file, Error: {}\n", .{err}); + return err; + }, + } + }; + + print("Progress reset, .progress.txt removed.\n", .{}); + std.process.exit(0); + } + // Normal build mode: verifies all exercises according to the recommended // order. const ziglings_step = b.step("ziglings", "Check all ziglings"); b.default_step = ziglings_step; var prev_step = &header_step.step; + // read the file to find the latest complete, use that in the for loop + // for (exercises[(s - 1)..]) |ex| { for (exercises) |ex| { + // print("here {s}\n", .{ex.main_file}); const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); verify_stepn.step.dependOn(prev_step); @@ -403,6 +426,18 @@ const ZiglingStep = struct { , .{ red, reset, exercise_output, red, reset, output, red, reset }); } + const progress = try std.fmt.allocPrint(b.allocator, "{d}", .{self.exercise.number()}); + defer b.allocator.free(progress); + + const file = try std.fs.cwd().createFile( + ".progress.txt", + .{ .read = true, .truncate = true }, + ); + defer file.close(); + + try file.writeAll(progress); + try file.sync(); + print("{s}PASSED:\n{s}{s}\n\n", .{ green_text, output, reset_text }); } From e54b30f3d3a4b05d7eb35f066efd3a00c86a4b4f Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 15:37:01 -0500 Subject: [PATCH 060/118] fmt --- build.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/build.zig b/build.zig index c701efd..ccb16ac 100644 --- a/build.zig +++ b/build.zig @@ -245,7 +245,6 @@ pub fn build(b: *Build) !void { } if (reset) |_| { - const progress_file = ".progress.txt"; std.fs.cwd().deleteFile(progress_file) catch |err| { From 8e6a52d5a6c9d0de356113494390a9d888d8ee1a Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 21:13:33 -0500 Subject: [PATCH 061/118] tracking, skipping and reset all wired in --- build.zig | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index ccb16ac..2bc948b 100644 --- a/build.zig +++ b/build.zig @@ -267,10 +267,33 @@ pub fn build(b: *Build) !void { b.default_step = ziglings_step; var prev_step = &header_step.step; - // read the file to find the latest complete, use that in the for loop - // for (exercises[(s - 1)..]) |ex| { - for (exercises) |ex| { - // print("here {s}\n", .{ex.main_file}); + + var starting_exercise: u32 = 0; + + if (std.fs.cwd().openFile(".progress.txt", .{})) |progress_file| { + defer progress_file.close(); + + const progress_file_size = try progress_file.getEndPos(); + + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + const contents = try progress_file.readToEndAlloc(allocator, progress_file_size); + defer allocator.free(contents); + + starting_exercise = try std.fmt.parseInt(u32, contents, 10); + } else |err| { + switch (err) { + // This is fine, may be the first time tests are run or progress have been reset + std.fs.File.OpenError.FileNotFound => {}, + else => { + print("Unable to open progress file, Error: {}\n", .{err}); + return err; + }, + } + } + + for (exercises[starting_exercise..]) |ex| { const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); verify_stepn.step.dependOn(prev_step); From 0903c5927b58f0ca166ee86c458de44fcf4234d6 Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 21:14:41 -0500 Subject: [PATCH 062/118] cleanup for PR --- build.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/build.zig b/build.zig index 2bc948b..40a2d47 100644 --- a/build.zig +++ b/build.zig @@ -162,7 +162,6 @@ pub fn build(b: *Build) !void { const exno: ?usize = b.option(usize, "n", "Select exercise"); const rand: ?bool = b.option(bool, "random", "Select random exercise"); const start: ?usize = b.option(usize, "s", "Start at exercise"); - // flag to reset the exercise progress const reset: ?bool = b.option(bool, "reset", "Reset exercise progress"); const sep = std.fs.path.sep_str; From 92c723536242b31ecf222ec1f00586ebf46ea994 Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 21:29:46 -0500 Subject: [PATCH 063/118] cleanup for PR --- build.zig | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/build.zig b/build.zig index 40a2d47..335a415 100644 --- a/build.zig +++ b/build.zig @@ -120,6 +120,8 @@ pub const logo = \\ ; +const progress_filename = ".progress.txt"; + pub fn build(b: *Build) !void { if (!validate_exercises()) std.process.exit(2); @@ -244,9 +246,7 @@ pub fn build(b: *Build) !void { } if (reset) |_| { - const progress_file = ".progress.txt"; - - std.fs.cwd().deleteFile(progress_file) catch |err| { + std.fs.cwd().deleteFile(progress_filename) catch |err| { switch (err) { std.fs.Dir.DeleteFileError.FileNotFound => {}, else => { @@ -256,7 +256,7 @@ pub fn build(b: *Build) !void { } }; - print("Progress reset, .progress.txt removed.\n", .{}); + print("Progress reset, {s} removed.\n", .{progress_filename}); std.process.exit(0); } @@ -269,7 +269,7 @@ pub fn build(b: *Build) !void { var starting_exercise: u32 = 0; - if (std.fs.cwd().openFile(".progress.txt", .{})) |progress_file| { + if (std.fs.cwd().openFile(progress_filename, .{})) |progress_file| { defer progress_file.close(); const progress_file_size = try progress_file.getEndPos(); @@ -283,10 +283,12 @@ pub fn build(b: *Build) !void { starting_exercise = try std.fmt.parseInt(u32, contents, 10); } else |err| { switch (err) { - // This is fine, may be the first time tests are run or progress have been reset - std.fs.File.OpenError.FileNotFound => {}, + + std.fs.File.OpenError.FileNotFound => { + // This is fine, may be the first time tests are run or progress have been reset + }, else => { - print("Unable to open progress file, Error: {}\n", .{err}); + print("Unable to open {s}: {}\n", .{progress_filename, err}); return err; }, } @@ -451,7 +453,7 @@ const ZiglingStep = struct { defer b.allocator.free(progress); const file = try std.fs.cwd().createFile( - ".progress.txt", + progress_filename, .{ .read = true, .truncate = true }, ); defer file.close(); From e09c11a16a12dde4f88b4abbd867626008734a23 Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 21:29:56 -0500 Subject: [PATCH 064/118] cleanup for PR --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index f478944..c884f21 100644 --- a/README.md +++ b/README.md @@ -173,6 +173,11 @@ zig build -Dn=19 -l ... ``` +To reset the progress (have it run all the exercises that have already been completed): +``` +zig build -Dreset +``` + ## What's Covered The primary goal for Ziglings is to cover the core Zig language. From a9487c246fc35346bc4646af28341a2bb6a83209 Mon Sep 17 00:00:00 2001 From: Zendril Date: Tue, 4 Feb 2025 22:24:52 -0500 Subject: [PATCH 065/118] cleanup for PR --- build.zig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index 335a415..fd72881 100644 --- a/build.zig +++ b/build.zig @@ -294,11 +294,13 @@ pub fn build(b: *Build) !void { } } - for (exercises[starting_exercise..]) |ex| { - const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); - verify_stepn.step.dependOn(prev_step); + for (exercises) |ex| { + if (starting_exercise < ex.number()) { + const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal); + verify_stepn.step.dependOn(prev_step); - prev_step = &verify_stepn.step; + prev_step = &verify_stepn.step; + } } ziglings_step.dependOn(prev_step); From 596d5e50cadac66bff0d635c38f3993643302adc Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Sat, 8 Feb 2025 10:07:59 -0800 Subject: [PATCH 066/118] format fix --- exercises/110_bit_manipulation3.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/exercises/110_bit_manipulation3.zig b/exercises/110_bit_manipulation3.zig index 620df3f..4ac2032 100644 --- a/exercises/110_bit_manipulation3.zig +++ b/exercises/110_bit_manipulation3.zig @@ -89,7 +89,7 @@ pub fn main() !void { // corresponding bits in the other operand to flip to the opposite value. // - 0s cause no change. // - // The 0s in our bitmask preserve these values + // The 0s in our bitmask preserve these values // -XOR op- ---expanded--- in the output. // _______________/ // / / @@ -452,4 +452,3 @@ fn checkAnswer(expected: u4, answer: u4) void { } newline(); } - From 1478d41801e6385efb5bf3a1acb12d71ad38eb8d Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Sat, 8 Feb 2025 13:15:48 -0800 Subject: [PATCH 067/118] added patch file for exercise 110 --- patches/patches/110_bit_manipulation3.patch | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 patches/patches/110_bit_manipulation3.patch diff --git a/patches/patches/110_bit_manipulation3.patch b/patches/patches/110_bit_manipulation3.patch new file mode 100644 index 0000000..9c64336 --- /dev/null +++ b/patches/patches/110_bit_manipulation3.patch @@ -0,0 +1,56 @@ +--- exercises/110_bit_manipulation3.zig 2025-02-08 11:52:35.609300707 -0800 ++++ answers/110_bit_manipulation3.zig 2025-02-08 13:00:15.414038314 -0800 +@@ -108,7 +108,7 @@ + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0101}); +- PORTB ^= (1 << 1) | (1 << 0); // What's wrong here? ++ PORTB ^= (1 << 2) | (1 << 0); + checkAnswer(0b1001, PORTB); + + newline(); +@@ -116,7 +116,7 @@ + PORTB = 0b1100; + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("^ {b:0>4} // (bitmask)\n", .{0b0011}); +- PORTB ^= (1 << 1) & (1 << 0); // What's wrong here? ++ PORTB ^= (1 << 1) | (1 << 0); + checkAnswer(0b1111, PORTB); + + newline(); +@@ -170,7 +170,7 @@ + PORTB = 0b1001; // reset PORTB + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("| {b:0>4} // (bitmask)\n", .{0b0100}); +- PORTB = PORTB ??? (1 << 2); // What's missing here? ++ PORTB = PORTB | (1 << 2); + checkAnswer(0b1101, PORTB); + + newline(); +@@ -178,7 +178,7 @@ + PORTB = 0b1001; // reset PORTB + print(" {b:0>4} // (reset state)\n", .{PORTB}); + print("| {b:0>4} // (bitmask)\n", .{0b0100}); +- PORTB ??? (1 << 2); // What's missing here? ++ PORTB |= (1 << 2); + checkAnswer(0b1101, PORTB); + + newline(); +@@ -269,7 +269,7 @@ + PORTB = 0b1110; // reset PORTB + print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); + print("& {b:0>4} // (bitmask)\n", .{0b1011}); +- PORTB = PORTB & ???@as(u4, 1 << 2); // What character is missing here? ++ PORTB = PORTB & ~@as(u4, 1 << 2); + checkAnswer(0b1010, PORTB); + + newline(); +@@ -277,7 +277,7 @@ + PORTB = 0b0111; // reset PORTB + print(" {b:0>4} // (reset state)\n", .{PORTB}); + print("& {b:0>4} // (bitmask)\n", .{0b1110}); +- PORTB &= ~(1 << 0); // What's missing here? ++ PORTB &= ~@as(u4, 1 << 0); + checkAnswer(0b0110, PORTB); + + newline(); From b38d70002a36f684698a4e54f8fcf4fa1b56a2d4 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 9 Feb 2025 16:34:56 +0100 Subject: [PATCH 068/118] Skip 74, the compiler corrects this now. --- build.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/build.zig b/build.zig index e528552..858e43d 100644 --- a/build.zig +++ b/build.zig @@ -970,6 +970,7 @@ const exercises = [_]Exercise{ .{ .main_file = "074_comptime9.zig", .output = "My llama value is 2.", + .skip = true, }, .{ .main_file = "075_quiz8.zig", From c02e6ead16eb05fddc5f890fa96226857e42d67e Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 9 Feb 2025 21:31:07 +0100 Subject: [PATCH 069/118] Added deletion of progress.txt for eowyn --- .gitignore | 1 + patches/eowyn.sh | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index 53a6184..0fa4230 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /answers/ /patches/healed/ /output/ +.progress.txt # Leave this in here for older zig versions /zig-cache/ diff --git a/patches/eowyn.sh b/patches/eowyn.sh index 8cac450..4eb35b6 100755 --- a/patches/eowyn.sh +++ b/patches/eowyn.sh @@ -26,6 +26,13 @@ echo "Zig version" $(zig version) echo "Eowyn version 23.10.5.1, let's try our magic power." echo "" +# Remove progress file +progress_file=".progress.txt" +if [ -f $progress_file ]; then + rm $progress_file +fi + + # Create directory of healing if it doesn't already exist. mkdir -p patches/healed From c1777f47d5478cde0f08dafc6937b0f38464d787 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Sun, 9 Feb 2025 21:42:31 +0100 Subject: [PATCH 070/118] Added delte_progress additional to the end of eowyn --- patches/eowyn.sh | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/patches/eowyn.sh b/patches/eowyn.sh index 4eb35b6..afc2732 100755 --- a/patches/eowyn.sh +++ b/patches/eowyn.sh @@ -12,6 +12,12 @@ # using the patches in this directory and convey them # to convalesce in the healed directory. # +delete_progress() { + progress_file=".progress.txt" + if [ -f $progress_file ]; then + rm $progress_file + fi +} set -e # We check ourselves before we wreck ourselves. @@ -23,15 +29,11 @@ fi # Which version we have? echo "Zig version" $(zig version) -echo "Eowyn version 23.10.5.1, let's try our magic power." +echo "Eowyn version 25.1.9, let's try our magic power." echo "" # Remove progress file -progress_file=".progress.txt" -if [ -f $progress_file ]; then - rm $progress_file -fi - +delete_progress # Create directory of healing if it doesn't already exist. mkdir -p patches/healed @@ -61,3 +63,6 @@ zig fmt --check patches/healed # Test the healed exercises. May the compiler have mercy upon us. zig build -Dhealed + +# Remove progress file again +delete_progress From d75f49b25b40ef049d2e55ba515b47bc73253400 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 10 Feb 2025 10:50:57 +0100 Subject: [PATCH 071/118] Fix repo link --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f478944..db63593 100644 --- a/README.md +++ b/README.md @@ -51,14 +51,14 @@ $ zig version Clone this repository with Git: ``` -$ git clone https://ziglings.org -$ cd ziglings.org +git clone https://codeberg.org/ziglings/exercises.git ziglings +cd ziglings ``` Then run `zig build` and follow the instructions to begin! ``` -$ zig build +zig build ``` Note: The output of Ziglings is the unaltered output from the Zig From 20596bc290404a56b2f23e2d95aa35137239e06f Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Mon, 10 Feb 2025 16:59:48 -0800 Subject: [PATCH 072/118] converted 110 to a quiz (quiz 9) --- build.zig | 2 +- exercises/{110_bit_manipulation3.zig => 110_quiz9.zig} | 0 .../patches/{110_bit_manipulation3.patch => 110_quiz9.patch} | 4 ++-- 3 files changed, 3 insertions(+), 3 deletions(-) rename exercises/{110_bit_manipulation3.zig => 110_quiz9.zig} (100%) rename patches/patches/{110_bit_manipulation3.patch => 110_quiz9.patch} (92%) diff --git a/build.zig b/build.zig index 3b753ee..25d831c 100644 --- a/build.zig +++ b/build.zig @@ -1269,7 +1269,7 @@ const exercises = [_]Exercise{ \\Max difference (new fn): 0.014 , }, - .{ .main_file = "110_bit_manipulation3.zig", .output = + .{ .main_file = "110_quiz9.zig", .output = \\Toggle pins with XOR on PORTB \\----------------------------- \\ 1100 // (initial state of PORTB) diff --git a/exercises/110_bit_manipulation3.zig b/exercises/110_quiz9.zig similarity index 100% rename from exercises/110_bit_manipulation3.zig rename to exercises/110_quiz9.zig diff --git a/patches/patches/110_bit_manipulation3.patch b/patches/patches/110_quiz9.patch similarity index 92% rename from patches/patches/110_bit_manipulation3.patch rename to patches/patches/110_quiz9.patch index 9c64336..9d9b864 100644 --- a/patches/patches/110_bit_manipulation3.patch +++ b/patches/patches/110_quiz9.patch @@ -1,5 +1,5 @@ ---- exercises/110_bit_manipulation3.zig 2025-02-08 11:52:35.609300707 -0800 -+++ answers/110_bit_manipulation3.zig 2025-02-08 13:00:15.414038314 -0800 +--- exercises/110_quiz9.zig 2025-02-08 13:19:48.522641785 -0800 ++++ answers/110_quiz9.zig 2025-02-10 17:42:04.525004335 -0800 @@ -108,7 +108,7 @@ PORTB = 0b1100; print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB}); From a7cd808bb8bdcb4e191c7bcbb427953a0461eac4 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:56:57 -0800 Subject: [PATCH 073/118] moved explanatory content below the broken code in main so that the exercise functions more like a quiz --- exercises/110_quiz9.zig | 419 ++++++++++++++++++++++------------------ 1 file changed, 236 insertions(+), 183 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 4ac2032..171a509 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -68,40 +68,31 @@ const testing = std.testing; pub fn main() !void { var PORTB: u4 = 0b0000; // only 4 bits wide for simplicity + + // The LCD display on our robot is not behaving as expected. In order to + // get it functioning properly, we must initialize it by sending the + // correct sequence of half-bytes to PORTB's lower four pins. // - // Let's first take a look at toggling bits. + // See if you can solve the following problems to get the lcd working and + // reveal the message our robot has stored in his EEPROM. // - // ------------------------------------------------------------------------ - // Toggling bits with XOR: - // ------------------------------------------------------------------------ - // XOR stands for "exclusive or". We can toggle bits with the ^ (XOR) - // bitwise operator, like so: + // .--. .--. + // | | | | + // +--------------------------+ + // | +----------------------+ | + // | | | | + // | | XXXXXXXX XXXXXXXX | | <-- LCD + // | | | | + // | +----------------------+ | + // | _________ | + // | |_|_|_|_|_| | + // | | + // +--------------------------+ + // | | // - // - // In order to output a 1, the logic of an XOR operation requires that the - // two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will - // both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior - // of outputing a 0 when both inputs are 1s is what makes it different from - // the OR operator; it also gives us the ability to toggle bits by putting - // 1s into our bitmask. - // - // - 1s in our bitmask operand, can be thought of as causing the - // corresponding bits in the other operand to flip to the opposite value. - // - 0s cause no change. - // - // The 0s in our bitmask preserve these values - // -XOR op- ---expanded--- in the output. - // _______________/ - // / / - // 0110 1 1 0 0 - // ^ 1111 0 1 0 1 (bitmask) - // ------ - - - - - // = 1001 1 0 0 1 <- This bit was already cleared. - // \_______\ - // \ - // We can think of these bits having flipped - // because of the presence of 1s in those columns - // of our bitmask. + // The last two problems throw you a bit of a curve ball. Try solving them + // on your own. If you need help, scroll to the bottom to see some in depth + // explanations on toggling, setting, and clearing bits in Zig. print("Toggle pins with XOR on PORTB\n", .{}); print("-----------------------------\n", .{}); @@ -121,49 +112,6 @@ pub fn main() !void { newline(); - // Now let's take a look at setting bits with the | operator. - // - // ------------------------------------------------------------------------ - // Setting bits with OR: - // ------------------------------------------------------------------------ - // We can set bits on PORTB with the | (OR) operator, like so: - // - // var PORTB: u4 = 0b1001; - // PORTB = PORTB | 0b0010; - // print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 - // - // -OR op- ---expanded--- - // _ Set only this bit. - // / - // 1001 1 0 0 1 - // | 0010 0 0 1 0 (bit mask) - // ------ - - - - - // = 1011 1 0 1 1 - // \___\_______\ - // \ - // These bits remain untouched because OR-ing with - // a 0 effects no change. - // - // ------------------------------------------------------------------------ - // To create a bit mask like 0b0010 used above: - // - // 1. First, shift the value 1 over one place with the bitwise << (shift - // left) operator as indicated below: - // 1 << 0 -> 0001 - // 1 << 1 -> 0010 <-- Shift 1 one place to the left - // 1 << 2 -> 0100 - // 1 << 3 -> 1000 - // - // This allows us to rewrite the above code like this: - // - // var PORTB: u4 = 0b1001; - // PORTB = PORTB | (1 << 1); - // print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 - // - // Finally, as in the C language, Zig allows us to use the |= operator, so - // we can rewrite our code again in an even more compact and idiomatic - // form: PORTB |= (1 << 1) - print("Set pins with OR on PORTB\n", .{}); print("-------------------------\n", .{}); @@ -183,86 +131,6 @@ pub fn main() !void { newline(); - // So now we've covered how to toggle and set bits. What about clearing - // them? Well, this is where Zig throws us a curve ball. Don't worry we'll - // go through it step by step. - - // ------------------------------------------------------------------------ - // Clearing bits with AND and NOT: - // ------------------------------------------------------------------------ - // We can clear bits with the & (AND) bitwise operator, like so: - - // PORTB = 0b1110; // reset PORTB - // PORTB = PORTB & 0b1011; - // print("PORTB: {b:0>4}\n", .{PORTB}); // output -> 1010 - // - // - 0s clear bits when used in conjuction with a bitwise AND. - // - 1s do nothing, thus preserving the original bits. - // - // -AND op- ---expanded--- - // __________ Clear only this bit. - // / - // 1110 1 1 1 0 - // & 1011 1 0 1 1 (bit mask) - // ------ - - - - - // = 1010 1 0 1 0 <- This bit was already cleared. - // \_______\ - // \ - // These bits remain untouched because AND-ing with a - // 1 preserves the original bit value whether 0 or 1. - // - // ------------------------------------------------------------------------ - // We can use the ~ (NOT) operator to easily create a bit mask like 1011: - // - // 1. First, shift the value 1 over two places with the bit-wise << (shift - // left) operator as indicated below: - // 1 << 0 -> 0001 - // 1 << 1 -> 0010 - // 1 << 2 -> 0100 <- The 1 has been shifted two places to the left - // 1 << 3 -> 1000 - // - // 2. The second step in creating our bit mask is to invert the bits - // ~0100 -> 1011 - // in C we would write this as: - // ~(1 << 2) -> 1011 - // - // But if we try to compile ~(1 << 2) in Zig, we'll get an error: - // unable to perform binary not operation on type 'comptime_int' - // - // Before Zig can invert our bits, it needs to know the number of - // bits it's being asked to invert. - // - // We do this with the @as (cast as) built-in like this: - // @as(u4, 1 << 2) -> 0100 - // - // Finally, we can invert our new mask by placing the NOT ~ operator - // before our expression, like this: - // ~@as(u4, 1 << 2) -> 1011 - // - // If you are offput by the fact that you can't simply invert bits like - // you can in languages such as C without casting to a particular size - // of integer, you're not alone. However, this is actually another - // instance where Zig is really helpful because it protects you from - // difficult to debug integer overflow bugs that can have you tearing - // your hair out. In the interest of keeping things sane, Zig requires - // you simply to tell it the size of number you are inverting. In the - // words of Andrew Kelley, "If you want to invert the bits of an - // integer, zig has to know how many bits there are." - // - // For more insight into the Zig team's position on why the language - // takes the approach it does with the ~ operator, take a look at - // Andrew's comments on the following github issue: - // https://github.com/ziglang/zig/issues/1382#issuecomment-414459529 - // - // Whew, so after all that what we end up with is: - // PORTB = PORTB & ~@as(u4, 1 << 2); - // - // We can shorten this with the &= combined AND and assignment operator, - // which applies the AND operator on PORTB and then reassigns PORTB. Here's - // what that looks like: - // PORTB &= ~@as(u4, 1 << 2); - // - print("Clear pins with AND and NOT on PORTB\n", .{}); print("------------------------------------\n", .{}); @@ -283,37 +151,222 @@ pub fn main() !void { newline(); newline(); - // ------------------------------------------------------------------------ - // Conclusion - // ------------------------------------------------------------------------ - // - // While the examples in this exercise have used only 4-bit wide variables, - // working with 8 bits is no different. Here's a an example where we set - // every other bit beginning with the two's place: - - // var PORTD: u8 = 0b0000_0000; - // print("PORTD: {b:0>8}\n", .{PORTD}); - // PORTD |= (1 << 1); - // PORTD = setBit(u8, PORTD, 3); - // PORTD |= (1 << 5) | (1 << 7); - // print("PORTD: {b:0>8} // set every other bit\n", .{PORTD}); - // PORTD = ~PORTD; - // print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); - // newline(); - // - // // Here we clear every other bit beginning with the two's place. - // - // PORTD = 0b1111_1111; - // print("PORTD: {b:0>8}\n", .{PORTD}); - // PORTD &= ~@as(u8, 1 << 1); - // PORTD = clearBit(u8, PORTD, 3); - // PORTD &= ~@as(u8, (1 << 5) | (1 << 7)); - // print("PORTD: {b:0>8} // clear every other bit\n", .{PORTD}); - // PORTD = ~PORTD; - // print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); - // newline(); } + +// ************************************************************************ +// IN-DEPTH EXPLANATIONS BELOW +// ************************************************************************ + + + + + + + + + + + + +// ------------------------------------------------------------------------ +// Toggling bits with XOR: +// ------------------------------------------------------------------------ +// XOR stands for "exclusive or". We can toggle bits with the ^ (XOR) +// bitwise operator, like so: +// +// +// In order to output a 1, the logic of an XOR operation requires that the +// two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will +// both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior +// of outputing a 0 when both inputs are 1s is what makes it different from +// the OR operator; it also gives us the ability to toggle bits by putting +// 1s into our bitmask. +// +// - 1s in our bitmask operand, can be thought of as causing the +// corresponding bits in the other operand to flip to the opposite value. +// - 0s cause no change. +// +// The 0s in our bitmask preserve these values +// -XOR op- ---expanded--- in the output. +// _______________/ +// / / +// 0110 1 1 0 0 +// ^ 1111 0 1 0 1 (bitmask) +// ------ - - - - +// = 1001 1 0 0 1 <- This bit was already cleared. +// \_______\ +// \ +// We can think of these bits having flipped +// because of the presence of 1s in those columns +// of our bitmask. +// +// Now let's take a look at setting bits with the | operator. +// + + + + + + +// ------------------------------------------------------------------------ +// Setting bits with OR: +// ------------------------------------------------------------------------ +// We can set bits on PORTB with the | (OR) operator, like so: +// +// var PORTB: u4 = 0b1001; +// PORTB = PORTB | 0b0010; +// print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 +// +// -OR op- ---expanded--- +// _ Set only this bit. +// / +// 1001 1 0 0 1 +// | 0010 0 0 1 0 (bit mask) +// ------ - - - - +// = 1011 1 0 1 1 +// \___\_______\ +// \ +// These bits remain untouched because OR-ing with +// a 0 effects no change. +// +// ------------------------------------------------------------------------ +// To create a bit mask like 0b0010 used above: +// +// 1. First, shift the value 1 over one place with the bitwise << (shift +// left) operator as indicated below: +// 1 << 0 -> 0001 +// 1 << 1 -> 0010 <-- Shift 1 one place to the left +// 1 << 2 -> 0100 +// 1 << 3 -> 1000 +// +// This allows us to rewrite the above code like this: +// +// var PORTB: u4 = 0b1001; +// PORTB = PORTB | (1 << 1); +// print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011 +// +// Finally, as in the C language, Zig allows us to use the |= operator, so +// we can rewrite our code again in an even more compact and idiomatic +// form: PORTB |= (1 << 1) + +// So now we've covered how to toggle and set bits. What about clearing +// them? Well, this is where Zig throws us a curve ball. Don't worry we'll +// go through it step by step. + + + + + + +// ------------------------------------------------------------------------ +// Clearing bits with AND and NOT: +// ------------------------------------------------------------------------ +// We can clear bits with the & (AND) bitwise operator, like so: + +// PORTB = 0b1110; // reset PORTB +// PORTB = PORTB & 0b1011; +// print("PORTB: {b:0>4}\n", .{PORTB}); // output -> 1010 +// +// - 0s clear bits when used in conjuction with a bitwise AND. +// - 1s do nothing, thus preserving the original bits. +// +// -AND op- ---expanded--- +// __________ Clear only this bit. +// / +// 1110 1 1 1 0 +// & 1011 1 0 1 1 (bit mask) +// ------ - - - - +// = 1010 1 0 1 0 <- This bit was already cleared. +// \_______\ +// \ +// These bits remain untouched because AND-ing with a +// 1 preserves the original bit value whether 0 or 1. +// +// ------------------------------------------------------------------------ +// We can use the ~ (NOT) operator to easily create a bit mask like 1011: +// +// 1. First, shift the value 1 over two places with the bit-wise << (shift +// left) operator as indicated below: +// 1 << 0 -> 0001 +// 1 << 1 -> 0010 +// 1 << 2 -> 0100 <- The 1 has been shifted two places to the left +// 1 << 3 -> 1000 +// +// 2. The second step in creating our bit mask is to invert the bits +// ~0100 -> 1011 +// in C we would write this as: +// ~(1 << 2) -> 1011 +// +// But if we try to compile ~(1 << 2) in Zig, we'll get an error: +// unable to perform binary not operation on type 'comptime_int' +// +// Before Zig can invert our bits, it needs to know the number of +// bits it's being asked to invert. +// +// We do this with the @as (cast as) built-in like this: +// @as(u4, 1 << 2) -> 0100 +// +// Finally, we can invert our new mask by placing the NOT ~ operator +// before our expression, like this: +// ~@as(u4, 1 << 2) -> 1011 +// +// If you are offput by the fact that you can't simply invert bits like +// you can in languages such as C without casting to a particular size +// of integer, you're not alone. However, this is actually another +// instance where Zig is really helpful because it protects you from +// difficult to debug integer overflow bugs that can have you tearing +// your hair out. In the interest of keeping things sane, Zig requires +// you simply to tell it the size of number you are inverting. In the +// words of Andrew Kelley, "If you want to invert the bits of an +// integer, zig has to know how many bits there are." +// +// For more insight into the Zig team's position on why the language +// takes the approach it does with the ~ operator, take a look at +// Andrew's comments on the following github issue: +// https://github.com/ziglang/zig/issues/1382#issuecomment-414459529 +// +// Whew, so after all that what we end up with is: +// PORTB = PORTB & ~@as(u4, 1 << 2); +// +// We can shorten this with the &= combined AND and assignment operator, +// which applies the AND operator on PORTB and then reassigns PORTB. Here's +// what that looks like: +// PORTB &= ~@as(u4, 1 << 2); +// + +// ------------------------------------------------------------------------ +// Conclusion +// ------------------------------------------------------------------------ +// +// While the examples in this quiz have used only 4-bit wide variables, +// working with 8 bits is no different. Here's a an example where we set +// every other bit beginning with the two's place: + +// var PORTD: u8 = 0b0000_0000; +// print("PORTD: {b:0>8}\n", .{PORTD}); +// PORTD |= (1 << 1); +// PORTD = setBit(u8, PORTD, 3); +// PORTD |= (1 << 5) | (1 << 7); +// print("PORTD: {b:0>8} // set every other bit\n", .{PORTD}); +// PORTD = ~PORTD; +// print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); +// newline(); +// +// // Here we clear every other bit beginning with the two's place. +// +// PORTD = 0b1111_1111; +// print("PORTD: {b:0>8}\n", .{PORTD}); +// PORTD &= ~@as(u8, 1 << 1); +// PORTD = clearBit(u8, PORTD, 3); +// PORTD &= ~@as(u8, (1 << 5) | (1 << 7)); +// print("PORTD: {b:0>8} // clear every other bit\n", .{PORTD}); +// PORTD = ~PORTD; +// print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); +// newline(); + + + // ---------------------------------------------------------------------------- // Here are some helper functions for manipulating bits // ---------------------------------------------------------------------------- From 465536baf00d07cf9ec5b6232dc3f48eea164cb0 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 13:45:51 -0800 Subject: [PATCH 074/118] made some simple changes to the wording to reflect the fact that this is a quiz --- exercises/110_quiz9.zig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 171a509..734b9dc 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -1,20 +1,20 @@ // ---------------------------------------------------------------------------- -// Toggling, Setting, and Clearing Bits +// Quiz Time: Toggling, Setting, and Clearing Bits // ---------------------------------------------------------------------------- // // Another exciting thing about Zig is its suitability for embedded // programming. Your Zig code doesn't have to remain on your laptop. You can // also deploy your code to microcontrollers! This means you can write Zig to // drive your next robot or greenhouse climate control system! Ready to enter -// the exciting world of embedded programming? This exercise is designed to -// give you a taste of what it's like to control registers in a -// microcontroller. Let's get started! +// the exciting world of embedded programming? This quiz is designed to test +// your knowledge of bit manipulationh in Zig while also giving you a taste of +// what it's like to control registers in a microcontroller. Let's get started! // // A common activity in microcontroller programming is setting and clearing // bits on input and output pins. This lets you control LEDs, sensors, motors // and more! In a previous exercise (097_bit_manipulation.zig) you learned how // to swap two bytes using the ^ (XOR - exclusive or) operator. In this -// exercise, we'll take a closer look at bit manipulation and how we can write +// quiz, we'll take a closer look at bit manipulation and how we can write // code that sets and clears specific bits as we would if we were programming // the pins on a real microcontroller. Included at the end of this exercise are // some helper functions that demonstrate how we might make our code a little @@ -47,8 +47,8 @@ // PORTB // // Drawing inspiration from this diagram, we'll use the pins for PORTB as our -// mental model for this exercise in bit manipulation. It should be noted that -// in the following examples we are using ordinary variables, one of which we +// mental model for this quiz on bit manipulation. It should be noted that +// in the following problems we are using ordinary variables, one of which we // have named PORTB, to simulate modifying the bits of real hardware registers. // But in actual microcontroller code, PORTB would be defined something like // this: @@ -57,7 +57,7 @@ // This lets the compiler know not to make any optimizations to PORTB so that // the IO pins are properly mapped to our code. // -// NOTE : To keep things simple, the following examples are given using type +// NOTE : To keep things simple, the following problems are given using type // u4, so applying the output to PORTB would only affect the lower four pins // PB0..PB3. Of course, there is nothing to prevent you from swapping the u4 // with a u8 so you can control all 8 of PORTB's IO pins. From 6fbf81d929273b16136afdfccb6ddbe592eb29ac Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:07:51 -0800 Subject: [PATCH 075/118] edited the first two paragraphs --- exercises/110_quiz9.zig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 734b9dc..2db3230 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -3,22 +3,23 @@ // ---------------------------------------------------------------------------- // // Another exciting thing about Zig is its suitability for embedded -// programming. Your Zig code doesn't have to remain on your laptop. You can +// programming. Your Zig code doesn't have to remain on your laptop; you can // also deploy your code to microcontrollers! This means you can write Zig to // drive your next robot or greenhouse climate control system! Ready to enter -// the exciting world of embedded programming? This quiz is designed to test -// your knowledge of bit manipulationh in Zig while also giving you a taste of -// what it's like to control registers in a microcontroller. Let's get started! +// the exciting world of embedded programming? Let's get started! +// +// ---------------------------------------------------------------------------- +// Some Background +// ---------------------------------------------------------------------------- // // A common activity in microcontroller programming is setting and clearing // bits on input and output pins. This lets you control LEDs, sensors, motors // and more! In a previous exercise (097_bit_manipulation.zig) you learned how -// to swap two bytes using the ^ (XOR - exclusive or) operator. In this -// quiz, we'll take a closer look at bit manipulation and how we can write -// code that sets and clears specific bits as we would if we were programming -// the pins on a real microcontroller. Included at the end of this exercise are -// some helper functions that demonstrate how we might make our code a little -// more readable. +// to swap two bytes using the ^ (XOR - exclusive or) operator. This quiz will +// test your knowledge of bit manipulationh in Zig while giving you a taste of +// what it's like to control registers in a real microcontroller. Included at +// the end are some helper functions that demonstrate how we might make our +// code a little more readable. // // Below is a pinout diagram for the famous ATmega328 AVR microcontroller used // as the primary microchip on popular microcontroller platforms like the From b7b3297d067416f0e44b285fdd8d7347165bf6c4 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:11:55 -0800 Subject: [PATCH 076/118] added blank lines between sections to make them easier to find --- exercises/110_quiz9.zig | 44 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 2db3230..4412150 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -158,18 +158,17 @@ pub fn main() !void { // ************************************************************************ // IN-DEPTH EXPLANATIONS BELOW // ************************************************************************ - - - - - - - - - - - - +// +// +// +// +// +// +// +// +// +// +// // ------------------------------------------------------------------------ // Toggling bits with XOR: // ------------------------------------------------------------------------ @@ -204,12 +203,10 @@ pub fn main() !void { // // Now let's take a look at setting bits with the | operator. // - - - - - - +// +// +// +// // ------------------------------------------------------------------------ // Setting bits with OR: // ------------------------------------------------------------------------ @@ -254,12 +251,11 @@ pub fn main() !void { // So now we've covered how to toggle and set bits. What about clearing // them? Well, this is where Zig throws us a curve ball. Don't worry we'll // go through it step by step. - - - - - - +// +// +// +// +// // ------------------------------------------------------------------------ // Clearing bits with AND and NOT: // ------------------------------------------------------------------------ From f7e8d4c44435251aaef9f409d5492895a955ce67 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:13:25 -0800 Subject: [PATCH 077/118] added header for quiz problems --- exercises/110_quiz9.zig | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 4412150..9036c04 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -70,30 +70,14 @@ const testing = std.testing; pub fn main() !void { var PORTB: u4 = 0b0000; // only 4 bits wide for simplicity - // The LCD display on our robot is not behaving as expected. In order to - // get it functioning properly, we must initialize it by sending the - // correct sequence of half-bytes to PORTB's lower four pins. - // - // See if you can solve the following problems to get the lcd working and - // reveal the message our robot has stored in his EEPROM. - // - // .--. .--. - // | | | | - // +--------------------------+ - // | +----------------------+ | - // | | | | - // | | XXXXXXXX XXXXXXXX | | <-- LCD - // | | | | - // | +----------------------+ | - // | _________ | - // | |_|_|_|_|_| | - // | | - // +--------------------------+ - // | | - // - // The last two problems throw you a bit of a curve ball. Try solving them - // on your own. If you need help, scroll to the bottom to see some in depth - // explanations on toggling, setting, and clearing bits in Zig. + // ------------------------------------------------------------------------ + // Quiz + // ------------------------------------------------------------------------ + + // See if you can solve the following problems. The last two problems throw + // you a bit of a curve ball. Try solving them on your own. If you need + // help, scroll to the bottom of main to see some in depth explanations on + // toggling, setting, and clearing bits in Zig. print("Toggle pins with XOR on PORTB\n", .{}); print("-----------------------------\n", .{}); From 2437edd51f58dcf6d5e8d4bdeb4e04be9a74c0b3 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:21:26 -0800 Subject: [PATCH 078/118] fixed incorrect bitmask in xor example --- exercises/110_quiz9.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 9036c04..d4f0478 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -175,8 +175,8 @@ pub fn main() !void { // -XOR op- ---expanded--- in the output. // _______________/ // / / -// 0110 1 1 0 0 -// ^ 1111 0 1 0 1 (bitmask) +// 1100 1 1 0 0 +// ^ 0101 0 1 0 1 (bitmask) // ------ - - - - // = 1001 1 0 0 1 <- This bit was already cleared. // \_______\ From 8384d4d9bf8be2d4a5ba55d90e5e633356134fa0 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:59:29 -0800 Subject: [PATCH 079/118] fixed minor spelling and grammar typos --- exercises/110_quiz9.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index d4f0478..89881b1 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -16,7 +16,7 @@ // bits on input and output pins. This lets you control LEDs, sensors, motors // and more! In a previous exercise (097_bit_manipulation.zig) you learned how // to swap two bytes using the ^ (XOR - exclusive or) operator. This quiz will -// test your knowledge of bit manipulationh in Zig while giving you a taste of +// test your knowledge of bit manipulation in Zig while giving you a taste of // what it's like to control registers in a real microcontroller. Included at // the end are some helper functions that demonstrate how we might make our // code a little more readable. @@ -321,7 +321,7 @@ pub fn main() !void { // ------------------------------------------------------------------------ // // While the examples in this quiz have used only 4-bit wide variables, -// working with 8 bits is no different. Here's a an example where we set +// working with 8 bits is no different. Here's an example where we set // every other bit beginning with the two's place: // var PORTD: u8 = 0b0000_0000; From 90e90c997e912ca4e5c50806dd5ab259e727ed40 Mon Sep 17 00:00:00 2001 From: Alexander Sisco <36649949+devspeare@users.noreply.github.com> Date: Thu, 13 Feb 2025 12:45:46 -0800 Subject: [PATCH 080/118] fixed formatting --- exercises/110_quiz9.zig | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 89881b1..540c6e4 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -7,7 +7,7 @@ // also deploy your code to microcontrollers! This means you can write Zig to // drive your next robot or greenhouse climate control system! Ready to enter // the exciting world of embedded programming? Let's get started! -// +// // ---------------------------------------------------------------------------- // Some Background // ---------------------------------------------------------------------------- @@ -135,10 +135,8 @@ pub fn main() !void { newline(); newline(); - } - // ************************************************************************ // IN-DEPTH EXPLANATIONS BELOW // ************************************************************************ @@ -346,8 +344,6 @@ pub fn main() !void { // print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD}); // newline(); - - // ---------------------------------------------------------------------------- // Here are some helper functions for manipulating bits // ---------------------------------------------------------------------------- From cd94f6023cd93d448f0b6eea0eea7f0a61980147 Mon Sep 17 00:00:00 2001 From: Alexander Sisco Date: Thu, 13 Feb 2025 13:14:29 -0800 Subject: [PATCH 081/118] fixed spelling of 'bitmask' --- exercises/110_quiz9.zig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index 540c6e4..cd0048b 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -202,7 +202,7 @@ pub fn main() !void { // _ Set only this bit. // / // 1001 1 0 0 1 -// | 0010 0 0 1 0 (bit mask) +// | 0010 0 0 1 0 (bitmask) // ------ - - - - // = 1011 1 0 1 1 // \___\_______\ @@ -211,7 +211,7 @@ pub fn main() !void { // a 0 effects no change. // // ------------------------------------------------------------------------ -// To create a bit mask like 0b0010 used above: +// To create a bitmask like 0b0010 used above: // // 1. First, shift the value 1 over one place with the bitwise << (shift // left) operator as indicated below: @@ -254,7 +254,7 @@ pub fn main() !void { // __________ Clear only this bit. // / // 1110 1 1 1 0 -// & 1011 1 0 1 1 (bit mask) +// & 1011 1 0 1 1 (bitmask) // ------ - - - - // = 1010 1 0 1 0 <- This bit was already cleared. // \_______\ @@ -263,7 +263,7 @@ pub fn main() !void { // 1 preserves the original bit value whether 0 or 1. // // ------------------------------------------------------------------------ -// We can use the ~ (NOT) operator to easily create a bit mask like 1011: +// We can use the ~ (NOT) operator to easily create a bitmask like 1011: // // 1. First, shift the value 1 over two places with the bit-wise << (shift // left) operator as indicated below: @@ -272,7 +272,7 @@ pub fn main() !void { // 1 << 2 -> 0100 <- The 1 has been shifted two places to the left // 1 << 3 -> 1000 // -// 2. The second step in creating our bit mask is to invert the bits +// 2. The second step in creating our bitmask is to invert the bits // ~0100 -> 1011 // in C we would write this as: // ~(1 << 2) -> 1011 From 7382949018a07d8770c742fda2873a1b33117910 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 14 Feb 2025 09:17:16 +0100 Subject: [PATCH 082/118] Shuttle weight fixed --- exercises/060_floats.zig | 2 +- patches/patches/060_floats.patch | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/exercises/060_floats.zig b/exercises/060_floats.zig index 6f341ad..217c265 100644 --- a/exercises/060_floats.zig +++ b/exercises/060_floats.zig @@ -43,7 +43,7 @@ pub fn main() void { // // We'll convert this weight from pound to kilograms at a // conversion of 0.453592kg to the pound. - const shuttle_weight: f16 = 0.453592 * 4480e6; + const shuttle_weight: f16 = 0.453592 * 4480e3; // By default, float values are formatted in scientific // notation. Try experimenting with '{d}' and '{d:.3}' to see diff --git a/patches/patches/060_floats.patch b/patches/patches/060_floats.patch index 404654a..e74f87e 100644 --- a/patches/patches/060_floats.patch +++ b/patches/patches/060_floats.patch @@ -1,11 +1,11 @@ ---- exercises/060_floats.zig 2023-11-06 19:45:03.609687304 +0100 -+++ answers/060_floats.zig 2023-11-06 19:44:49.249419994 +0100 +--- exercises/060_floats.zig 2025-02-14 09:10:40.443151829 +0100 ++++ answers/060_floats.zig 2025-02-14 09:10:47.576619873 +0100 @@ -43,7 +43,7 @@ // // We'll convert this weight from pound to kilograms at a // conversion of 0.453592kg to the pound. -- const shuttle_weight: f16 = 0.453592 * 4480e6; -+ const shuttle_weight: f32 = 0.453592 * 4.480e6; +- const shuttle_weight: f16 = 0.453592 * 4480e3; ++ const shuttle_weight: f32 = 0.453592 * 4.480e3; // By default, float values are formatted in scientific // notation. Try experimenting with '{d}' and '{d:.3}' to see From f285bd59a4080eb2d62afa414e087dfd54184a96 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 14 Feb 2025 09:22:36 +0100 Subject: [PATCH 083/118] Output from #60 adapted --- build.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.zig b/build.zig index 25d831c..51288ad 100644 --- a/build.zig +++ b/build.zig @@ -283,12 +283,11 @@ pub fn build(b: *Build) !void { starting_exercise = try std.fmt.parseInt(u32, contents, 10); } else |err| { switch (err) { - std.fs.File.OpenError.FileNotFound => { // This is fine, may be the first time tests are run or progress have been reset }, else => { - print("Unable to open {s}: {}\n", .{progress_filename, err}); + print("Unable to open {s}: {}\n", .{ progress_filename, err }); return err; }, } @@ -964,7 +963,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "060_floats.zig", - .output = "Shuttle liftoff weight: 2032092kg", + .output = "Shuttle liftoff weight: 2032kg", }, .{ .main_file = "061_coercions.zig", From a22f1df0a1d98322dd28067ba5509f71a8f3e6b8 Mon Sep 17 00:00:00 2001 From: mz0 Date: Mon, 24 Feb 2025 00:04:43 +0400 Subject: [PATCH 084/118] Shuttle weight fixed w.r.t. issue-211 --- build.zig | 2 +- exercises/060_floats.zig | 6 +++--- patches/patches/060_floats.patch | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.zig b/build.zig index 51288ad..8941610 100644 --- a/build.zig +++ b/build.zig @@ -963,7 +963,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "060_floats.zig", - .output = "Shuttle liftoff weight: 2032kg", + .output = "Shuttle liftoff weight: 2032 metric tons", }, .{ .main_file = "061_coercions.zig", diff --git a/exercises/060_floats.zig b/exercises/060_floats.zig index 217c265..b570518 100644 --- a/exercises/060_floats.zig +++ b/exercises/060_floats.zig @@ -41,14 +41,14 @@ pub fn main() void { // The approximate weight of the Space Shuttle upon liftoff // (including boosters and fuel tank) was 4,480,000 lb. // - // We'll convert this weight from pound to kilograms at a - // conversion of 0.453592kg to the pound. + // We'll convert this weight from pounds to metric units at a + // conversion of 0.453592 kg to the pound. const shuttle_weight: f16 = 0.453592 * 4480e3; // By default, float values are formatted in scientific // notation. Try experimenting with '{d}' and '{d:.3}' to see // how decimal formatting works. - print("Shuttle liftoff weight: {d:.0}kg\n", .{shuttle_weight}); + print("Shuttle liftoff weight: {d:.0} metric tons\n", .{shuttle_weight}); } // Floating further: diff --git a/patches/patches/060_floats.patch b/patches/patches/060_floats.patch index e74f87e..9e64c6f 100644 --- a/patches/patches/060_floats.patch +++ b/patches/patches/060_floats.patch @@ -1,9 +1,9 @@ ---- exercises/060_floats.zig 2025-02-14 09:10:40.443151829 +0100 -+++ answers/060_floats.zig 2025-02-14 09:10:47.576619873 +0100 +--- exercises/060_floats.zig 2025-03-03 20:23:40.255443963 +0400 ++++ answers/060_floats.zig 2025-03-03 20:29:58.554854977 +0400 @@ -43,7 +43,7 @@ // - // We'll convert this weight from pound to kilograms at a - // conversion of 0.453592kg to the pound. + // We'll convert this weight from pounds to metric units at a + // conversion of 0.453592 kg to the pound. - const shuttle_weight: f16 = 0.453592 * 4480e3; + const shuttle_weight: f32 = 0.453592 * 4.480e3; From e0ecff70452615d8041c4ccb5c176e0424e62548 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 10 Mar 2025 10:02:07 +0100 Subject: [PATCH 085/118] Updated version number --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index db63593..6985390 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Verify the installation and build number of `zig` like so: ``` $ zig version -0.14.0-dev.xxxx+xxxxxxxxx +0.15.0-dev.xxxx+xxxxxxxxx ``` Clone this repository with Git: @@ -73,8 +73,8 @@ the appropriate tag. The Zig language is under very active development. In order to be current, Ziglings tracks **development** builds of the Zig compiler rather than versioned **release** builds. The last -stable release was `0.13.0`, but Ziglings needs a dev build with -pre-release version "0.14.0" and a build number at least as high +stable release was `0.14.0`, but Ziglings needs a dev build with +pre-release version "0.15.0" and a build number at least as high as that shown in the example version check above. It is likely that you'll download a build which is _greater_ than From 6f3cdcf0183efae4e3915e56a7257084ff8d0e4a Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Thu, 13 Mar 2025 20:49:41 +0200 Subject: [PATCH 086/118] Update type info for StructField type in 082 Signed-off-by: Yevhen Babiichuk (DustDFG) --- README.md | 1 + exercises/082_anonymous_structs3.zig | 6 ++++-- patches/patches/082_anonymous_structs3.patch | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 63b96fe..2838209 100644 --- a/README.md +++ b/README.md @@ -233,6 +233,7 @@ Zig Core Language * [X] Interfaces * [X] Bit manipulation * [X] Working with C +* [ ] Opaque types (anyopaque) * [X] Threading * [x] Labeled switch * [x] Vector operations (SIMD) diff --git a/exercises/082_anonymous_structs3.zig b/exercises/082_anonymous_structs3.zig index 573d0bb..469cd66 100644 --- a/exercises/082_anonymous_structs3.zig +++ b/exercises/082_anonymous_structs3.zig @@ -95,13 +95,15 @@ fn printTuple(tuple: anytype) void { // Each 'field' in this loop is one of these: // // pub const StructField = struct { - // name: []const u8, + // name: [:0]const u8, // type: type, - // default_value: anytype, + // default_value_ptr: ?*const anyopaque, // is_comptime: bool, // alignment: comptime_int, // }; // + // Note we will learn about 'anyopaque' type later + // // You'll need this builtin: // // @field(lhs: anytype, comptime field_name: []const u8) diff --git a/patches/patches/082_anonymous_structs3.patch b/patches/patches/082_anonymous_structs3.patch index b918011..0f71a94 100644 --- a/patches/patches/082_anonymous_structs3.patch +++ b/patches/patches/082_anonymous_structs3.patch @@ -1,5 +1,5 @@ ---- exercises/082_anonymous_structs3.zig 2024-09-07 19:13:58.210327580 +0200 -+++ answers/082_anonymous_structs3.zig 2024-09-07 19:21:20.972733477 +0200 +--- exercises/082_anonymous_structs3.zig 2025-03-14 16:41:17.892873287 +0200 ++++ answers/082_anonymous_structs3.zig 2025-03-14 16:40:56.043829543 +0200 @@ -82,14 +82,14 @@ // @typeInfo(Circle).@"struct".fields // @@ -17,7 +17,7 @@ // 3. Print the field's name, type, and value. // // Each 'field' in this loop is one of these: -@@ -117,9 +117,9 @@ +@@ -119,9 +119,9 @@ // // The first field should print as: "0"(bool):true print("\"{s}\"({any}):{any} ", .{ From 1a9b7ec3427dac2a802183a202b041fa6d41662e Mon Sep 17 00:00:00 2001 From: "Yevhen Babiichuk (DustDFG)" Date: Fri, 14 Mar 2025 22:26:20 +0200 Subject: [PATCH 087/118] Rectify 106 and 107 patches Signed-off-by: Yevhen Babiichuk (DustDFG) --- patches/patches/106_files.patch | 91 ++++---------------------------- patches/patches/107_files2.patch | 50 ++++-------------- 2 files changed, 19 insertions(+), 122 deletions(-) diff --git a/patches/patches/106_files.patch b/patches/patches/106_files.patch index 89f37ad..f40a33a 100644 --- a/patches/patches/106_files.patch +++ b/patches/patches/106_files.patch @@ -1,63 +1,16 @@ ---- exercises/106_files.zig 2024-11-09 20:33:07.455580904 +0100 -+++ answers/106_files.zig 2024-11-09 20:33:30.394785215 +0100 -@@ -1,22 +1,22 @@ - // - // Until now, we've only been printing our output in the console, --// which is good enough for fighting aliens and hermit bookkeeping. -+// which is good enough for fighting alien and hermit bookkeeping. - // --// However, many other tasks require some interaction with the file system, -+// However, many other task require some interaction with the file system, - // which is the underlying structure for organizing files on your computer. - // --// The file system provides a hierarchical structure for storing files --// by organizing them into directories, which hold files and other directories, --// thus creating a tree structure that can be navigated. -+// The File System provide a hierarchical structure for storing files -+// by organizing files into directories, which hold files and other directories, -+// thus creating a tree structure for navigating. - // --// Fortunately, the Zig Standard Library provides a simple API for interacting --// with the file system, see the detail documentation here: -+// Fortunately, the Zig Standard Library provide a simple api for interacting -+// with the file system, see the detail documentation here - // - // https://ziglang.org/documentation/master/std/#std.fs - // --// In this exercise, we'll try to: --// - create a new directory, --// - open a file in the directory, -+// In this exercise, we'll try to -+// - create a new directory -+// - open a file in the directory - // - write to the file. - // - // import std as always -@@ -27,42 +27,42 @@ - const cwd: std.fs.Dir = std.fs.cwd(); - - // then we'll try to make a new directory /output/ -- // to store our output files. -+ // to put our output files. - cwd.makeDir("output") catch |e| switch (e) { -- // there is a chance you might want to run this -+ // there are chance you might want to run this - // program more than once and the path might already -- // have been created, so we'll have to handle this error -+ // been created, so we'll have to handle this error +--- exercises/106_files.zig 2025-03-13 15:26:59.532367792 +0200 ++++ answers/106_files.zig 2025-03-14 22:04:52.243435159 +0200 +@@ -35,7 +35,7 @@ // by doing nothing // // we want to catch error.PathAlreadyExists and do nothing - ??? => {}, -- // if there's any other unexpected error we just propagate it through + error.PathAlreadyExists => {}, -+ // if is any other unexpected error we just propagate it through + // if there's any other unexpected error we just propagate it through else => return e, }; - - // then we'll try to open our freshly created directory -- // wait a minute... -+ // wait a minute +@@ -44,7 +44,7 @@ + // wait a minute... // opening a directory might fail! // what should we do here? - var output_dir: std.fs.Dir = cwd.openDir("output", .{}); @@ -65,36 +18,12 @@ defer output_dir.close(); // we try to open the file `zigling.txt`, -- // and propagate any error up -+ // and propagate the error up if there are any errors - const file: std.fs.File = try output_dir.createFile("zigling.txt", .{}); - // it is a good habit to close a file after you are done with it - // so that other programs can read it and prevent data corruption +@@ -55,7 +55,7 @@ // but here we are not yet done writing to the file -- // if only there were a keyword in Zig that -- // allowed you to "defer" code execution to the end of the scope... + // if only there were a keyword in Zig that + // allowed you to "defer" code execution to the end of the scope... - file.close(); -+ // if only there were a keyword in zig that -+ // allows you "defer" code execute to the end of scope... + defer file.close(); -- // you are not allowed to move these two lines above the file closing line! -+ // !you are not allowed to switch these two lines above the file closing line! + // you are not allowed to move these two lines above the file closing line! const byte_written = try file.write("It's zigling time!"); - std.debug.print("Successfully wrote {d} bytes.\n", .{byte_written}); - } - // to check if you actually write to the file, you can either, --// 1. open the file in your text editor, or -+// 1. open the file on your text editor, or - // 2. print the content of the file in the console with the following command - // >> cat ./output/zigling.txt - // -@@ -86,7 +86,7 @@ - // - // Question: - // - what should you do if you want to also read the file after opening it? --// - go to the documentation of the struct `std.fs.Dir` here: -+// - go to documentation of the struct `std.fs.Dir` here - // https://ziglang.org/documentation/master/std/#std.fs.Dir - // - can you find a function for opening a file? how about deleting a file? - // - what kind of options can you use with those functions? diff --git a/patches/patches/107_files2.patch b/patches/patches/107_files2.patch index f03a2e8..7e2692f 100644 --- a/patches/patches/107_files2.patch +++ b/patches/patches/107_files2.patch @@ -1,55 +1,23 @@ ---- exercises/107_files2.zig 2024-06-17 10:11:53.651439869 +0200 -+++ answers/107_files2.zig 2024-06-17 10:21:50.700671057 +0200 -@@ -4,17 +4,17 @@ - // - create a file {project_root}/output/zigling.txt - // with content `It's zigling time!`(18 byte total) - // --// Now there's no point in writing to a file if we don't read from it, am I right? --// Let's write a program to read the content of the file that we just created. -+// Now there no point in writing to a file if we don't read from it am I right? -+// let's write a program to read the content of the file that we just created. - // - // I am assuming that you've created the appropriate files for this to work. - // --// Alright, bud, lean in close. Here's the game plan. -+// Alright, bud, lean in close here's the game plan. - // - First, we open the {project_root}/output/ directory - // - Secondly, we open file `zigling.txt` in that directory --// - Then, we initalize an array of characters with all letter 'A', and print it --// - After that, we read the content of the file into the array --// - Finally, we print out the content we just read -+// - then, we initalize an array of characters with all letter 'A', and print it -+// - After that, we read the content of the file to the array -+// - Finally, we print out the read content - - const std = @import("std"); - -@@ -30,23 +30,23 @@ - const file = try output_dir.openFile("zigling.txt", .{}); - defer file.close(); - -- // initalize an array of u8 with all letter 'A' -- // we need to pick the size of the array, 64 seems like a good number -+ // initalize an array of u8 with all letter 'A'. -+ // we need to pick the size of the array, 64 seems like a good number. +--- exercises/107_files2.zig 2025-03-13 15:26:59.532367792 +0200 ++++ answers/107_files2.zig 2025-03-14 22:08:35.167953736 +0200 +@@ -33,7 +33,7 @@ + // initalize an array of u8 with all letter 'A' + // we need to pick the size of the array, 64 seems like a good number // fix the initalization below - var content = ['A']*64; + var content = [_]u8{'A'} ** 64; // this should print out : `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA` std.debug.print("{s}\n", .{content}); - // okay, seems like a threat of violence is not the answer in this case -- // can you go here to find a way to read the content? -+ // can you go here to find a way to read the content ? +@@ -41,12 +41,12 @@ + // can you go here to find a way to read the content? // https://ziglang.org/documentation/master/std/#std.fs.File // hint: you might find two answers that are both valid in this case - const bytes_read = zig_read_the_file_or_i_will_fight_you(&content); + const bytes_read = try file.read(&content); -- // Woah, too screamy. I know you're excited for zigling time but tone it down a bit. -- // Can you print only what we read from the file? -+ // Woah, too screamy, I know you're excited for zigling time but tone it down a bit -+ // Can you print only what we read from the file ? + // Woah, too screamy. I know you're excited for zigling time but tone it down a bit. + // Can you print only what we read from the file? std.debug.print("Successfully Read {d} bytes: {s}\n", .{ bytes_read, - content, // change this line only From 522b4673a426258d1299abd75021a9510644f9ba Mon Sep 17 00:00:00 2001 From: Jost Alemann Date: Thu, 20 Mar 2025 21:24:40 +0100 Subject: [PATCH 088/118] fix: typos --- build.zig | 2 +- exercises/033_iferror.zig | 2 +- exercises/071_comptime6.zig | 2 +- exercises/105_threading2.zig | 6 +++--- exercises/107_files2.zig | 6 +++--- exercises/108_labeled_switch.zig | 2 +- exercises/110_quiz9.zig | 4 ++-- patches/patches/107_files2.patch | 4 ++-- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/build.zig b/build.zig index 8941610..2d7d2f4 100644 --- a/build.zig +++ b/build.zig @@ -200,7 +200,7 @@ pub fn build(b: *Build) !void { if (rand) |_| { // Random build mode: verifies one random exercise. - // like for 'exno' but chooses a random exersise number. + // like for 'exno' but chooses a random exercise number. print("work in progress: check a random exercise\n", .{}); var prng = std.Random.DefaultPrng.init(blk: { diff --git a/exercises/033_iferror.zig b/exercises/033_iferror.zig index 6ba0c61..12da2d2 100644 --- a/exercises/033_iferror.zig +++ b/exercises/033_iferror.zig @@ -17,7 +17,7 @@ // // if (foo) |value| { // ... -// } else |err| switch(err) { +// } else |err| switch (err) { // ... // } // diff --git a/exercises/071_comptime6.zig b/exercises/071_comptime6.zig index 5938abc..9b3e5a2 100644 --- a/exercises/071_comptime6.zig +++ b/exercises/071_comptime6.zig @@ -7,7 +7,7 @@ // doing this work. // // An 'inline for' is performed at compile time, allowing you to -// programatically loop through a series of items in situations +// programmatically loop through a series of items in situations // like those mentioned above where a regular runtime 'for' loop // wouldn't be allowed: // diff --git a/exercises/105_threading2.zig b/exercises/105_threading2.zig index 7e16a1c..374391a 100644 --- a/exercises/105_threading2.zig +++ b/exercises/105_threading2.zig @@ -21,9 +21,9 @@ // There were the Scottish mathematician Gregory and the German // mathematician Leibniz, and even a few hundred years earlier the Indian // mathematician Madhava. All of them independently developed the same -// formula, which was published by Leibnitz in 1682 in the journal +// formula, which was published by Leibniz in 1682 in the journal // "Acta Eruditorum". -// This is why this method has become known as the "Leibnitz series", +// This is why this method has become known as the "Leibniz series", // although the other names are also often used today. // We will not go into the formula and its derivation in detail, but // will deal with the series straight away: @@ -50,7 +50,7 @@ // enough for us for now, because we want to understand the principle and // nothing more, right? // -// As we have already discovered, the Leibnitz series is a series with a +// As we have already discovered, the Leibniz series is a series with a // fixed distance of 2 between the individual partial values. This makes // it easy to apply a simple loop to it, because if we start with n = 1 // (which is not necessarily useful now) we always have to add 2 in each diff --git a/exercises/107_files2.zig b/exercises/107_files2.zig index 6768898..d059879 100644 --- a/exercises/107_files2.zig +++ b/exercises/107_files2.zig @@ -12,7 +12,7 @@ // Alright, bud, lean in close. Here's the game plan. // - First, we open the {project_root}/output/ directory // - Secondly, we open file `zigling.txt` in that directory -// - Then, we initalize an array of characters with all letter 'A', and print it +// - Then, we initialize an array of characters with all letter 'A', and print it // - After that, we read the content of the file into the array // - Finally, we print out the content we just read @@ -30,9 +30,9 @@ pub fn main() !void { const file = try output_dir.openFile("zigling.txt", .{}); defer file.close(); - // initalize an array of u8 with all letter 'A' + // initialize an array of u8 with all letter 'A' // we need to pick the size of the array, 64 seems like a good number - // fix the initalization below + // fix the initialization below var content = ['A']*64; // this should print out : `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA` std.debug.print("{s}\n", .{content}); diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 16a5879..9262c6f 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -24,7 +24,7 @@ // // By combining all we've learned so far, we can now proceed with a labeled switch // -// A labeled switch is some extra syntatic sugar, which comes with all sorts of +// A labeled switch is some extra syntactic sugar, which comes with all sorts of // candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367 // // Here is the previous excerpt implemented as a labeled switch instead: diff --git a/exercises/110_quiz9.zig b/exercises/110_quiz9.zig index cd0048b..8f5cb61 100644 --- a/exercises/110_quiz9.zig +++ b/exercises/110_quiz9.zig @@ -161,7 +161,7 @@ pub fn main() !void { // In order to output a 1, the logic of an XOR operation requires that the // two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will // both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior -// of outputing a 0 when both inputs are 1s is what makes it different from +// of outputting a 0 when both inputs are 1s is what makes it different from // the OR operator; it also gives us the ability to toggle bits by putting // 1s into our bitmask. // @@ -247,7 +247,7 @@ pub fn main() !void { // PORTB = PORTB & 0b1011; // print("PORTB: {b:0>4}\n", .{PORTB}); // output -> 1010 // -// - 0s clear bits when used in conjuction with a bitwise AND. +// - 0s clear bits when used in conjunction with a bitwise AND. // - 1s do nothing, thus preserving the original bits. // // -AND op- ---expanded--- diff --git a/patches/patches/107_files2.patch b/patches/patches/107_files2.patch index 7e2692f..95aaa0c 100644 --- a/patches/patches/107_files2.patch +++ b/patches/patches/107_files2.patch @@ -1,9 +1,9 @@ --- exercises/107_files2.zig 2025-03-13 15:26:59.532367792 +0200 +++ answers/107_files2.zig 2025-03-14 22:08:35.167953736 +0200 @@ -33,7 +33,7 @@ - // initalize an array of u8 with all letter 'A' + // initialize an array of u8 with all letter 'A' // we need to pick the size of the array, 64 seems like a good number - // fix the initalization below + // fix the initialization below - var content = ['A']*64; + var content = [_]u8{'A'} ** 64; // this should print out : `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA` From 377d184cdcf9a5916b0d834cc327ae8dfdf52666 Mon Sep 17 00:00:00 2001 From: chrboesch Date: Mon, 14 Apr 2025 17:05:40 +0000 Subject: [PATCH 089/118] new issue template --- .gitea/issue_template.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitea/issue_template.md diff --git a/.gitea/issue_template.md b/.gitea/issue_template.md new file mode 100644 index 0000000..4af39e3 --- /dev/null +++ b/.gitea/issue_template.md @@ -0,0 +1,5 @@ +Ziglings is a progressive learning series — each exercise builds on previous ones. +Before opening an issue, please ensure you've followed the path and read the instructions carefully. + +Respectful and constructive feedback is always welcome. + From 761fb1a501a73cf553e1ec4ec0d8ab82ff75d6e4 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 12 May 2025 21:36:37 +0200 Subject: [PATCH 090/118] Changed the values for better understanding --- build.zig | 2 +- exercises/097_bit_manipulation.zig | 8 ++++---- patches/patches/097_bit_manipulation.patch | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.zig b/build.zig index 2d7d2f4..6c76917 100644 --- a/build.zig +++ b/build.zig @@ -1146,7 +1146,7 @@ const exercises = [_]Exercise{ }, .{ .main_file = "097_bit_manipulation.zig", - .output = "x = 0; y = 1", + .output = "x = 1011; y = 1101", }, .{ .main_file = "098_bit_manipulation2.zig", diff --git a/exercises/097_bit_manipulation.zig b/exercises/097_bit_manipulation.zig index 03fc72d..0e64ad7 100644 --- a/exercises/097_bit_manipulation.zig +++ b/exercises/097_bit_manipulation.zig @@ -71,9 +71,9 @@ const print = std.debug.print; pub fn main() !void { - // As in the example above, we use 1 and 0 as values for x and y - var x: u8 = 1; - var y: u8 = 0; + // Let us use 1101 and 1011 as values for x and y + var x: u8 = 0b1101; + var y: u8 = 0b1011; // Now we swap the values of the two variables by doing xor on them x ^= y; @@ -82,7 +82,7 @@ pub fn main() !void { // What must be written here? ???; - print("x = {d}; y = {d}\n", .{ x, y }); + print("x = {b}; y = {b}\n", .{ x, y }); } // This variable swap takes advantage of the fact that the value resulting diff --git a/patches/patches/097_bit_manipulation.patch b/patches/patches/097_bit_manipulation.patch index 5303ee1..19ba876 100644 --- a/patches/patches/097_bit_manipulation.patch +++ b/patches/patches/097_bit_manipulation.patch @@ -1,5 +1,5 @@ ---- exercises/097_bit_manipulation.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/097_bit_manipulation.zig 2023-10-05 20:04:07.282771124 +0200 +--- exercises/097_bit_manipulation.zig 2025-05-12 21:25:03.395385743 +0200 ++++ answers/097_bit_manipulation.zig 2025-05-12 21:22:57.472986976 +0200 @@ -80,7 +80,7 @@ y ^= x; @@ -7,5 +7,5 @@ - ???; + x ^= y; - print("x = {d}; y = {d}\n", .{ x, y }); + print("x = {b}; y = {b}\n", .{ x, y }); } From 76b8fcdb2801995e3c92c5477886b50cca30ab21 Mon Sep 17 00:00:00 2001 From: felixrabe Date: Fri, 30 May 2025 12:12:26 +0200 Subject: [PATCH 091/118] Add ')' --- exercises/050_no_value.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/050_no_value.zig b/exercises/050_no_value.zig index 8c73ed3..f5365cf 100644 --- a/exercises/050_no_value.zig +++ b/exercises/050_no_value.zig @@ -43,7 +43,7 @@ // // "void" is a _type_, not a value. It is the most popular of the // Zero Bit Types (those types which take up absolutely no space -// and have only a semantic value. When compiled to executable +// and have only a semantic value). When compiled to executable // code, zero bit types generate no code at all. The above example // shows a variable foo of type void which is assigned the value // of an empty expression. It's much more common to see void as From 14c81a6ceff247072fa719accdc6007c4f3d3001 Mon Sep 17 00:00:00 2001 From: felixrabe Date: Fri, 30 May 2025 21:53:24 +0200 Subject: [PATCH 092/118] 080: Fix @typeName results in comment --- exercises/080_anonymous_structs.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/080_anonymous_structs.zig b/exercises/080_anonymous_structs.zig index 55dedd4..4e3ce84 100644 --- a/exercises/080_anonymous_structs.zig +++ b/exercises/080_anonymous_structs.zig @@ -19,12 +19,12 @@ // const MyBar = Bar(); // store the struct type // const bar = Bar() {}; // create instance of the struct // -// * The value of @typeName(Bar()) is "Bar()". -// * The value of @typeName(MyBar) is "Bar()". -// * The value of @typeName(@TypeOf(bar)) is "Bar()". +// * The value of @typeName(Bar()) is ".Bar()". +// * The value of @typeName(MyBar) is ".Bar()". +// * The value of @typeName(@TypeOf(bar)) is ".Bar()". // // You can also have completely anonymous structs. The value -// of @typeName(struct {}) is "struct:". +// of @typeName(struct {}) is ".__struct_". // const print = @import("std").debug.print; From 69ad718446225aba634331c07f1cde8b24770cff Mon Sep 17 00:00:00 2001 From: felixrabe Date: Sat, 31 May 2025 23:15:28 +0200 Subject: [PATCH 093/118] 099: Make hex example match output --- exercises/099_formatting.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/099_formatting.zig b/exercises/099_formatting.zig index 37fab45..ef6b84e 100644 --- a/exercises/099_formatting.zig +++ b/exercises/099_formatting.zig @@ -60,7 +60,7 @@ // variety of formatting instructions. It's basically a tiny // language of its own. Here's a numeric example: // -// print("Catch-{x:0>4}.", .{twenty_two}); +// print("Catch-0x{x:0>4}.", .{twenty_two}); // // This formatting instruction outputs a hexadecimal number with // leading zeros: From 91f1c045bcd33e43f2723ed5b8a159c85f54acb0 Mon Sep 17 00:00:00 2001 From: felixrabe Date: Sun, 1 Jun 2025 01:05:22 +0200 Subject: [PATCH 094/118] 108: Make pretty --- exercises/108_labeled_switch.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index 9262c6f..fb61ac0 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -19,7 +19,7 @@ // } // break; // } -// std.debug.print("This statement cannot be reached\n", .{}); +// std.debug.print("This statement cannot be reached\n", .{}); // } // // By combining all we've learned so far, we can now proceed with a labeled switch From b1223f92edd6d488d491125dd6d415dc915707b4 Mon Sep 17 00:00:00 2001 From: felixrabe Date: Sun, 1 Jun 2025 01:08:07 +0200 Subject: [PATCH 095/118] 108: . --- exercises/108_labeled_switch.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig index fb61ac0..897fcf5 100644 --- a/exercises/108_labeled_switch.zig +++ b/exercises/108_labeled_switch.zig @@ -22,7 +22,7 @@ // std.debug.print("This statement cannot be reached\n", .{}); // } // -// By combining all we've learned so far, we can now proceed with a labeled switch +// By combining all we've learned so far, we can now proceed with a labeled switch. // // A labeled switch is some extra syntactic sugar, which comes with all sorts of // candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367 From e431cbb0cf01b89d565f5e1637782d8cef6d3151 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Thu, 12 Jun 2025 09:20:33 +0200 Subject: [PATCH 096/118] Stable release in README corrected. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6985390..63d8dbf 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ the appropriate tag. The Zig language is under very active development. In order to be current, Ziglings tracks **development** builds of the Zig compiler rather than versioned **release** builds. The last -stable release was `0.14.0`, but Ziglings needs a dev build with +stable release was `0.14.1`, but Ziglings needs a dev build with pre-release version "0.15.0" and a build number at least as high as that shown in the example version check above. From 451e1a373969f81fb63223e10b1d69ba7dac3523 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 17 Jun 2025 14:07:31 +0200 Subject: [PATCH 097/118] Fixes the changes in zig's struct.fields --- exercises/065_builtins2.zig | 8 ++++++-- patches/patches/065_builtins2.patch | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/exercises/065_builtins2.zig b/exercises/065_builtins2.zig index 6b8168c..067f07c 100644 --- a/exercises/065_builtins2.zig +++ b/exercises/065_builtins2.zig @@ -99,11 +99,15 @@ pub fn main() void { // 'fields' is a slice of StructFields. Here's the declaration: // // pub const StructField = struct { - // name: []const u8, + // name: [:0]const u8, // type: type, - // default_value: anytype, + // default_value_ptr: ?*const anyopaque, // is_comptime: bool, // alignment: comptime_int, + // + // defaultValue() ?sf.type // Function that loads the + // // field's default value from + // // `default_value_ptr` // }; // // Please complete these 'if' statements so that the field diff --git a/patches/patches/065_builtins2.patch b/patches/patches/065_builtins2.patch index e5e6410..ad4192b 100644 --- a/patches/patches/065_builtins2.patch +++ b/patches/patches/065_builtins2.patch @@ -1,5 +1,5 @@ ---- exercises/065_builtins2.zig 2024-11-02 16:58:30.607829441 +0100 -+++ answers/065_builtins2.zig 2024-11-02 16:58:33.821220588 +0100 +--- exercises/065_builtins2.zig 2025-06-17 13:58:07.857258167 +0200 ++++ answers/065_builtins2.zig 2025-06-17 13:56:36.630415938 +0200 @@ -58,7 +58,7 @@ // Oops! We cannot leave the 'me' and 'myself' fields // undefined. Please set them here: @@ -18,7 +18,7 @@ // Now we print a pithy statement about Narcissus. print("A {s} loves all {s}es. ", .{ -@@ -109,15 +109,15 @@ +@@ -113,15 +113,15 @@ // Please complete these 'if' statements so that the field // name will not be printed if the field is of type 'void' // (which is a zero-bit type that takes up no space at all!): From f5d2c5124c2728d14d4c349c9287edb00f9eb633 Mon Sep 17 00:00:00 2001 From: Callum Styan Date: Sun, 13 Jul 2025 17:02:50 -0700 Subject: [PATCH 098/118] for expectEqual the first param is expected Signed-off-by: Callum Styan --- exercises/102_testing.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/102_testing.zig b/exercises/102_testing.zig index 89a0ee8..248f5b5 100644 --- a/exercises/102_testing.zig +++ b/exercises/102_testing.zig @@ -58,7 +58,7 @@ test "add" { // Another way to perform this test // is as follows: - try testing.expectEqual(add(41, 1), 42); + try testing.expectEqual(42, add(41, 1)); // This time a test with the addition // of a negative number: From 9ae739c4c95aec30e2ac4c49d0dc879ff4b5d169 Mon Sep 17 00:00:00 2001 From: Arnold Filip Date: Mon, 21 Jul 2025 15:00:15 +0200 Subject: [PATCH 099/118] Fix zig 0.15.0-dev.1149+4e6a04929 build errors --- build.zig | 11 +++++------ test/tests.zig | 11 +++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/build.zig b/build.zig index 6c76917..7522dee 100644 --- a/build.zig +++ b/build.zig @@ -126,19 +126,18 @@ pub fn build(b: *Build) !void { if (!validate_exercises()) std.process.exit(2); use_color_escapes = false; - if (std.io.getStdErr().supportsAnsiEscapeCodes()) { + if (std.fs.File.stderr().supportsAnsiEscapeCodes()) { use_color_escapes = true; } else if (builtin.os.tag == .windows) { const w32 = struct { - const WINAPI = std.os.windows.WINAPI; const DWORD = std.os.windows.DWORD; const ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004; const STD_ERROR_HANDLE: DWORD = @bitCast(@as(i32, -12)); - extern "kernel32" fn GetStdHandle(id: DWORD) callconv(WINAPI) ?*anyopaque; - extern "kernel32" fn GetConsoleMode(console: ?*anyopaque, out_mode: *DWORD) callconv(WINAPI) u32; - extern "kernel32" fn SetConsoleMode(console: ?*anyopaque, mode: DWORD) callconv(WINAPI) u32; + const GetStdHandle = std.os.windows.kernel32.GetStdHandle; + const GetConsoleMode = std.os.windows.kernel32.GetConsoleMode; + const SetConsoleMode = std.os.windows.kernel32.SetConsoleMode; }; - const handle = w32.GetStdHandle(w32.STD_ERROR_HANDLE); + const handle = w32.GetStdHandle(w32.STD_ERROR_HANDLE).?; var mode: w32.DWORD = 0; if (w32.GetConsoleMode(handle, &mode) != 0) { mode |= w32.ENABLE_VIRTUAL_TERMINAL_PROCESSING; diff --git a/test/tests.zig b/test/tests.zig index 5f64f8e..42c3653 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -161,7 +161,8 @@ const CheckNamedStep = struct { ); defer stderr_file.close(); - const stderr = stderr_file.reader(); + var buffer: [4096]u8 = undefined; + const stderr = stderr_file.reader(&buffer); { // Skip the logo. const nlines = mem.count(u8, root.logo, "\n"); @@ -213,7 +214,8 @@ const CheckStep = struct { ); defer stderr_file.close(); - const stderr = stderr_file.reader(); + var buffer: [4096]u8 = undefined; + const stderr = stderr_file.reader(&buffer); for (exercises) |ex| { if (ex.number() == 1) { // Skip the logo. @@ -298,7 +300,7 @@ fn check( } fn readLine(reader: fs.File.Reader, buf: []u8) !?[]const u8 { - if (try reader.readUntilDelimiterOrEof(buf, '\n')) |line| { + if (try reader.file.deprecatedReader().readUntilDelimiterOrEof(buf, '\n')) |line| { return mem.trimRight(u8, line, " \r\n"); } @@ -405,7 +407,8 @@ fn heal(allocator: Allocator, exercises: []const Exercise, work_path: []const u8 /// difference that returns an error when the temp path cannot be created. pub fn makeTempPath(b: *Build) ![]const u8 { const rand_int = std.crypto.random.int(u64); - const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ Build.hex64(rand_int); + const rand_hex64 = std.fmt.hex(rand_int); + const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ rand_hex64; const path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM"); try b.cache_root.handle.makePath(tmp_dir_sub_path); From cb0a1a027f05371d1debc681949a269cf918aaab Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 21 Jul 2025 21:05:45 +0200 Subject: [PATCH 100/118] Removed patch files for async because of new formating errors. --- patches/patches/084_async.patch | 11 ----------- patches/patches/085_async2.patch | 10 ---------- patches/patches/086_async3.patch | 16 ---------------- patches/patches/087_async4.patch | 21 --------------------- patches/patches/088_async5.patch | 11 ----------- patches/patches/089_async6.patch | 13 ------------- patches/patches/090_async7.patch | 11 ----------- patches/patches/091_async8.patch | 26 -------------------------- 8 files changed, 119 deletions(-) delete mode 100644 patches/patches/084_async.patch delete mode 100644 patches/patches/085_async2.patch delete mode 100644 patches/patches/086_async3.patch delete mode 100644 patches/patches/087_async4.patch delete mode 100644 patches/patches/088_async5.patch delete mode 100644 patches/patches/089_async6.patch delete mode 100644 patches/patches/090_async7.patch delete mode 100644 patches/patches/091_async8.patch diff --git a/patches/patches/084_async.patch b/patches/patches/084_async.patch deleted file mode 100644 index 11a9da0..0000000 --- a/patches/patches/084_async.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- exercises/084_async.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/084_async.zig 2023-10-05 20:04:07.219436606 +0200 -@@ -48,7 +48,7 @@ - pub fn main() void { - // Additional Hint: you can assign things to '_' when you - // don't intend to do anything with them. -- foo(); -+ _ = async foo(); - } - - fn foo() void { diff --git a/patches/patches/085_async2.patch b/patches/patches/085_async2.patch deleted file mode 100644 index ba10b05..0000000 --- a/patches/patches/085_async2.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- exercises/085_async2.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/085_async2.zig 2023-10-05 20:04:07.226103397 +0200 -@@ -19,6 +19,7 @@ - - pub fn main() void { - var foo_frame = async foo(); -+ resume foo_frame; - } - - fn foo() void { diff --git a/patches/patches/086_async3.patch b/patches/patches/086_async3.patch deleted file mode 100644 index d80d4a1..0000000 --- a/patches/patches/086_async3.patch +++ /dev/null @@ -1,16 +0,0 @@ ---- exercises/086_async3.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/086_async3.zig 2023-10-05 20:04:07.229436793 +0200 -@@ -13,7 +13,12 @@ - const n = 5; - var foo_frame = async foo(n); - -- ??? -+ // Silly solution. You can also use a loop. -+ resume foo_frame; -+ resume foo_frame; -+ resume foo_frame; -+ resume foo_frame; -+ resume foo_frame; - - print("\n", .{}); - } diff --git a/patches/patches/087_async4.patch b/patches/patches/087_async4.patch deleted file mode 100644 index b1c1736..0000000 --- a/patches/patches/087_async4.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- exercises/087_async4.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/087_async4.zig 2023-10-05 20:04:07.236103584 +0200 -@@ -16,7 +16,7 @@ - - while (global_counter <= 5) { - print("{} ", .{global_counter}); -- ??? -+ resume foo_frame; - } - - print("\n", .{}); -@@ -24,7 +24,7 @@ - - fn foo() void { - while (true) { -- ??? -- ??? -+ global_counter += 1; -+ suspend {} - } - } diff --git a/patches/patches/088_async5.patch b/patches/patches/088_async5.patch deleted file mode 100644 index b9d5a21..0000000 --- a/patches/patches/088_async5.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- exercises/088_async5.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/088_async5.zig 2023-10-05 20:04:07.239436980 +0200 -@@ -36,7 +36,7 @@ - pub fn main() void { - var myframe = async getPageTitle("http://example.com"); - -- var value = ??? -+ var value = await myframe; - - print("{s}\n", .{value}); - } diff --git a/patches/patches/089_async6.patch b/patches/patches/089_async6.patch deleted file mode 100644 index 4a0687e..0000000 --- a/patches/patches/089_async6.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- exercises/089_async6.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/089_async6.zig 2023-10-05 20:04:07.242770376 +0200 -@@ -41,8 +41,8 @@ - var com_frame = async getPageTitle("http://example.com"); - var org_frame = async getPageTitle("http://example.org"); - -- var com_title = com_frame; -- var org_title = org_frame; -+ var com_title = await com_frame; -+ var org_title = await org_frame; - - print(".com: {s}, .org: {s}.\n", .{ com_title, org_title }); - } diff --git a/patches/patches/090_async7.patch b/patches/patches/090_async7.patch deleted file mode 100644 index 62ec057..0000000 --- a/patches/patches/090_async7.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- exercises/090_async7.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/090_async7.zig 2023-10-05 20:04:07.249437167 +0200 -@@ -29,7 +29,7 @@ - // The main() function can not be async. But we know - // getBeef() will not suspend with this particular - // invocation. Please make this okay: -- var my_beef = getBeef(0); -+ var my_beef = nosuspend getBeef(0); - - print("beef? {X}!\n", .{my_beef}); - } diff --git a/patches/patches/091_async8.patch b/patches/patches/091_async8.patch deleted file mode 100644 index ddd3fce..0000000 --- a/patches/patches/091_async8.patch +++ /dev/null @@ -1,26 +0,0 @@ ---- exercises/091_async8.zig 2023-10-03 22:15:22.125574535 +0200 -+++ answers/091_async8.zig 2023-10-05 20:04:07.252770563 +0200 -@@ -17,7 +17,7 @@ - - var frame = async suspendable(); - -- print("X", .{}); -+ print("D", .{}); - - resume frame; - -@@ -25,11 +25,11 @@ - } - - fn suspendable() void { -- print("X", .{}); -+ print("B", .{}); - - suspend { -- print("X", .{}); -+ print("C", .{}); - } - -- print("X", .{}); -+ print("E", .{}); - } From 49e73db5f5e139b610306ec6495aa6889eb83170 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 00:28:03 +0200 Subject: [PATCH 101/118] Switched to new reader version --- test/tests.zig | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/test/tests.zig b/test/tests.zig index 42c3653..b191610 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -161,8 +161,7 @@ const CheckNamedStep = struct { ); defer stderr_file.close(); - var buffer: [4096]u8 = undefined; - const stderr = stderr_file.reader(&buffer); + var stderr = stderr_file.readerStreaming(&.{}); { // Skip the logo. const nlines = mem.count(u8, root.logo, "\n"); @@ -170,10 +169,10 @@ const CheckNamedStep = struct { var lineno: usize = 0; while (lineno < nlines) : (lineno += 1) { - _ = try readLine(stderr, &buf); + _ = try readLine(&stderr, &buf); } } - try check_output(step, ex, stderr); + try check_output(step, ex, &stderr); } }; @@ -214,8 +213,7 @@ const CheckStep = struct { ); defer stderr_file.close(); - var buffer: [4096]u8 = undefined; - const stderr = stderr_file.reader(&buffer); + var stderr = stderr_file.readerStreaming(&.{}); for (exercises) |ex| { if (ex.number() == 1) { // Skip the logo. @@ -224,15 +222,15 @@ const CheckStep = struct { var lineno: usize = 0; while (lineno < nlines) : (lineno += 1) { - _ = try readLine(stderr, &buf); + _ = try readLine(&stderr, &buf); } } - try check_output(step, ex, stderr); + try check_output(step, ex, &stderr); } } }; -fn check_output(step: *Step, exercise: Exercise, reader: Reader) !void { +fn check_output(step: *Step, exercise: Exercise, reader: *Reader) !void { const b = step.owner; var buf: [1024]u8 = undefined; @@ -299,12 +297,9 @@ fn check( } } -fn readLine(reader: fs.File.Reader, buf: []u8) !?[]const u8 { - if (try reader.file.deprecatedReader().readUntilDelimiterOrEof(buf, '\n')) |line| { - return mem.trimRight(u8, line, " \r\n"); - } - - return null; +fn readLine(reader: *fs.File.Reader, buf: []u8) !?[]const u8 { + try reader.interface.readSliceAll(buf); + return mem.trimRight(u8, buf, " \r\n"); } /// Fails with a custom error message. From b499788606d83aac75e82da2d32b5b7ceb3d6896 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 00:40:06 +0200 Subject: [PATCH 102/118] Corrected the necessary Zig version --- build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig b/build.zig index 7522dee..ebe6838 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.14.0-dev.1573"; + const required_zig = "0.15.0-dev.1092"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From f21f8f7863f512aed8ae0418351756819990df67 Mon Sep 17 00:00:00 2001 From: Arnold Filip Date: Tue, 22 Jul 2025 09:17:24 +0200 Subject: [PATCH 103/118] Update stdout writer usage to use std.fs.File --- exercises/026_hello2.zig | 4 ++-- exercises/034_quiz4.zig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/026_hello2.zig b/exercises/026_hello2.zig index cd59b86..582dba9 100644 --- a/exercises/026_hello2.zig +++ b/exercises/026_hello2.zig @@ -16,12 +16,12 @@ const std = @import("std"); // pub fn main() !void { // We get a Writer for Standard Out so we can print() to it. - const stdout = std.io.getStdOut().writer(); + var stdout = std.fs.File.stdout().writer(&.{}); // Unlike std.debug.print(), the Standard Out writer can fail // with an error. We don't care _what_ the error is, we want // to be able to pass it up as a return value of main(). // // We just learned of a single statement which can accomplish this. - stdout.print("Hello world!\n", .{}); + stdout.interface.print("Hello world!\n", .{}); } diff --git a/exercises/034_quiz4.zig b/exercises/034_quiz4.zig index 2d843f2..8704397 100644 --- a/exercises/034_quiz4.zig +++ b/exercises/034_quiz4.zig @@ -10,11 +10,11 @@ const std = @import("std"); const NumError = error{IllegalNumber}; pub fn main() void { - const stdout = std.io.getStdOut().writer(); + var stdout = std.fs.File.stdout().writer(&.{}); const my_num: u32 = getNumber(); - try stdout.print("my_num={}\n", .{my_num}); + try stdout.interface.print("my_num={}\n", .{my_num}); } // This function is obviously weird and non-functional. But you will not be changing it for this quiz. From ed2f76e9600ce63405a5b4de0d7a2ea9f21cf4a6 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 10:08:24 +0200 Subject: [PATCH 104/118] Added patch files. --- patches/patches/026_hello2.patch | 8 ++++---- patches/patches/034_quiz4.patch | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/patches/patches/026_hello2.patch b/patches/patches/026_hello2.patch index f0224a1..f99cc67 100644 --- a/patches/patches/026_hello2.patch +++ b/patches/patches/026_hello2.patch @@ -1,9 +1,9 @@ ---- exercises/026_hello2.zig 2023-10-03 22:15:22.122241138 +0200 -+++ answers/026_hello2.zig 2023-10-05 20:04:06.959431737 +0200 +--- exercises/026_hello2.zig 2025-07-22 09:55:51.337832401 +0200 ++++ answers/026_hello2.zig 2025-07-22 10:00:11.233348058 +0200 @@ -23,5 +23,5 @@ // to be able to pass it up as a return value of main(). // // We just learned of a single statement which can accomplish this. -- stdout.print("Hello world!\n", .{}); -+ try stdout.print("Hello world!\n", .{}); +- stdout.interface.print("Hello world!\n", .{}); ++ try stdout.interface.print("Hello world!\n", .{}); } diff --git a/patches/patches/034_quiz4.patch b/patches/patches/034_quiz4.patch index 8c0bc0e..15c95fc 100644 --- a/patches/patches/034_quiz4.patch +++ b/patches/patches/034_quiz4.patch @@ -1,15 +1,15 @@ ---- exercises/034_quiz4.zig 2023-10-03 22:15:22.122241138 +0200 -+++ answers/034_quiz4.zig 2023-10-05 20:04:06.996099091 +0200 +--- exercises/034_quiz4.zig 2025-07-22 09:55:51.337832401 +0200 ++++ answers/034_quiz4.zig 2025-07-22 10:05:08.320323184 +0200 @@ -9,10 +9,10 @@ const NumError = error{IllegalNumber}; -pub fn main() void { +pub fn main() !void { - const stdout = std.io.getStdOut().writer(); + var stdout = std.fs.File.stdout().writer(&.{}); - const my_num: u32 = getNumber(); + const my_num: u32 = try getNumber(); - try stdout.print("my_num={}\n", .{my_num}); + try stdout.interface.print("my_num={}\n", .{my_num}); } From 54f48c75c415f03acba5c3744454e7e9e45840d4 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 10:16:17 +0200 Subject: [PATCH 105/118] Fixed 82 --- build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig b/build.zig index ebe6838..f3dd2d2 100644 --- a/build.zig +++ b/build.zig @@ -1063,7 +1063,7 @@ const exercises = [_]Exercise{ .{ .main_file = "082_anonymous_structs3.zig", .output = - \\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.141592e0 + \\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.141592 , .hint = "This one is a challenge! But you have everything you need.", }, From 0d06220ec5d0623cef4d90a019040a984e9317f5 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 10:24:22 +0200 Subject: [PATCH 106/118] Fixed 98 --- exercises/098_bit_manipulation2.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/098_bit_manipulation2.zig b/exercises/098_bit_manipulation2.zig index 979b103..8b51265 100644 --- a/exercises/098_bit_manipulation2.zig +++ b/exercises/098_bit_manipulation2.zig @@ -32,7 +32,7 @@ const print = std.debug.print; pub fn main() !void { // let's check the pangram - print("Is this a pangram? {?}!\n", .{isPangram("The quick brown fox jumps over the lazy dog.")}); + print("Is this a pangram? {}!\n", .{isPangram("The quick brown fox jumps over the lazy dog.")}); } fn isPangram(str: []const u8) bool { @@ -45,7 +45,7 @@ fn isPangram(str: []const u8) bool { // loop about all characters in the string for (str) |c| { // if the character is an alphabetical character - if (ascii.isASCII(c) and ascii.isAlphabetic(c)) { + if (ascii.isAscii(c) and ascii.isAlphabetic(c)) { // then we set the bit at the position // // to do this, we use a little trick: From f4619868961828bc943cd29d4e2c99edd76fbb00 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 10:30:19 +0200 Subject: [PATCH 107/118] Fixed 104 --- exercises/104_threading.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/104_threading.zig b/exercises/104_threading.zig index 9c4e216..638769f 100644 --- a/exercises/104_threading.zig +++ b/exercises/104_threading.zig @@ -106,7 +106,7 @@ pub fn main() !void { // After the threads have been started, // they run in parallel and we can still do some work in between. - std.time.sleep(1500 * std.time.ns_per_ms); + std.Thread.sleep(1500 * std.time.ns_per_ms); std.debug.print("Some weird stuff, after starting the threads.\n", .{}); } // After we have left the closed area, we wait until @@ -117,12 +117,12 @@ pub fn main() !void { // This function is started with every thread that we set up. // In our example, we pass the number of the thread as a parameter. fn thread_function(num: usize) !void { - std.time.sleep(200 * num * std.time.ns_per_ms); + std.Thread.sleep(200 * num * std.time.ns_per_ms); std.debug.print("thread {d}: {s}\n", .{ num, "started." }); // This timer simulates the work of the thread. const work_time = 3 * ((5 - num % 3) - 2); - std.time.sleep(work_time * std.time.ns_per_s); + std.Thread.sleep(work_time * std.time.ns_per_s); std.debug.print("thread {d}: {s}\n", .{ num, "finished." }); } From 4044b93dd210cb3eb8c1993f2be0e286c4383f2f Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Tue, 22 Jul 2025 10:45:09 +0200 Subject: [PATCH 108/118] Added Readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a6e760f..b497666 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,8 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.14.0-dev.1573 +Version-0.15.0-dev.1092 +* *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) From 9bff77a12a4f6eedeadbd2ad6076be4fe2c4e804 Mon Sep 17 00:00:00 2001 From: DoKoB Date: Tue, 5 Aug 2025 08:11:36 +0530 Subject: [PATCH 109/118] fix: initial zig build caused by self.step.evalZigProcess() --- build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.zig b/build.zig index f3dd2d2..8b22a3c 100644 --- a/build.zig +++ b/build.zig @@ -519,7 +519,7 @@ const ZiglingStep = struct { // NOTE: After many changes in zig build system, we need to create the cache path manually. // See https://github.com/ziglang/zig/pull/21115 // Maybe there is a better way (in the future). - const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false); + const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false, null, b.allocator); const exe_name = switch (self.exercise.kind) { .exe => self.exercise.name(), .@"test" => "test", From fd310273a7aeecbf877057a62c3f32bc1405c926 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 8 Aug 2025 20:34:59 +0200 Subject: [PATCH 110/118] Current version set --- README.md | 1 + build.zig | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b497666..c3fc8a0 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ that if you update one, you may need to also update the other. ### Version Changes Version-0.15.0-dev.1092 +* *2025-08-08* zig 0.15.0-dev.1380 - changes in build system, see [#24588](https://github.com/ziglang/zig/pull/24588) * *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) diff --git a/build.zig b/build.zig index 8b22a3c..eaf4646 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.15.0-dev.1092"; + const required_zig = "0.15.0-dev.1380"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { From 80528613c2a1d2b9685c0d8fbe2a1357ecf265d8 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Mon, 11 Aug 2025 09:52:58 +0200 Subject: [PATCH 111/118] Fixed zig version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c3fc8a0..7800942 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.15.0-dev.1092 +Version-0.15.0-dev.1380 * *2025-08-08* zig 0.15.0-dev.1380 - changes in build system, see [#24588](https://github.com/ziglang/zig/pull/24588) * *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) From 06e56be9c5568a996815941847b3373a5f268029 Mon Sep 17 00:00:00 2001 From: Sardorbek Imomaliev Date: Mon, 11 Aug 2025 20:57:17 +0100 Subject: [PATCH 112/118] fix: 019 typo in example function, missing return type --- exercises/019_functions2.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/019_functions2.zig b/exercises/019_functions2.zig index a527ae2..5a76c7b 100644 --- a/exercises/019_functions2.zig +++ b/exercises/019_functions2.zig @@ -3,7 +3,7 @@ // example that takes two parameters. As you can see, parameters // are declared just like any other types ("name": "type"): // -// fn myFunction(number: u8, is_lucky: bool) { +// fn myFunction(number: u8, is_lucky: bool) void { // ... // } // From aeacadb76be91619417d3d13df20b25a0ca21392 Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 15 Aug 2025 15:00:53 +0200 Subject: [PATCH 113/118] Fixed changes in array list --- README.md | 1 + build.zig | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7800942..ca2069a 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ that if you update one, you may need to also update the other. ### Version Changes Version-0.15.0-dev.1380 +* *2025-08-08* zig 0.15.0-dev.1519 - changes in array listr, see [#24801](https://github.com/ziglang/zig/pull/24801) * *2025-08-08* zig 0.15.0-dev.1380 - changes in build system, see [#24588](https://github.com/ziglang/zig/pull/24588) * *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) diff --git a/build.zig b/build.zig index eaf4646..e72dd4d 100644 --- a/build.zig +++ b/build.zig @@ -15,7 +15,7 @@ const print = std.debug.print; // 1) Getting Started // 2) Version Changes comptime { - const required_zig = "0.15.0-dev.1380"; + const required_zig = "0.15.0-dev.1519"; const current_zig = builtin.zig_version; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; if (current_zig.order(min_zig) == .lt) { @@ -492,7 +492,7 @@ const ZiglingStep = struct { const path = join(b.allocator, &.{ self.work_path, exercise_path }) catch @panic("OOM"); - var zig_args = std.ArrayList([]const u8).init(b.allocator); + var zig_args = std.array_list.Managed([]const u8).init(b.allocator); defer zig_args.deinit(); zig_args.append(b.graph.zig_exe) catch @panic("OOM"); @@ -581,17 +581,17 @@ fn resetLine() void { /// Removes trailing whitespace for each line in buf, also ensuring that there /// are no trailing LF characters at the end. pub fn trimLines(allocator: std.mem.Allocator, buf: []const u8) ![]const u8 { - var list = try std.ArrayList(u8).initCapacity(allocator, buf.len); + var list = try std.array_list.Aligned(u8, null).initCapacity(allocator, buf.len); var iter = std.mem.splitSequence(u8, buf, " \n"); while (iter.next()) |line| { // TODO: trimming CR characters is probably not necessary. const data = std.mem.trimRight(u8, line, " \r"); - try list.appendSlice(data); - try list.append('\n'); + try list.appendSlice(allocator, data); + try list.append(allocator, '\n'); } - const result = try list.toOwnedSlice(); // TODO: probably not necessary + const result = try list.toOwnedSlice(allocator); // TODO: probably not necessary // Remove the trailing LF character, that is always present in the exercise // output. From b580f7e30ec2adf7656e2d690adc7fb187bcdfed Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 15 Aug 2025 15:03:10 +0200 Subject: [PATCH 114/118] adjusted version information --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ca2069a..bf84593 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,6 @@ that if you update one, you may need to also update the other. ### Version Changes -Version-0.15.0-dev.1380 * *2025-08-08* zig 0.15.0-dev.1519 - changes in array listr, see [#24801](https://github.com/ziglang/zig/pull/24801) * *2025-08-08* zig 0.15.0-dev.1380 - changes in build system, see [#24588](https://github.com/ziglang/zig/pull/24588) * *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) From 1ca8b90589f598cd209ebab5586aa8c76773c67f Mon Sep 17 00:00:00 2001 From: Chris Boesch Date: Fri, 15 Aug 2025 15:10:47 +0200 Subject: [PATCH 115/118] fixed typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf84593..913d6b3 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ that if you update one, you may need to also update the other. ### Version Changes -* *2025-08-08* zig 0.15.0-dev.1519 - changes in array listr, see [#24801](https://github.com/ziglang/zig/pull/24801) +* *2025-08-15* zig 0.15.0-dev.1519 - changes in array list, see [#24801](https://github.com/ziglang/zig/pull/24801) * *2025-08-08* zig 0.15.0-dev.1380 - changes in build system, see [#24588](https://github.com/ziglang/zig/pull/24588) * *2025-07-22* zig 0.15.0-dev.1092 - various changes due to new I/O API, see [#24488](https://github.com/ziglang/zig/pull/24488) * *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257) From 02db8326778072c638b84293b30b55999f5ba585 Mon Sep 17 00:00:00 2001 From: "Simon 'Sze' L. Schlee" Date: Sun, 24 Aug 2025 03:08:17 +0200 Subject: [PATCH 116/118] pass -freference-trace to executed compile command Currently users executing `zig build` to run the exercises, may encounter compiler output that tells them to use `-freference-trace=[num]` to see more of the hidden reference traces, so we should pass this parameter to the zigling exercise being compiled, so that the learner can provide this parameter like they would normally, when using `zig build` directly in normal Zig programs. --- build.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.zig b/build.zig index e72dd4d..7e8bf7a 100644 --- a/build.zig +++ b/build.zig @@ -508,6 +508,10 @@ const ZiglingStep = struct { zig_args.append("-lc") catch @panic("OOM"); } + if (b.reference_trace) |rt| { + zig_args.append(b.fmt("-freference-trace={}", .{rt})) catch @panic("OOM"); + } + zig_args.append(b.pathFromRoot(path)) catch @panic("OOM"); zig_args.append("--cache-dir") catch @panic("OOM"); From 63640875699059e44a5f15b1521b17b42ef1da27 Mon Sep 17 00:00:00 2001 From: Chris Boesch <48591413+chrboesch@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:42:03 +0200 Subject: [PATCH 117/118] fixed version numbers --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 913d6b3..9be565f 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Verify the installation and build number of `zig` like so: ``` $ zig version -0.15.0-dev.xxxx+xxxxxxxxx +0.16.0-dev.xxxx+xxxxxxxxx ``` Clone this repository with Git: @@ -73,8 +73,8 @@ the appropriate tag. The Zig language is under very active development. In order to be current, Ziglings tracks **development** builds of the Zig compiler rather than versioned **release** builds. The last -stable release was `0.14.1`, but Ziglings needs a dev build with -pre-release version "0.15.0" and a build number at least as high +stable release was `0.15.1`, but Ziglings needs a dev build with +pre-release version "0.16.0" and a build number at least as high as that shown in the example version check above. It is likely that you'll download a build which is _greater_ than From 16ec20747190fa0d02ca8872cebbba4e0581b08d Mon Sep 17 00:00:00 2001 From: Chris Boesch <48591413+chrboesch@users.noreply.github.com> Date: Sun, 24 Aug 2025 14:50:42 +0200 Subject: [PATCH 118/118] fixed typo and broken link --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 9be565f..fd45a06 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,9 @@ language such as C. Each exercise is self-contained and self-explained. However, you're encouraged to also check out these Zig language resources -for more detail: +for more details: * https://ziglang.org/learn/ -* https://ziglearn.org/ * https://ziglang.org/documentation/master/ * [Zig in Depth! (video series)](https://www.youtube.com/watch?v=MMtvGA1YhW4&list=PLtB7CL7EG7pCw7Xy1SQC53Gl8pI7aDg9t&pp=iAQB)