mirror of
https://codeberg.org/ziglings/exercises.git
synced 2026-06-08 07:50:00 +00:00
Compare commits
9 Commits
beeca8d510
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a89702b2 | ||
|
|
72a441a6bd | ||
|
|
6aaf048935 | ||
|
|
febc5e8bd2 | ||
|
|
b7ff71cb9e | ||
|
|
a403436fe8 | ||
|
|
3b865a0c17 | ||
|
|
63c798637c | ||
|
|
4480762e83 |
@@ -44,7 +44,7 @@ in that case, you can download it directly from the [build directory](https://zi
|
|||||||
Verify the installation and build number of `zig` like so:
|
Verify the installation and build number of `zig` like so:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ zig version
|
zig version
|
||||||
0.17.0-dev.xxxx+xxxxxxxxx
|
0.17.0-dev.xxxx+xxxxxxxxx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -93,36 +93,25 @@ pub fn main() void {
|
|||||||
|
|
||||||
print("He has room in his heart for:", .{});
|
print("He has room in his heart for:", .{});
|
||||||
|
|
||||||
// A StructFields array
|
// `field_names` is a slice of strings and it holds the names of the struct's fields
|
||||||
const fields = @typeInfo(Narcissus).@"struct".fields;
|
// `field_types` is a slice of strings and it holds the types of the struct's fields,
|
||||||
|
// it is guaranteed to be the same length as `field_names`
|
||||||
|
const field_names = @typeInfo(Narcissus).@"struct".field_names;
|
||||||
|
const field_types = @typeInfo(Narcissus).@"struct".field_types;
|
||||||
|
|
||||||
// 'fields' is a slice of StructFields. Here's the declaration:
|
|
||||||
//
|
|
||||||
// pub const StructField = struct {
|
|
||||||
// name: [:0]const u8, // Don't worry about `:0` yet!
|
|
||||||
// type: type,
|
|
||||||
// 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
|
// Please complete these 'if' statements so that the field
|
||||||
// name will not be printed if the field is of type '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!):
|
// (which is a zero-bit type that takes up no space at all!):
|
||||||
if (fields[0].??? != void) {
|
if (field_???[???] != void) {
|
||||||
print(" {s}", .{fields[0].name});
|
print(" {s}", .{field_???[???]});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields[1].??? != void) {
|
if (field_???[???] != void) {
|
||||||
print(" {s}", .{fields[1].name});
|
print(" {s}", .{field_???[???]});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fields[2].??? != void) {
|
if (field_???[???] != void) {
|
||||||
print(" {s}", .{fields[2].name});
|
print(" {s}", .{field_???[???]});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Yuck, look at all that repeated code above! I don't know
|
// Yuck, look at all that repeated code above! I don't know
|
||||||
|
|||||||
@@ -36,13 +36,14 @@ pub fn main() void {
|
|||||||
// statement was repeated three times almost verbatim. Yuck!
|
// statement was repeated three times almost verbatim. Yuck!
|
||||||
//
|
//
|
||||||
// Please use an 'inline for' to implement the block below
|
// Please use an 'inline for' to implement the block below
|
||||||
// for each field in the slice 'fields'!
|
// for each field in the corresponding slices (they're of the same length)!
|
||||||
|
|
||||||
const fields = @typeInfo(Narcissus).@"struct".fields;
|
const field_names = @typeInfo(Narcissus).@"struct".field_names;
|
||||||
|
const field_types = @typeInfo(Narcissus).@"struct".field_types;
|
||||||
|
|
||||||
??? {
|
??? {
|
||||||
if (field.type != void) {
|
if (field_type != void) {
|
||||||
print(" {s}", .{field.name});
|
print(" {s}", .{field_name});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -74,36 +74,27 @@ fn printTuple(tuple: anytype) void {
|
|||||||
// @typeInfo() - takes a type, returns a TypeInfo union
|
// @typeInfo() - takes a type, returns a TypeInfo union
|
||||||
// with fields specific to that type.
|
// with fields specific to that type.
|
||||||
//
|
//
|
||||||
// The list of a struct type's fields can be found in
|
// The list of a struct type's field types can be found in
|
||||||
// TypeInfo's @"struct".fields.
|
// TypeInfo's @"struct".field_types.
|
||||||
//
|
//
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// @typeInfo(Circle).@"struct".fields
|
// @typeInfo(Circle).@"struct".field_types
|
||||||
//
|
//
|
||||||
// This will be an array of StructFields.
|
// This will be an array of field types.
|
||||||
const fields = ???;
|
const field_types = ???;
|
||||||
|
|
||||||
|
// This will be an array of field names.
|
||||||
|
const field_names = ???;
|
||||||
|
|
||||||
// 2. Loop through each field. This must be done at compile
|
// 2. Loop through each field. This must be done at compile
|
||||||
// time.
|
// time.
|
||||||
//
|
//
|
||||||
// Hint: remember 'inline' loops?
|
// Hint: remember 'inline' loops?
|
||||||
//
|
//
|
||||||
for (fields) |field| {
|
for (???, ???) |???, ???| {
|
||||||
// 3. Print the field's name, type, and value.
|
// 3. Print the field's name, type, and value.
|
||||||
//
|
//
|
||||||
// Each 'field' in this loop is one of these:
|
|
||||||
//
|
|
||||||
// pub const StructField = struct {
|
|
||||||
// name: [:0]const u8,
|
|
||||||
// type: type,
|
|
||||||
// default_value_ptr: ?*const anyopaque,
|
|
||||||
// is_comptime: bool,
|
|
||||||
// alignment: comptime_int,
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// Note we will learn about 'anyopaque' type later
|
|
||||||
//
|
|
||||||
// You'll need this builtin:
|
// You'll need this builtin:
|
||||||
//
|
//
|
||||||
// @field(lhs: anytype, comptime field_name: []const u8)
|
// @field(lhs: anytype, comptime field_name: []const u8)
|
||||||
@@ -123,8 +114,8 @@ fn printTuple(tuple: anytype) void {
|
|||||||
// for declarations. If it's a value, it looks for data.
|
// for declarations. If it's a value, it looks for data.
|
||||||
//
|
//
|
||||||
print("\"{s}\"({any}):{any} ", .{
|
print("\"{s}\"({any}):{any} ", .{
|
||||||
field.???,
|
field_name,
|
||||||
field.???,
|
field_type,
|
||||||
???,
|
???,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
--- exercises/065_builtins2.zig 2026-02-27 13:10:36
|
--- exercises/065_builtins2.zig 2026-06-01 15:33:16.617432671 +0200
|
||||||
+++ answers/065_builtins2.zig 2026-02-27 13:10:52
|
+++ answers/065_builtins2.zig 2026-06-01 15:33:31.104018108 +0200
|
||||||
@@ -58,7 +58,7 @@
|
@@ -58,7 +58,7 @@
|
||||||
// Oops! We cannot leave the 'me' and 'myself' fields
|
// Oops! We cannot leave the 'me' and 'myself' fields
|
||||||
// undefined. Please set them here:
|
// undefined. Please set them here:
|
||||||
@@ -18,22 +18,26 @@
|
|||||||
|
|
||||||
// Now we print a pithy statement about Narcissus.
|
// Now we print a pithy statement about Narcissus.
|
||||||
print("A {s} loves all {s}es. ", .{
|
print("A {s} loves all {s}es. ", .{
|
||||||
@@ -113,15 +113,15 @@
|
@@ -102,16 +102,16 @@
|
||||||
// Please complete these 'if' statements so that the field
|
// Please complete these 'if' statements so that the field
|
||||||
// name will not be printed if the field is of type '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!):
|
// (which is a zero-bit type that takes up no space at all!):
|
||||||
- if (fields[0].??? != void) {
|
- if (field_???[???] != void) {
|
||||||
+ if (fields[0].type != void) {
|
- print(" {s}", .{field_???[???]});
|
||||||
print(" {s}", .{fields[0].name});
|
+ if (field_types[0] != void) {
|
||||||
|
+ print(" {s}", .{field_names[0]});
|
||||||
}
|
}
|
||||||
|
|
||||||
- if (fields[1].??? != void) {
|
- if (field_???[???] != void) {
|
||||||
+ if (fields[1].type != void) {
|
- print(" {s}", .{field_???[???]});
|
||||||
print(" {s}", .{fields[1].name});
|
+ if (field_types[1] != void) {
|
||||||
|
+ print(" {s}", .{field_names[1]});
|
||||||
}
|
}
|
||||||
|
|
||||||
- if (fields[2].??? != void) {
|
- if (field_???[???] != void) {
|
||||||
+ if (fields[2].type != void) {
|
- print(" {s}", .{field_???[???]});
|
||||||
print(" {s}", .{fields[2].name});
|
+ if (field_types[2] != void) {
|
||||||
|
+ print(" {s}", .{field_names[2]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Yuck, look at all that repeated code above! I don't know
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
--- exercises/071_comptime6.zig 2024-09-02 19:21:50.250454978 +0200
|
--- exercises/071_comptime6.zig 2026-06-01 15:35:27.223400223 +0200
|
||||||
+++ answers/071_comptime6.zig 2024-09-02 19:21:23.553250563 +0200
|
+++ answers/071_comptime6.zig 2026-06-01 15:36:35.349728561 +0200
|
||||||
@@ -40,7 +40,7 @@
|
@@ -41,7 +41,7 @@
|
||||||
|
const field_names = @typeInfo(Narcissus).@"struct".field_names;
|
||||||
const fields = @typeInfo(Narcissus).@"struct".fields;
|
const field_types = @typeInfo(Narcissus).@"struct".field_types;
|
||||||
|
|
||||||
- ??? {
|
- ??? {
|
||||||
+ inline for (fields) |field| {
|
+ inline for (field_names, field_types) |field_name, field_type| {
|
||||||
if (field.type != void) {
|
if (field_type != void) {
|
||||||
print(" {s}", .{field.name});
|
print(" {s}", .{field_name});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,32 @@
|
|||||||
--- exercises/082_anonymous_structs3.zig 2026-02-27 13:05:46
|
--- exercises/082_anonymous_structs3.zig 2026-06-01 15:59:11.872467805 +0200
|
||||||
+++ answers/082_anonymous_structs3.zig 2026-02-27 13:07:22
|
+++ answers/082_anonymous_structs3.zig 2026-06-01 15:58:38.004730144 +0200
|
||||||
@@ -82,14 +82,14 @@
|
@@ -82,17 +82,17 @@
|
||||||
// @typeInfo(Circle).@"struct".fields
|
// @typeInfo(Circle).@"struct".field_types
|
||||||
//
|
//
|
||||||
// This will be an array of StructFields.
|
// This will be an array of field types.
|
||||||
- const fields = ???;
|
- const field_types = ???;
|
||||||
+ const fields = @typeInfo(@TypeOf(tuple)).@"struct".fields;
|
+ const field_types = @typeInfo(@TypeOf(tuple)).@"struct".field_types;
|
||||||
|
|
||||||
|
// This will be an array of field names.
|
||||||
|
- const field_names = ???;
|
||||||
|
+ const field_names = @typeInfo(@TypeOf(tuple)).@"struct".field_names;
|
||||||
|
|
||||||
// 2. Loop through each field. This must be done at compile
|
// 2. Loop through each field. This must be done at compile
|
||||||
// time.
|
// time.
|
||||||
//
|
//
|
||||||
// Hint: remember 'inline' loops?
|
// Hint: remember 'inline' loops?
|
||||||
//
|
//
|
||||||
- for (fields) |field| {
|
- for (???, ???) |???, ???| {
|
||||||
+ inline for (fields) |field| {
|
+ inline for (field_types, field_names) |field_type, field_name| {
|
||||||
// 3. Print the field's name, type, and value.
|
// 3. Print the field's name, type, and value.
|
||||||
//
|
//
|
||||||
// Each 'field' in this loop is one of these:
|
// You'll need this builtin:
|
||||||
@@ -123,9 +123,9 @@
|
@@ -116,7 +116,7 @@
|
||||||
// for declarations. If it's a value, it looks for data.
|
|
||||||
//
|
|
||||||
print("\"{s}\"({any}):{any} ", .{
|
print("\"{s}\"({any}):{any} ", .{
|
||||||
- field.???,
|
field_name,
|
||||||
- field.???,
|
field_type,
|
||||||
- ???,
|
- ???,
|
||||||
+ field.name,
|
+ @field(tuple, field_name),
|
||||||
+ field.type,
|
|
||||||
+ @field(tuple, field.name),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const builtin = @import("builtin");
|
|||||||
|
|
||||||
const Process = std.process;
|
const Process = std.process;
|
||||||
const print = std.debug.print;
|
const print = std.debug.print;
|
||||||
|
const cutPrefix = std.mem.cutPrefix;
|
||||||
|
|
||||||
const progress_filename = ".progress.txt";
|
const progress_filename = ".progress.txt";
|
||||||
|
|
||||||
@@ -102,6 +103,16 @@ pub const Exercise = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Shared, read-only run context threaded through the helpers.
|
||||||
|
const Context = struct {
|
||||||
|
io: std.Io,
|
||||||
|
arena: std.mem.Allocator,
|
||||||
|
zig_exe: []const u8,
|
||||||
|
work_path: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Error = error{Failed};
|
||||||
|
|
||||||
// Ansi colors.
|
// Ansi colors.
|
||||||
var use_color_escapes = false;
|
var use_color_escapes = false;
|
||||||
var red_text: []const u8 = "";
|
var red_text: []const u8 = "";
|
||||||
@@ -138,7 +149,8 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
const io = init.io;
|
const io = init.io;
|
||||||
const arena = init.arena.allocator();
|
const arena = init.arena.allocator();
|
||||||
|
|
||||||
const args = try init.minimal.args.toSlice(arena);
|
var args_it = try init.minimal.args.iterateAllocator(arena);
|
||||||
|
if (!args_it.skip()) @panic("expected self arg");
|
||||||
|
|
||||||
setupColors(io);
|
setupColors(io);
|
||||||
|
|
||||||
@@ -150,22 +162,21 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
var only_n: ?usize = null;
|
var only_n: ?usize = null;
|
||||||
var start_n: ?usize = null;
|
var start_n: ?usize = null;
|
||||||
|
|
||||||
for (1..args.len) |n| {
|
while (args_it.next()) |arg| {
|
||||||
const arg = args[n];
|
|
||||||
if (std.mem.eql(u8, arg, "--logo")) {
|
if (std.mem.eql(u8, arg, "--logo")) {
|
||||||
print("{s}{s}{s}", .{ yellow_text, logo, reset_text });
|
print("{s}{s}{s}", .{ yellow_text, logo, reset_text });
|
||||||
return;
|
return;
|
||||||
} else if (prefix(arg, "--zig=")) |v| {
|
} else if (cutPrefix(u8, arg, "--zig=")) |v| {
|
||||||
zig_exe = v;
|
zig_exe = v;
|
||||||
} else if (prefix(arg, "--work-path=")) |v| {
|
} else if (cutPrefix(u8, arg, "--work-path=")) |v| {
|
||||||
work_path = v;
|
work_path = v;
|
||||||
} else if (prefix(arg, "--only=")) |v| {
|
} else if (cutPrefix(u8, arg, "--only=")) |v| {
|
||||||
only_n = std.fmt.parseInt(usize, v, 10) catch {
|
only_n = std.fmt.parseInt(usize, v, 10) catch {
|
||||||
print("invalid --only value: {s}\n", .{v});
|
print("invalid --only value: {s}\n", .{v});
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
};
|
};
|
||||||
mode = .named;
|
mode = .named;
|
||||||
} else if (prefix(arg, "--start=")) |v| {
|
} else if (cutPrefix(u8, arg, "--start=")) |v| {
|
||||||
start_n = std.fmt.parseInt(usize, v, 10) catch {
|
start_n = std.fmt.parseInt(usize, v, 10) catch {
|
||||||
print("invalid --start value: {s}\n", .{v});
|
print("invalid --start value: {s}\n", .{v});
|
||||||
std.process.exit(1);
|
std.process.exit(1);
|
||||||
@@ -181,7 +192,12 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
|
|
||||||
print("{s}", .{logo});
|
print("{s}", .{logo});
|
||||||
|
|
||||||
const ctx: Context = .{ .io = io, .arena = arena, .zig_exe = zig_exe, .work_path = work_path };
|
const ctx: Context = .{
|
||||||
|
.io = io,
|
||||||
|
.arena = arena,
|
||||||
|
.zig_exe = zig_exe,
|
||||||
|
.work_path = work_path,
|
||||||
|
};
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
.named => {
|
.named => {
|
||||||
@@ -230,21 +246,6 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prefix(arg: []const u8, pre: []const u8) ?[]const u8 {
|
|
||||||
if (std.mem.startsWith(u8, arg, pre)) return arg[pre.len..];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shared, read-only run context threaded through the helpers.
|
|
||||||
const Context = struct {
|
|
||||||
io: std.Io,
|
|
||||||
arena: std.mem.Allocator,
|
|
||||||
zig_exe: []const u8,
|
|
||||||
work_path: []const u8,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Error = error{Failed};
|
|
||||||
|
|
||||||
// Iterates exercises from `start_index` to the end, stopping at the first failure.
|
// Iterates exercises from `start_index` to the end, stopping at the first failure.
|
||||||
// Progress is written after each passed exercise.
|
// Progress is written after each passed exercise.
|
||||||
fn iterateFrom(ctx: Context, start_index: usize) Error!void {
|
fn iterateFrom(ctx: Context, start_index: usize) Error!void {
|
||||||
|
|||||||
Reference in New Issue
Block a user