# Appendix I. Exercise Answers

### Appendix I. Exercise Answers

These are short answers or sketches for selected exercises from the book. Many exercises have several reasonable solutions. The important part is clarity and correctness.

### I.1 Hello, Zig

Exercise 1-1. Run the first program.

```sh
zig run main.zig
```

Exercise 1-2. Change the message.

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("goodbye\n", .{});
}
```

Exercise 1-3. Print two lines.

```zig
const std = @import("std");

pub fn main() void {
    std.debug.print("first\nsecond\n", .{});
}
```

Exercise 1-4. Print a string value.

```zig
const std = @import("std");

pub fn main() void {
    const name = "zig";

    std.debug.print("{s}\n", .{name});
}
```

### I.2 Variables and Types

Exercise 2-1. Swap two integers.

```zig
var a: i32 = 10;
var b: i32 = 20;

const tmp = a;
a = b;
b = tmp;
```

Exercise 2-2. Print an integer and a float.

```zig
const std = @import("std");

pub fn main() void {
    const i: i32 = 10;
    const f: f64 = 3.14;

    std.debug.print("{d} {d}\n", .{ i, f });
}
```

Exercise 2-3. Convert an integer.

```zig
const x: i32 = 10;
const y: u32 = @intCast(x);
```

### I.3 Control Flow

Exercise 3-1. Print numbers from 0 to 9.

```zig
const std = @import("std");

pub fn main() void {
    var i: usize = 0;

    while (i < 10) : (i += 1) {
        std.debug.print("{d}\n", .{i});
    }
}
```

Exercise 3-2. Sum an array.

```zig
const items = [_]i32{ 1, 2, 3, 4 };

var sum: i32 = 0;

for (items) |item| {
    sum += item;
}
```

Exercise 3-3. Use `switch`.

```zig
switch (ch) {
    'a', 'e', 'i', 'o', 'u' => vowel(),
    else => consonant(),
}
```

### I.4 Functions

Exercise 4-1. Maximum of two integers.

```zig
fn max(a: i32, b: i32) i32 {
    return if (a > b) a else b;
}
```

Exercise 4-2. Absolute value.

```zig
fn abs(x: i32) i32 {
    return if (x < 0) -x else x;
}
```

Exercise 4-3. Recursive factorial.

```zig
fn fact(n: u32) u32 {
    if (n == 0) {
        return 1;
    }

    return n * fact(n - 1);
}
```

### I.5 Arrays and Slices

Exercise 5-1. Reverse an array in place.

```zig
fn reverse(items: []u8) void {
    var i: usize = 0;
    var j: usize = items.len;

    while (i < j) {
        j -= 1;

        const tmp = items[i];
        items[i] = items[j];
        items[j] = tmp;

        i += 1;
    }
}
```

Exercise 5-2. Find the largest value.

```zig
fn max(items: []const i32) i32 {
    var m = items[0];

    for (items[1..]) |item| {
        if (item > m) {
            m = item;
        }
    }

    return m;
}
```

### I.6 Structs

Exercise 6-1. Define a point.

```zig
const Point = struct {
    x: i32,
    y: i32,
};
```

Exercise 6-2. Add two points.

```zig
fn add(a: Point, b: Point) Point {
    return .{
        .x = a.x + b.x,
        .y = a.y + b.y,
    };
}
```

Exercise 6-3. Zero constructor.

```zig
const Point = struct {
    x: i32,
    y: i32,

    fn zero() Point {
        return .{
            .x = 0,
            .y = 0,
        };
    }
};
```

### I.7 Errors

Exercise 7-1. Return an error for division by zero.

```zig
const MathError = error{
    DivideByZero,
};

fn divide(a: i32, b: i32) MathError!i32 {
    if (b == 0) {
        return error.DivideByZero;
    }

    return @divTrunc(a, b);
}
```

Exercise 7-2. Use `try`.

```zig
const result = try divide(a, b);
```

Exercise 7-3. Use `catch`.

```zig
const result = divide(a, b) catch 0;
```

### I.8 Optionals

Exercise 8-1. Return the first element or null.

```zig
fn first(items: []const i32) ?i32 {
    if (items.len == 0) {
        return null;
    }

    return items[0];
}
```

Exercise 8-2. Use `orelse`.

```zig
const value = first(items) orelse -1;
```

### I.9 Allocation

Exercise 9-1. Allocate an array.

```zig
const buf = try allocator.alloc(u8, 1024);
defer allocator.free(buf);
```

Exercise 9-2. Duplicate a string.

```zig
const copy = try allocator.dupe(u8, text);
defer allocator.free(copy);
```

### I.10 Array Lists

Exercise 10-1. Append numbers.

```zig
var list = std.ArrayList(i32).init(allocator);
defer list.deinit();

try list.append(1);
try list.append(2);
try list.append(3);
```

Exercise 10-2. Sum the list.

```zig
var sum: i32 = 0;

for (list.items) |item| {
    sum += item;
}
```

### I.11 Strings

Exercise 11-1. Count spaces.

```zig
fn countSpaces(text: []const u8) usize {
    var n: usize = 0;

    for (text) |ch| {
        if (ch == ' ') {
            n += 1;
        }
    }

    return n;
}
```

Exercise 11-2. Compare two strings.

```zig
const same = std.mem.eql(u8, a, b);
```

### I.12 Files

Exercise 12-1. Read a file.

```zig
const std = @import("std");

pub fn main() !void {
    const allocator = std.heap.page_allocator;

    const file = try std.fs.cwd().openFile(
        "data.txt",
        .{},
    );
    defer file.close();

    const data = try file.readToEndAlloc(
        allocator,
        1024 * 1024,
    );
    defer allocator.free(data);

    std.debug.print("{s}\n", .{data});
}
```

Exercise 12-2. Copy standard input to standard output.

```zig
const std = @import("std");

pub fn main() !void {
    var buf: [1024]u8 = undefined;

    const stdin = std.io.getStdIn().reader();
    const stdout = std.io.getStdOut().writer();

    while (true) {
        const n = try stdin.read(&buf);

        if (n == 0) {
            break;
        }

        try stdout.writeAll(buf[0..n]);
    }
}
```

### I.13 Generic Functions

Exercise 13-1. Generic swap.

```zig
fn swap(comptime T: type, a: *T, b: *T) void {
    const tmp = a.*;
    a.* = b.*;
    b.* = tmp;
}
```

Exercise 13-2. Generic maximum.

```zig
fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}
```

### I.14 Testing

Exercise 14-1. Test a function.

```zig
const std = @import("std");

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "addition" {
    try std.testing.expect(add(2, 3) == 5);
}
```

Run:

```sh
zig test main.zig
```

### I.15 Small Programs

Exercise 15-1. Count lines.

```zig
const std = @import("std");

pub fn main() !void {
    var buf: [1024]u8 = undefined;

    const stdin = std.io.getStdIn().reader();

    var count: usize = 0;

    while (true) {
        const n = try stdin.read(&buf);

        if (n == 0) {
            break;
        }

        for (buf[0..n]) |ch| {
            if (ch == '\n') {
                count += 1;
            }
        }
    }

    std.debug.print("{d}\n", .{count});
}
```

Exercise 15-2. Hex dump.

```zig
for (data, 0..) |byte, i| {
    std.debug.print("{x:0>2} ", .{byte});

    if ((i + 1) % 16 == 0) {
        std.debug.print("\n", .{});
    }
}
```

### I.16 Final Note

The exercises are small on purpose. Write short programs first. Keep interfaces narrow. Allocate explicitly. Handle errors immediately. Reduce hidden state. The language becomes simpler as the program becomes clearer.

