Compare commits

...

117 commits

Author SHA1 Message Date
Norman Köhring
e8270de928 some exercises 2024-05-27 15:21:28 +02:00
Chris Boesch
776316e60b Merge pull request 'Update exercises/105_threading2.zig' (#95) from rpm0372/exercises:TypoIn105 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/95
2024-05-12 11:50:56 +00:00
rpm0372
efe2d19c69 Update exercises/105_threading2.zig
The last word, '"diggits" was misspelled.
2024-05-11 22:38:15 +00:00
Chris Boesch
49c54fb075 Merge pull request 'Nobody wants the long version of finding out if a variable is set.' (#94) from minor_improvements into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/94
2024-05-10 21:40:54 +00:00
Chris Boesch
67f87a76c2
Nobody wants the long version of finding out if a variable is set.
So switched to the short version with 'orelse'. ;)
2024-05-10 23:21:04 +02:00
Chris Boesch
dfdaf03d99 Merge pull request 'Add devcontainer config' (#90) from aquilarafa/exercises:add-devcontainer into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/90
2024-05-06 15:17:52 +00:00
Rafael Áquila
5da194ba9c Add devcontainer.json 2024-05-06 07:47:27 -03:00
Chris Boesch
8345e839b0 Merge pull request 'Fix some typos' (#89) from typos into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/89
2024-05-06 07:25:18 +00:00
Chris Boesch
6c23f2682e Merge branch 'main' into typos 2024-05-06 07:20:37 +00:00
Chris Boesch
19bd8745e4
Fix some typos 2024-05-06 09:13:56 +02:00
Chris Boesch
1ac46d7a42 Merge pull request 'Fix patches for 106 and 107' (#88) from wp433 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/88
2024-05-04 23:27:01 +00:00
Chris Boesch
165cc199ca
Fix patches for 106 and 107 2024-05-05 01:16:23 +02:00
Chris Boesch
e182d1f19d Merge pull request 'fix: typos in exercises 094 and 098' (#87) from d-hain/ziglings-exercises:typo-fix-094-098 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/87
2024-05-04 22:46:16 +00:00
Chris Boesch
09e2f37a50 Merge branch 'main' into typo-fix-094-098 2024-05-04 22:45:32 +00:00
Chris Boesch
27db3112f9 Merge pull request 'fix: typo: % instead of @ for a builtin function' (#85) from d-hain/ziglings-exercises:094_c_math-typo-fix into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/85
2024-05-04 22:34:11 +00:00
David Hain
8cb2a5aa3c fix: some grammatical errors 2024-05-04 22:53:04 +02:00
David Hain
c936c5e123 fix: many grammatical errors 2024-05-04 22:35:07 +02:00
David Hain
5c2354a1bf fix: typo: removed extra s 2024-05-04 21:12:54 +02:00
David Hain
4dbd056100 fix: typo: % instead of @ for a builtin function 2024-05-04 18:51:00 +02:00
Chris Boesch
9ce4a7d6f0 Merge pull request 'Update .woodpecker/eowyn.yaml' (#83) from wp-patch-2 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/83
2024-04-24 14:58:05 +00:00
Chris Boesch
b484be9ac1 Update .woodpecker/eowyn.yaml
Add pull command
2024-04-24 14:40:01 +00:00
Chris Boesch
a2a0a6e891 Merge pull request 'Update .woodpecker/eowyn.yaml' (#82) from chrboesch-wp-patch-1 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/82
2024-04-24 14:31:07 +00:00
Chris Boesch
e7eaa080b6 Update .woodpecker/eowyn.yaml
Add tag "latest"
2024-04-24 14:20:57 +00:00
Chris Boesch
ce0a6cc91c Merge pull request 'Switch to new zig dev release 0.13' (#81) from r013 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/81
2024-04-20 20:37:30 +00:00
Chris Boesch
c94eb33e44
Switch to new zig dev release 0.13 2024-04-20 22:35:14 +02:00
Chris Boesch
8f36619bd7 Merge pull request 'fixing little typo on exercise 107_files2.zig' (#80) from susubub/exercises:little-typo_107 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/80
2024-04-18 17:55:02 +00:00
susubub
aa74dde367 fixing little typo on exercise 107_files2.zig 2024-04-17 20:04:43 -03:00
Chris Boesch
9432c2b0fd Merge pull request 'Fixed woodpecker warnings' (#79) from pr78 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/79
2024-04-10 21:02:13 +00:00
Chris Boesch
f4f8eb7ff1
Fixed woodpecker warnings 2024-04-10 22:56:33 +02:00
Chris Boesch
72e3d6ebdc Update .woodpecker/eowyn.yml 2024-04-10 18:38:59 +00:00
Chris Boesch
3c9c55df8e Merge pull request 'Additional timer in thread start added' (#77) from I75 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/77
2024-04-10 17:21:18 +00:00
Chris Boesch
376a839672 Merge branch 'main' into I75 2024-04-10 17:16:14 +00:00
Chris Boesch
ba2a9622c4
Additional timer in thread start added 2024-04-10 19:13:46 +02:00
Chris Boesch
2122c477a0 Merge pull request 'Greater gradation of timers built into the threads' (#76) from I75 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/76
2024-04-10 14:18:01 +00:00
Chris Boesch
7732cd7716
Greater gradation of timers built into the threads 2024-04-10 16:06:23 +02:00
Chris Boesch
564916db81 Update README.md 2024-04-03 07:51:19 +00:00
Chris Boesch
84864d808f Merge pull request 'Zig version changed' (#73) from pr72 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/73
2024-04-03 07:47:46 +00:00
Chris Boesch
7875a0f9aa
Zig version changed 2024-04-03 00:37:33 +02:00
Chris Boesch
c0ff1b70c1 Merge pull request 'WIP - fix breaking zig change to @fieldParentPtr' (#72) from kamidev/exercises:fix_zig_breaking_pr_19470 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/72
2024-04-02 22:19:17 +00:00
kamidev
f06c1f27d1
Fix breaking zig change to @fieldParentPtr parameters
See https://github.com/ziglang/zig/pull/19470
2024-03-31 17:02:29 +02:00
Chris Boesch
ba4709b20f Merge pull request 'fix typo' (#70) from i69 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/70
2024-03-28 20:53:46 +00:00
Chris Boesch
e06cdc0b70 Merge branch 'main' into i69 2024-03-28 20:42:35 +00:00
Chris Boesch
86ac326885
fix typo 2024-03-28 21:33:16 +01:00
Chris Boesch
20919722ff Merge pull request 'added exercise/106_files.zig' (#66) from dizzyi_solo/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/66
2024-03-27 18:54:51 +00:00
Chris Boesch
db21ab9855 Merge branch 'main' into main 2024-03-27 18:50:52 +00:00
Alan CHUNG
05589f8ba1 added format parameter {d} 2024-03-27 16:53:19 +08:00
Alan CHUNG
223fc79e44 106 & 107 2024-03-27 16:40:24 +08:00
Alan CHUNG
69bc9a0723 Pass CI test locally 2024-03-26 14:33:25 +08:00
Alan CHUNG
5f74c7f911 specify directory on patch file 106 2024-03-26 14:05:16 +08:00
Alan CHUNG
2c44f3e4ff specify directory on patch file 106 2024-03-26 14:03:54 +08:00
Alan CHUNG
92ea6718b2 remove header of patch files of 106 2024-03-26 14:01:12 +08:00
Alan CHUNG
9bf7a84e56 106_files.patches actual 2024-03-26 13:53:29 +08:00
Alan CHUNG
9ce889b438 106_files.zig actual test 2024-03-26 13:51:59 +08:00
Alan CHUNG
74a6e60e17 add patch files for 106_files.zig 2024-03-25 16:39:45 +08:00
Alan CHUNG
23b11a7509 106_files.zig format 2024-03-25 16:36:15 +08:00
Alan CHUNG
66d08f1e1f modified build.zig 2024-03-25 16:24:42 +08:00
Dizzyi
ec6f6c5870 added exercise/106_files.zig 2024-03-25 01:11:33 +08:00
Chris Boesch
a3de4e3d0f Update .woodpecker/eowyn.yml 2024-03-24 15:57:39 +00:00
Chris Boesch
0d1c76a410 Update .woodpecker/eowyn.yml 2024-03-24 15:55:43 +00:00
Chris Boesch
8e6612a59d Update .woodpecker/eowyn.yml
fix warning
2024-03-24 15:45:53 +00:00
Chris Boesch
95cfeaa606 Update exercises/105_threading2.zig
Fixed typo.
2024-03-23 15:57:33 +00:00
Chris Boesch
dabd9a5a0a Merge pull request 'Added second threading exercise.' (#65) from threading2 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/65
2024-03-23 15:48:08 +00:00
Chris Boesch
d65e3f3f9a
Added second threading exercise. 2024-03-23 16:42:27 +01:00
Chris Boesch
cdaa246131 Merge pull request 'Fixed the renaming of std.os to std.posix' (#64) from fix_63 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/64
2024-03-21 23:28:30 +00:00
Chris Boesch
2b9e3da5c8
Fixed the renaming of std.os to std.posix 2024-03-22 00:25:01 +01:00
Chris Boesch
2092f35127 Merge pull request 'Changes for a new Zig version.' (#60) from version_change into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/60
2024-03-14 23:11:06 +00:00
Chris Boesch
abed92c05e Changes for a new Zig version. 2024-03-15 00:00:17 +01:00
Chris Boesch
5728ccc8eb Merge pull request 'fix exercise 82 output' (#58) from dolichomps/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/58
2024-03-14 22:41:29 +00:00
Chris Boesch
a87e7c895e Merge pull request 'Improved the explanation about passing arguments and added an example.' (#59) from issue51 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/59
2024-03-14 22:40:30 +00:00
Chris Boesch
9844123dd1 Improved the explanation about passing arguments and added an example. 2024-03-14 23:37:14 +01:00
dolichomps
c8f081f3e8 fix exercise 82 output
zig commit bd24e66 changed the floating point formatting implementation so output for exercise 82 no longer matched
2024-03-14 02:28:07 +00:00
Chris Boesch
e3877321b6 Merge pull request 'Minor corrections to the "contributing"' (#56) from contrib into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/56
2024-03-12 20:03:17 +00:00
Chris Boesch
08cc60ba59 Minor corrections to the "contributing" 2024-03-12 20:59:29 +01:00
Chris Boesch
6b46b26c22 Merge pull request 'Fixed unicode literal' (#55) from i52 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/55
2024-03-08 00:09:54 +00:00
Chris Boesch
d0519d18fa Fixed unicode literal 2024-03-08 01:07:57 +01:00
Chris Boesch
9e9cf40453 Merge pull request 'Added threading exercise' (#54) from 104_threading into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/54
2024-03-05 08:22:40 +00:00
Chris Boesch
6984345d0a Added threading exercise 2024-03-05 09:15:57 +01:00
Chris Boesch
277304454a Merge pull request 'Added notes to exercise 94 c_math.' (#53) from 094_c-math into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/53
2024-02-28 12:06:56 +00:00
Chris Boesch
9e48c9a339 Added notes to exercise 94 c_math. 2024-02-28 13:01:11 +01:00
Chris Boesch
48b2032024 Merge pull request 'Zig version adjusted.' (#50) from build_fix into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/50
2024-02-16 15:04:27 +00:00
Chris Boesch
55b2ac4c5f Zig version adjusted. 2024-02-16 15:19:10 +01:00
Chris Boesch
099d0bba93 Merge pull request 'Text improvement' (#48) from chrboesch-patch-1 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/48
2024-02-11 14:12:07 +00:00
Chris Boesch
8257ccb5c8 Text improvement
closes #47
2024-02-11 14:07:37 +00:00
Chris Boesch
4b1ae6117c Merge pull request 'Fix zig_exe location in Build struct' (#45) from asd/ziglings:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/45
2024-02-06 18:36:50 +00:00
Alexander Saltanov
755911747f Fix zig_exe location in Build struct
Reflect Zig breaking changes as of 105db13536
2024-02-06 00:06:19 +03:00
Chris Boesch
fa22e861d5 Merge pull request 'added space, missing after end-of-sentence dot.' (#40) from anthon/exercises:missing-space-1 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/40
2024-01-13 15:14:07 +00:00
Chris Boesch
7bfd7adce8 Update exercises/093_hello_c.zig
small typo
2024-01-13 14:27:58 +00:00
Anthon
58dff3f504 added space, missing after end-of-sentence dot. 2024-01-10 06:16:44 +00:00
Chris Boesch
0d46acfa02 Merge pull request 'Zig 0.12.0-dev.2043 compatability changes for test runner' (#35) from drglove/exercises:zig-2043-changes into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/35
2024-01-05 13:52:09 +00:00
drglove
15de3785a3 Bump ziglang version in Version Changes header 2024-01-05 08:43:31 +00:00
drglove
7d23ddc1f6 Update version changes with 2043. 2024-01-05 08:27:52 +00:00
drglove
ba9447d2c6 Bump version to match required changes. 2024-01-05 08:24:29 +00:00
drglove
7a0cbb131f Use std.Build.LazyPath over now removed std.Build.FileSource.
See corresponding ziglang change here: https://github.com/ziglang/zig/issues/16353
2024-01-05 08:17:09 +00:00
drglove
528a8645f8 Fix casing of std.build -> std.Build in tests. 2024-01-05 08:15:51 +00:00
Chris Boesch
b7dfa4cd1d Merge pull request 'Correct comment to match code in 076_sentinels' (#33) from mttrb/ziglings:076-comment into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/33
2024-01-04 20:47:06 +00:00
Matthew Robinson
1ed03cf0a1 Fix formatting of comment 2024-01-01 02:16:39 +08:00
Matthew Robinson
1a001b9eb7 Correct comment to match code in 076_sentinels 2024-01-01 01:41:31 +08:00
Chris Boesch
e7c106ba3a Merge pull request 'Fix minor typo' (#32) from babaiserror/exercises:typo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/32
2023-12-30 16:34:16 +00:00
babaiserror
2fb7da53e7 Fix minor typo 2023-12-29 22:59:39 -05:00
Chris Boesch
72e15c9ef3 Merge pull request 'Removed ci/compat.sh as it is included in build.zig again' (#30) from ci into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/30
2023-11-21 23:01:10 +00:00
Chris Boesch
492e5f5c40 Removed ci/compat.sh as it is included in build.zig again 2023-11-21 23:51:28 +01:00
Chris Boesch
5eafe16e97 Merge pull request 'Fix two minor typos' (#29) from A-h-m-e-d/exercises:typos into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/29

Thanks!
2023-11-21 20:49:55 +00:00
Ahmed
46e3a38dbc Fix two minor typos 2023-11-21 19:09:47 +02:00
Chris Boesch
f987a06ccc Merge pull request 'Converted var to const if there is no mutation in the var.' (#28) from var_const into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/28
2023-11-21 14:26:23 +00:00
Chris Boesch
b0511bb3c7 Fixed patch hunk 2023-11-21 15:22:36 +01:00
Chris Boesch
7679f93f68 Converted var to const if there is no mutation in var.
This is checked from compiler version 0.12.0-dev.1664
2023-11-21 15:01:22 +01:00
Chris Boesch
b7015c2d9d Merge pull request 'fixed variable declaration by changing it to a const, since it's never mutated' (#27) from zev/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/27
2023-11-21 13:20:51 +00:00
Zev Averbach
063a74c59a fixed variable declaration by changing it to a const, since it's never mutated 2023-11-21 12:00:34 +01:00
Chris Boesch
f29c0692d5 Added link to 'Zig in Depth' 2023-11-19 14:51:24 +00:00
Chris Boesch
afe5511455 Merge pull request 'Changed three dots to colons, see #23' (#25) from pr23 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/25
2023-11-07 14:23:12 +00:00
Chris Boesch
cab5ee87bf Changed three dots to colons, see #23 2023-11-07 15:18:00 +01:00
Chris Boesch
5a259a943f Merge pull request 'Change the task so that the exercise contains two errors again.' (#24) from i22 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/24
2023-11-06 18:55:54 +00:00
Chris Boesch
55b58fea56 Change the task so that the exercise contains two errors again. 2023-11-06 19:50:47 +01:00
Chris Boesch
08d294f2b8 Merge pull request 'fixed build: renamed child.exec to run' (#19) from fix_build into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/19
2023-10-24 10:42:25 +00:00
Chris Boesch
6446542867 Update .woodpecker/eowyn.yml
force pulling
2023-10-24 10:23:10 +00:00
Chris Boesch
8a1fbea5c9 fixed build: renamed exec to run 2023-10-24 11:57:44 +02:00
Chris Boesch
633af411e6 Update README.md
insert tag hint
2023-10-24 08:43:07 +00:00
88 changed files with 785 additions and 260 deletions

View file

@ -0,0 +1,31 @@
// 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"
}

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
/zig-out/ /zig-out/
/answers/ /answers/
/patches/healed/ /patches/healed/
/output/

9
.woodpecker/eowyn.yaml Normal file
View file

@ -0,0 +1,9 @@
steps:
- name: eowyn
image: ziglings/ziglang:latest
pull: true
commands:
- sh ./patches/eowyn.sh
when:
event: [push, cron]
cron: daily*

View file

@ -1,11 +0,0 @@
steps:
eowyn:
image: ziglings/ziglang
commands:
- sh ./patches/eowyn.sh
when:
events:
- push
- pull-requests
- cron
cron: "Daily"

View file

@ -54,13 +54,12 @@ Ziglings. Please file an issue...or make a pull request!
## Formatting ## Formatting
All exercises should conform to `zig fmt`. I often forget to do All exercises should conform to `zig fmt`.
this.
## Pull Request Workflow ## Pull Request Workflow
Ziglings uses the "standard" Github workflow as guided by the Web Ziglings uses the "standard" Codeberg workflow as guided by the Web
interface. Specifically: interface. Specifically:
* Fork this repository * Fork this repository
@ -71,7 +70,7 @@ interface. Specifically:
`git push origin my-branch` `git push origin my-branch`
* Create a pull request from your branch to `ziglings/main` * Create a pull request from your branch to `ziglings/main`
* Your faithful Ziglings maintainers will take a look at your * Your faithful Ziglings maintainers will take a look at your
request ASAP (we don't talk about May-July 2022, LOL) request ASAP (we don't talk about May-July, LOL)
* Once the changes are reviewed, your request will be merged and * Once the changes are reviewed, your request will be merged and
eternal Ziglings contributor glory is yours! eternal Ziglings contributor glory is yours!

View file

@ -1,12 +1,4 @@
# Ziglings # Ziglings
# ⚠️ Ziglings has moved from GitHub to Codeberg!
You are looking at the current Ziglings repo if you are viewing
this at https://codeberg.org/ziglings/exercises/
You can also use the handy URL https://ziglings.org to get here!
***
Welcome to Ziglings! This project contains a series of tiny Welcome to Ziglings! This project contains a series of tiny
broken programs (and one nasty surprise). By fixing them, you'll broken programs (and one nasty surprise). By fixing them, you'll
@ -39,6 +31,7 @@ for more detail:
* https://ziglang.org/learn/ * https://ziglang.org/learn/
* https://ziglearn.org/ * https://ziglearn.org/
* https://ziglang.org/documentation/master/ * https://ziglang.org/documentation/master/
* [Zig in Depth! (video series)](https://www.youtube.com/watch?v=MMtvGA1YhW4&list=PLtB7CL7EG7pCw7Xy1SQC53Gl8pI7aDg9t&pp=iAQB)
Also, the [Zig community](https://github.com/ziglang/zig/wiki/Community) Also, the [Zig community](https://github.com/ziglang/zig/wiki/Community)
is incredibly friendly and helpful! is incredibly friendly and helpful!
@ -53,7 +46,7 @@ Verify the installation and build number of `zig` like so:
``` ```
$ zig version $ zig version
0.12.0-dev.xxxx+xxxxxxxxx 0.13.0-dev.xxxx+xxxxxxxxx
``` ```
Clone this repository with Git: Clone this repository with Git:
@ -75,11 +68,14 @@ reading these.
## A Note About Versions ## A Note About Versions
**Hint:** To check out Ziglings for a stable release of Zig, you can use
the appropriate tag.
The Zig language is under very active development. In order to be The Zig language is under very active development. In order to be
current, Ziglings tracks **development** builds of the Zig current, Ziglings tracks **development** builds of the Zig
compiler rather than versioned **release** builds. The last compiler rather than versioned **release** builds. The last
stable release was `0.11.0`, but Ziglings needs a dev build with stable release was `0.12.0`, but Ziglings needs a dev build with
pre-release version "0.12.0" and a build number at least as high pre-release version "0.13.0" and a build number at least as high
as that shown in the example version check above. as that shown in the example version check above.
It is likely that you'll download a build which is _greater_ than It is likely that you'll download a build which is _greater_ than
@ -92,7 +88,13 @@ that if you update one, you may need to also update the other.
### Version Changes ### Version Changes
Version-0.11.0-dev.4246+71dfce31b Version-0.12.0-dev.3518
* *2024-03-21* zig 0.12.0-dev.3518 - change to @fieldParentPtr - see [#19470](https://github.com/ziglang/zig/pull/19470)
* *2024-03-21* zig 0.12.0-dev.3397 - rename std.os to std.posix - see [#5019](https://github.com/ziglang/zig/issues/5019)
* *2024-03-14* zig 0.12.0-dev.3302 - changes in `std.fmt` - floating-point formatting implementation - see [#19229](https://github.com/ziglang/zig/pull/19229)
* *2024-02-05* zig 0.12.0-dev.2618 - changes in `build system` - from `Step.zig_exe` to `Step.graph.zig_exe` - see [#18778](https://github.com/ziglang/zig/issues/18778)
* *2024-01-05* zig 0.12.0-dev.2043 - rename of `std.Build.FileSource` to `std.Build.LazyPath` - see [#16353](https://github.com/ziglang/zig/issues/16353)
* *2023-10-24* zig 0.12.0-dev.1243 - changes in `std.ChildProcess`: renamed exec to run - see [#5853](https://github.com/ziglang/zig/issues/5853)
* *2023-06-26* zig 0.11.0-dev.4246 - changes in compile step (now it can be null) * *2023-06-26* zig 0.11.0-dev.4246 - changes in compile step (now it can be null)
* *2023-06-26* zig 0.11.0-dev.3853 - removal of destination type from all cast builtins * *2023-06-26* zig 0.11.0-dev.3853 - removal of destination type from all cast builtins
* *2023-06-20* zig 0.11.0-dev.3747 - `@enumToInt` is now `@intFromEnum` and `@intToFloat` is now `@floatFromInt` * *2023-06-20* zig 0.11.0-dev.3747 - `@enumToInt` is now `@intFromEnum` and `@intToFloat` is now `@floatFromInt`
@ -209,13 +211,14 @@ Zig Core Language
* [X] Interfaces * [X] Interfaces
* [X] Bit manipulation * [X] Bit manipulation
* [X] Working with C * [X] Working with C
* [ ] Interfaces part 2 * [X] Threading
Zig Standard Library Zig Standard Library
* [X] String formatting * [X] String formatting
* [X] Testing * [X] Testing
* [X] Tokenization * [X] Tokenization
* [X] File handling
## Contributing ## Contributing

View file

@ -15,7 +15,7 @@ const print = std.debug.print;
// 1) Getting Started // 1) Getting Started
// 2) Version Changes // 2) Version Changes
comptime { comptime {
const required_zig = "0.11.0-dev.4246"; const required_zig = "0.12.0-dev.3518";
const current_zig = builtin.zig_version; const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
if (current_zig.order(min_zig) == .lt) { if (current_zig.order(min_zig) == .lt) {
@ -119,7 +119,7 @@ pub const logo =
; ;
pub fn build(b: *Build) !void { pub fn build(b: *Build) !void {
if (!validate_exercises()) std.os.exit(2); if (!validate_exercises()) std.process.exit(2);
use_color_escapes = false; use_color_escapes = false;
if (std.io.getStdErr().supportsAnsiEscapeCodes()) { if (std.io.getStdErr().supportsAnsiEscapeCodes()) {
@ -172,7 +172,7 @@ pub fn build(b: *Build) !void {
// Named build mode: verifies a single exercise. // Named build mode: verifies a single exercise.
if (n == 0 or n > exercises.len - 1) { if (n == 0 or n > exercises.len - 1) {
print("unknown exercise number: {}\n", .{n}); print("unknown exercise number: {}\n", .{n});
std.os.exit(2); std.process.exit(2);
} }
const ex = exercises[n - 1]; const ex = exercises[n - 1];
@ -247,7 +247,7 @@ const ZiglingStep = struct {
fn make(step: *Step, prog_node: *std.Progress.Node) !void { fn make(step: *Step, prog_node: *std.Progress.Node) !void {
// NOTE: Using exit code 2 will prevent the Zig compiler to print the message: // NOTE: Using exit code 2 will prevent the Zig compiler to print the message:
// "error: the following build command failed with exit code 1:..." // "error: the following build command failed with exit code 1:..."
const self = @fieldParentPtr(ZiglingStep, "step", step); const self: *ZiglingStep = @alignCast(@fieldParentPtr("step", step));
if (self.exercise.skip) { if (self.exercise.skip) {
print("Skipping {s}\n\n", .{self.exercise.main_file}); print("Skipping {s}\n\n", .{self.exercise.main_file});
@ -262,7 +262,7 @@ const ZiglingStep = struct {
print("\n{s}Ziglings hint: {s}{s}", .{ bold_text, hint, reset_text }); print("\n{s}Ziglings hint: {s}{s}", .{ bold_text, hint, reset_text });
self.help(); self.help();
std.os.exit(2); std.process.exit(2);
}; };
self.run(exe_path.?, prog_node) catch { self.run(exe_path.?, prog_node) catch {
@ -272,7 +272,7 @@ const ZiglingStep = struct {
print("\n{s}Ziglings hint: {s}{s}", .{ bold_text, hint, reset_text }); print("\n{s}Ziglings hint: {s}{s}", .{ bold_text, hint, reset_text });
self.help(); self.help();
std.os.exit(2); std.process.exit(2);
}; };
// Print possible warning/debug messages. // Print possible warning/debug messages.
@ -281,14 +281,14 @@ const ZiglingStep = struct {
fn run(self: *ZiglingStep, exe_path: []const u8, _: *std.Progress.Node) !void { fn run(self: *ZiglingStep, exe_path: []const u8, _: *std.Progress.Node) !void {
resetLine(); resetLine();
print("Checking {s}...\n", .{self.exercise.main_file}); print("Checking: {s}\n", .{self.exercise.main_file});
const b = self.step.owner; const b = self.step.owner;
// Allow up to 1 MB of stdout capture. // Allow up to 1 MB of stdout capture.
const max_output_bytes = 1 * 1024 * 1024; const max_output_bytes = 1 * 1024 * 1024;
var result = Child.exec(.{ const result = Child.run(.{
.allocator = b.allocator, .allocator = b.allocator,
.argv = &.{exe_path}, .argv = &.{exe_path},
.cwd = b.build_root.path.?, .cwd = b.build_root.path.?,
@ -306,7 +306,7 @@ const ZiglingStep = struct {
} }
} }
fn check_output(self: *ZiglingStep, result: Child.ExecResult) !void { fn check_output(self: *ZiglingStep, result: Child.RunResult) !void {
const b = self.step.owner; const b = self.step.owner;
// Make sure it exited cleanly. // Make sure it exited cleanly.
@ -355,7 +355,7 @@ const ZiglingStep = struct {
print("{s}PASSED:\n{s}{s}\n\n", .{ green_text, output, reset_text }); print("{s}PASSED:\n{s}{s}\n\n", .{ green_text, output, reset_text });
} }
fn check_test(self: *ZiglingStep, result: Child.ExecResult) !void { fn check_test(self: *ZiglingStep, result: Child.RunResult) !void {
switch (result.term) { switch (result.term) {
.Exited => |code| { .Exited => |code| {
if (code != 0) { if (code != 0) {
@ -376,7 +376,7 @@ const ZiglingStep = struct {
} }
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}); print("Compiling: {s}\n", .{self.exercise.main_file});
const b = self.step.owner; const b = self.step.owner;
const exercise_path = self.exercise.main_file; const exercise_path = self.exercise.main_file;
@ -386,7 +386,7 @@ const ZiglingStep = struct {
var zig_args = std.ArrayList([]const u8).init(b.allocator); var zig_args = std.ArrayList([]const u8).init(b.allocator);
defer zig_args.deinit(); defer zig_args.deinit();
zig_args.append(b.zig_exe) catch @panic("OOM"); zig_args.append(b.graph.zig_exe) catch @panic("OOM");
const cmd = switch (self.exercise.kind) { const cmd = switch (self.exercise.kind) {
.exe => "build-exe", .exe => "build-exe",
@ -495,8 +495,7 @@ const PrintStep = struct {
} }
fn make(step: *Step, _: *std.Progress.Node) !void { fn make(step: *Step, _: *std.Progress.Node) !void {
const self = @fieldParentPtr(PrintStep, "step", step); const self: *PrintStep = @alignCast(@fieldParentPtr("step", step));
print("{s}", .{self.message}); print("{s}", .{self.message});
} }
}; };
@ -839,7 +838,7 @@ const exercises = [_]Exercise{
}, },
.{ .{
.main_file = "060_floats.zig", .main_file = "060_floats.zig",
.output = "Shuttle liftoff weight: 1995796kg", .output = "Shuttle liftoff weight: 2032092kg",
}, },
.{ .{
.main_file = "061_coercions.zig", .main_file = "061_coercions.zig",
@ -939,7 +938,7 @@ const exercises = [_]Exercise{
.{ .{
.main_file = "082_anonymous_structs3.zig", .main_file = "082_anonymous_structs3.zig",
.output = .output =
\\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.14159202e+00 \\"0"(bool):true "1"(bool):false "2"(i32):42 "3"(f32):3.141592e0
, ,
.hint = "This one is a challenge! But you have everything you need.", .hint = "This one is a challenge! But you have everything you need.",
}, },
@ -1103,6 +1102,35 @@ const exercises = [_]Exercise{
\\This little poem has 15 words! \\This little poem has 15 words!
, ,
}, },
.{
.main_file = "104_threading.zig",
.output =
\\Starting work...
\\thread 1: started.
\\thread 2: started.
\\thread 3: started.
\\Some weird stuff, after starting the threads.
\\thread 2: finished.
\\thread 1: finished.
\\thread 3: finished.
\\Zig is cool!
,
},
.{
.main_file = "105_threading2.zig",
.output = "PI ≈ 3.14159265",
},
.{
.main_file = "106_files.zig",
.output = "Successfully wrote 18 bytes.",
},
.{
.main_file = "107_files2.zig",
.output =
\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
\\Successfully Read 18 bytes: It's zigling time!
,
},
.{ .{
.main_file = "999_the_end.zig", .main_file = "999_the_end.zig",
.output = .output =

View file

@ -1,25 +0,0 @@
#!/bin/bash
# This script checks that `zig build` will return an useful error message when
# the Zig compiler is not compatible, instead of failing due to a syntax error.
#
# This script should be run on an UNIX system.
zig_version=$(zig version)
zig build -Dn=1 -Dhealed &> /dev/null 2>&1
zig_ret=$?
if [ "$zig_ret" -eq 0 ]; then
printf "zig %s unexpectedly succeeded\n" "$zig_version"
exit 1
fi
zig_error=$(zig build -Dn=1 -Dhealed 2>&1)
echo "$zig_error" | grep -q "it looks like your version of zig is too old"
zig_ret=$?
if [ "$zig_ret" -ne 0 ]; then
printf "zig %s is not compatible\n" "$zig_version"
exit 1
fi

View file

@ -16,6 +16,6 @@
// //
const std = @import("std"); const std = @import("std");
fn main() void { pub fn main() void {
std.debug.print("Hello world!\n", .{}); std.debug.print("Hello world!\n", .{});
} }

View file

@ -11,7 +11,7 @@
// Please complete the import below: // Please complete the import below:
// //
??? = @import("std"); const std = @import("std");
pub fn main() void { pub fn main() void {
std.debug.print("Standard Library.\n", .{}); std.debug.print("Standard Library.\n", .{});

View file

@ -34,12 +34,12 @@
const std = @import("std"); const std = @import("std");
pub fn main() void { pub fn main() void {
const n: u8 = 50; var n: u8 = 50;
n = n + 5; n = n + 5;
const pi: u8 = 314159; const pi: u32 = 314159;
const negative_eleven: u8 = -11; const negative_eleven: i8 = -11;
// There are no errors in the next line, just explanation: // There are no errors in the next line, just explanation:
// Perhaps you noticed before that the print function takes two // Perhaps you noticed before that the print function takes two

View file

@ -27,7 +27,7 @@ pub fn main() void {
// (Problem 1) // (Problem 1)
// This "const" is going to cause a problem later - can you see what it is? // This "const" is going to cause a problem later - can you see what it is?
// How do we fix it? // How do we fix it?
const some_primes = [_]u8{ 1, 3, 5, 7, 11, 13, 17, 19 }; var some_primes = [_]u8{ 1, 3, 5, 7, 11, 13, 17, 19 };
// Individual values can be set with '[]' notation. // Individual values can be set with '[]' notation.
// Example: This line changes the first prime to 2 (which is correct): // Example: This line changes the first prime to 2 (which is correct):
@ -40,11 +40,11 @@ pub fn main() void {
// (Problem 2) // (Problem 2)
// Looks like we need to complete this expression. Use the example // Looks like we need to complete this expression. Use the example
// above to set "fourth" to the fourth element of the some_primes array: // above to set "fourth" to the fourth element of the some_primes array:
const fourth = some_primes[???]; const fourth = some_primes[3];
// (Problem 3) // (Problem 3)
// Use the len property to get the length of the array: // Use the len property to get the length of the array:
const length = some_primes.???; const length = some_primes.len;
std.debug.print("First: {}, Fourth: {}, Length: {}\n", .{ std.debug.print("First: {}, Fourth: {}, Length: {}\n", .{
first, fourth, length, first, fourth, length,

View file

@ -25,12 +25,12 @@ pub fn main() void {
// (Problem 1) // (Problem 1)
// Please set this array concatenating the two arrays above. // Please set this array concatenating the two arrays above.
// It should result in: 1 3 3 7 // It should result in: 1 3 3 7
const leet = ???; const leet = le ++ et;
// (Problem 2) // (Problem 2)
// Please set this array using repetition. // Please set this array using repetition.
// It should result in: 1 0 0 1 1 0 0 1 1 0 0 1 // It should result in: 1 0 0 1 1 0 0 1 1 0 0 1
const bit_pattern = [_]u8{ ??? } ** 3; const bit_pattern = [_]u8{ 1, 0, 0, 1 } ** 3;
// Okay, that's all of the problems. Let's see the results. // Okay, that's all of the problems. Let's see the results.
// //

View file

@ -24,18 +24,18 @@ pub fn main() void {
// (Problem 1) // (Problem 1)
// Use array square bracket syntax to get the letter 'd' from // Use array square bracket syntax to get the letter 'd' from
// the string "stardust" above. // the string "stardust" above.
const d: u8 = ziggy[???]; const d: u8 = ziggy[4];
// (Problem 2) // (Problem 2)
// Use the array repeat '**' operator to make "ha ha ha ". // Use the array repeat '**' operator to make "ha ha ha ".
const laugh = "ha " ???; const laugh = "ha " ** 3;
// (Problem 3) // (Problem 3)
// Use the array concatenation '++' operator to make "Major Tom". // Use the array concatenation '++' operator to make "Major Tom".
// (You'll need to add a space as well!) // (You'll need to add a space as well!)
const major = "Major"; const major = "Major";
const tom = "Tom"; const tom = "Tom";
const major_tom = major ??? tom; const major_tom = major ++ " " ++ tom;
// That's all the problems. Let's see our results: // That's all the problems. Let's see our results:
std.debug.print("d={u} {s}{s}\n", .{ d, laugh, major_tom }); std.debug.print("d={u} {s}{s}\n", .{ d, laugh, major_tom });

View file

@ -15,9 +15,9 @@ const std = @import("std");
pub fn main() void { pub fn main() void {
const lyrics = const lyrics =
Ziggy played guitar \\Ziggy played guitar
Jamming good with Andrew Kelley \\Jamming good with Andrew Kelley
And the Spiders from Mars \\And the Spiders from Mars
; ;
std.debug.print("{s}\n", .{lyrics}); std.debug.print("{s}\n", .{lyrics});

View file

@ -19,7 +19,7 @@ pub fn main() void {
// the idiomatic type to use for array indexing. // the idiomatic type to use for array indexing.
// //
// There IS a problem on this line, but 'usize' isn't it. // There IS a problem on this line, but 'usize' isn't it.
const x: usize = 1; var x: usize = 1;
// Note: When you want to declare memory (an array in this // Note: When you want to declare memory (an array in this
// case) without putting anything in it, you can set it to // case) without putting anything in it, you can set it to
@ -33,10 +33,10 @@ pub fn main() void {
lang[0] = letters[x]; lang[0] = letters[x];
x = 3; x = 3;
lang[???] = letters[x]; lang[1] = letters[x];
x = ???; x = 5;
lang[2] = letters[???]; lang[2] = letters[x];
// We want to "Program in Zig!" of course: // We want to "Program in Zig!" of course:
std.debug.print("Program in {s}!\n", .{lang}); std.debug.print("Program in {s}!\n", .{lang});

View file

@ -24,7 +24,7 @@ pub fn main() void {
const foo = 1; const foo = 1;
// Please fix this condition: // Please fix this condition:
if (foo) { if (foo == 1) {
// We want our program to print this message! // We want our program to print this message!
std.debug.print("Foo is 1!\n", .{}); std.debug.print("Foo is 1!\n", .{});
} else { } else {

View file

@ -10,7 +10,7 @@ pub fn main() void {
// Please use an if...else expression to set "price". // Please use an if...else expression to set "price".
// If discount is true, the price should be $17, otherwise $20: // If discount is true, the price should be $17, otherwise $20:
const price: u8 = if ???; const price: u8 = if (discount) 17 else 20;
std.debug.print("With the discount, the price is ${}.\n", .{price}); std.debug.print("With the discount, the price is ${}.\n", .{price});
} }

View file

@ -21,7 +21,7 @@ pub fn main() void {
var n: u32 = 2; var n: u32 = 2;
// Please use a condition that is true UNTIL "n" reaches 1024: // Please use a condition that is true UNTIL "n" reaches 1024:
while (???) { while (n < 1024) {
// Print the current number // Print the current number
std.debug.print("{} ", .{n}); std.debug.print("{} ", .{n});

View file

@ -25,7 +25,7 @@ pub fn main() void {
// Please set the continue expression so that we get the desired // Please set the continue expression so that we get the desired
// results in the print statement below. // results in the print statement below.
while (n < 1000) : ??? { while (n < 1000) : (n *= 2) {
// Print the current number // Print the current number
std.debug.print("{} ", .{n}); std.debug.print("{} ", .{n});
} }

View file

@ -24,8 +24,8 @@ pub fn main() void {
while (n <= 20) : (n += 1) { while (n <= 20) : (n += 1) {
// The '%' symbol is the "modulo" operator and it // The '%' symbol is the "modulo" operator and it
// returns the remainder after division. // returns the remainder after division.
if (n % 3 == 0) ???; if (n % 3 == 0) continue;
if (n % 5 == 0) ???; if (n % 5 == 0) continue;
std.debug.print("{} ", .{n}); std.debug.print("{} ", .{n});
} }

View file

@ -18,7 +18,7 @@ pub fn main() void {
// Oh dear! This while loop will go forever?! // Oh dear! This while loop will go forever?!
// Please fix this so the print statement below gives the desired output. // Please fix this so the print statement below gives the desired output.
while (true) : (n += 1) { while (true) : (n += 1) {
if (???) ???; if (n > 3) break;
} }
// Result: we want n=4 // Result: we want n=4

View file

@ -15,7 +15,7 @@ pub fn main() void {
std.debug.print("A Dramatic Story: ", .{}); std.debug.print("A Dramatic Story: ", .{});
for (???) |???| { for (story) |scene| {
if (scene == 'h') std.debug.print(":-) ", .{}); if (scene == 'h') std.debug.print(":-) ", .{});
if (scene == 's') std.debug.print(":-( ", .{}); if (scene == 's') std.debug.print(":-( ", .{});
if (scene == 'n') std.debug.print(":-| ", .{}); if (scene == 'n') std.debug.print(":-| ", .{});

View file

@ -25,7 +25,7 @@ pub fn main() void {
// the value of the place as a power of two for each bit. // the value of the place as a power of two for each bit.
// //
// See if you can figure out the missing pieces: // See if you can figure out the missing pieces:
for (bits, ???) |bit, ???| { for (bits, 0..) |bit, i| {
// Note that we convert the usize i to a u32 with // Note that we convert the usize i to a u32 with
// @intCast(), a builtin function just like @import(). // @intCast(), a builtin function just like @import().
// We'll learn about these properly in a later exercise. // We'll learn about these properly in a later exercise.

View file

@ -9,18 +9,18 @@
// Let's go from 1 to 16. This has been started for you, but there // Let's go from 1 to 16. This has been started for you, but there
// are some problems. :-( // are some problems. :-(
// //
const std = import standard library; const std = @import("std");
function main() void { pub fn main() void {
var i: u8 = 1; var i: u8 = 1;
const stop_at: u8 = 16; const stop_at: u8 = 16;
// What kind of loop is this? A 'for' or a 'while'? // What kind of loop is this? A 'for' or a 'while'?
??? (i <= stop_at) : (i += 1) { while (i <= stop_at) : (i += 1) {
if (i % 3 == 0) std.debug.print("Fizz", .{}); if (i % 3 == 0) std.debug.print("Fizz", .{});
if (i % 5 == 0) std.debug.print("Buzz", .{}); if (i % 5 == 0) std.debug.print("Buzz", .{});
if (!(i % 3 == 0) and !(i % 5 == 0)) { if (!(i % 3 == 0) and !(i % 5 == 0)) {
std.debug.print("{}", .{???}); std.debug.print("{}", .{i});
} }
std.debug.print(", ", .{}); std.debug.print(", ", .{});
} }

View file

@ -25,6 +25,6 @@ pub fn main() void {
// We're just missing a couple things. One thing we're NOT missing is the // We're just missing a couple things. One thing we're NOT missing is the
// keyword "pub", which is not needed here. Can you guess why? // keyword "pub", which is not needed here. Can you guess why?
// //
??? deepThought() ??? { fn deepThought() u8 {
return 42; // Number courtesy Douglas Adams return 42; // Number courtesy Douglas Adams
} }

View file

@ -22,7 +22,7 @@ pub fn main() void {
// You'll need to figure out the parameter name and type that we're // You'll need to figure out the parameter name and type that we're
// expecting. The output type has already been specified for you. // expecting. The output type has already been specified for you.
// //
fn twoToThe(???) u32 { fn twoToThe(my_number: u8) u32 {
return std.math.pow(u32, 2, my_number); return std.math.pow(u32, 2, my_number);
// std.math.pow(type, a, b) takes a numeric type and two // std.math.pow(type, a, b) takes a numeric type and two
// numbers of that type (or that can coerce to that type) and // numbers of that type (or that can coerce to that type) and

View file

@ -21,8 +21,8 @@ pub fn main() void {
// //
// This function prints, but does not return anything. // This function prints, but does not return anything.
// //
fn printPowersOfTwo(numbers: [4]u16) ??? { fn printPowersOfTwo(numbers: [4]u16) void {
loop (numbers) |n| { for (numbers) |n| {
std.debug.print("{} ", .{twoToThe(n)}); std.debug.print("{} ", .{twoToThe(n)});
} }
} }
@ -31,13 +31,13 @@ fn printPowersOfTwo(numbers: [4]u16) ??? {
// exercise. But don't be fooled! This one does the math without the aid // exercise. But don't be fooled! This one does the math without the aid
// of the standard library! // of the standard library!
// //
fn twoToThe(number: u16) ??? { fn twoToThe(number: u16) u32 {
var n: u16 = 0; var n: u16 = 0;
var total: u16 = 1; var total: u16 = 1;
loop (n < number) : (n += 1) { while (n < number) : (n += 1) {
total *= 2; total *= 2;
} }
return ???; return total;
} }

View file

@ -9,7 +9,7 @@
// "TooSmall". Please add it where needed! // "TooSmall". Please add it where needed!
const MyNumberError = error{ const MyNumberError = error{
TooBig, TooBig,
???, TooSmall,
TooFour, TooFour,
}; };
@ -26,7 +26,7 @@ pub fn main() void {
if (number_error == MyNumberError.TooBig) { if (number_error == MyNumberError.TooBig) {
std.debug.print(">4. ", .{}); std.debug.print(">4. ", .{});
} }
if (???) { if (number_error == MyNumberError.TooSmall) {
std.debug.print("<4. ", .{}); std.debug.print("<4. ", .{});
} }
if (number_error == MyNumberError.TooFour) { if (number_error == MyNumberError.TooFour) {

View file

@ -19,7 +19,7 @@ const std = @import("std");
const MyNumberError = error{TooSmall}; const MyNumberError = error{TooSmall};
pub fn main() void { pub fn main() void {
var my_number: ??? = 5; var my_number: MyNumberError!u8 = 5;
// Looks like my_number will need to either store a number OR // Looks like my_number will need to either store a number OR
// an error. Can you set the type correctly above? // an error. Can you set the type correctly above?

View file

@ -12,14 +12,14 @@ const MyNumberError = error{TooSmall};
pub fn main() void { pub fn main() void {
const a: u32 = addTwenty(44) catch 22; const a: u32 = addTwenty(44) catch 22;
const b: u32 = addTwenty(4) ??? 22; const b: u32 = addTwenty(4) catch 22;
std.debug.print("a={}, b={}\n", .{ a, b }); std.debug.print("a={}, b={}\n", .{ a, b });
} }
// Please provide the return type from this function. // Please provide the return type from this function.
// Hint: it'll be an error union. // Hint: it'll be an error union.
fn addTwenty(n: u32) ??? { fn addTwenty(n: u32) MyNumberError!u32 {
if (n < 5) { if (n < 5) {
return MyNumberError.TooSmall; return MyNumberError.TooSmall;
} else { } else {

View file

@ -59,7 +59,12 @@ fn fixTooSmall(n: u32) MyNumberError!u32 {
// If we get a TooSmall error, we should return 10. // If we get a TooSmall error, we should return 10.
// If we get any other error, we should return that error. // If we get any other error, we should return that error.
// Otherwise, we return the u32 number. // Otherwise, we return the u32 number.
return detectProblems(n) ???; return detectProblems(n) catch |err| {
if (err == MyNumberError.TooSmall) {
return 10;
}
return err;
};
} }
fn detectProblems(n: u32) MyNumberError!u32 { fn detectProblems(n: u32) MyNumberError!u32 {

View file

@ -26,7 +26,7 @@ fn addFive(n: u32) MyNumberError!u32 {
// This function needs to return any error which might come back from detect(). // This function needs to return any error which might come back from detect().
// Please use a "try" statement rather than a "catch". // Please use a "try" statement rather than a "catch".
// //
var x = detect(n); const x = try detect(n);
return x + 5; return x + 5;
} }

View file

@ -23,5 +23,5 @@ pub fn main() !void {
// to be able to pass it up as a return value of main(). // to be able to pass it up as a return value of main().
// //
// We just learned of a single statement which can accomplish this. // We just learned of a single statement which can accomplish this.
stdout.print("Hello world!\n", .{}); try stdout.print("Hello world!\n", .{});
} }

View file

@ -20,6 +20,6 @@ const std = @import("std");
pub fn main() void { pub fn main() void {
// Without changing anything else, please add a 'defer' statement // Without changing anything else, please add a 'defer' statement
// to this code so that our program prints "One Two\n": // to this code so that our program prints "One Two\n":
std.debug.print("Two\n", .{}); defer std.debug.print("Two\n", .{});
std.debug.print("One ", .{}); std.debug.print("One ", .{});
} }

View file

@ -18,7 +18,7 @@ pub fn main() void {
fn printAnimal(animal: u8) void { fn printAnimal(animal: u8) void {
std.debug.print("(", .{}); std.debug.print("(", .{});
std.debug.print(") ", .{}); // <---- how?! defer std.debug.print(") ", .{}); // <---- how?!
if (animal == 'g') { if (animal == 'g') {
std.debug.print("Goat", .{}); std.debug.print("Goat", .{});

View file

@ -21,8 +21,8 @@ const MyErr = error{ GetFail, IncFail };
pub fn main() void { pub fn main() void {
// We simply quit the entire program if we fail to get a number: // We simply quit the entire program if we fail to get a number:
var a: u32 = makeNumber() catch return; const a: u32 = makeNumber() catch return;
var b: u32 = makeNumber() catch return; const b: u32 = makeNumber() catch return;
std.debug.print("Numbers: {}, {}\n", .{ a, b }); std.debug.print("Numbers: {}, {}\n", .{ a, b });
} }
@ -32,7 +32,7 @@ fn makeNumber() MyErr!u32 {
// Please make the "failed" message print ONLY if the makeNumber() // Please make the "failed" message print ONLY if the makeNumber()
// function exits with an error: // function exits with an error:
std.debug.print("failed!\n", .{}); errdefer std.debug.print("failed!\n", .{});
var num = try getNumber(); // <-- This could fail! var num = try getNumber(); // <-- This could fail!

View file

@ -46,6 +46,7 @@ pub fn main() void {
// match for every possible value). Please add an "else" // match for every possible value). Please add an "else"
// to this switch to print a question mark "?" when c is // to this switch to print a question mark "?" when c is
// not one of the existing matches. // not one of the existing matches.
else => std.debug.print("?", .{}),
} }
} }

View file

@ -31,6 +31,7 @@ pub fn main() void {
26 => 'Z', 26 => 'Z',
// As in the last exercise, please add the 'else' clause // As in the last exercise, please add the 'else' clause
// and this time, have it return an exclamation mark '!'. // and this time, have it return an exclamation mark '!'.
else => '!',
}; };
std.debug.print("{c}", .{real_char}); std.debug.print("{c}", .{real_char});

View file

@ -35,6 +35,7 @@ pub fn main() void {
3 => { 3 => {
current_value *= current_value; current_value *= current_value;
}, },
else => unreachable,
} }
std.debug.print("{} ", .{current_value}); std.debug.print("{} ", .{current_value});

View file

@ -39,7 +39,7 @@ pub fn main() void {
std.debug.print("={}. ", .{value}); std.debug.print("={}. ", .{value});
} else |err| switch (err) { } else |err| switch (err) {
MyNumberError.TooBig => std.debug.print(">4. ", .{}), MyNumberError.TooBig => std.debug.print(">4. ", .{}),
// Please add a match for TooSmall here and have it print: "<4. " MyNumberError.TooSmall => std.debug.print("<4. ", .{}),
} }
} }

View file

@ -6,14 +6,11 @@
// my_num=42 // my_num=42
// //
const std = @import("std"); const std = @import("std");
const NumError = error{IllegalNumber}; const NumError = error{IllegalNumber};
pub fn main() void { pub fn main() !void {
const stdout = std.io.getStdOut().writer(); const stdout = std.io.getStdOut().writer();
const my_num: u32 = try getNumber();
const my_num: u32 = getNumber();
try stdout.print("my_num={}\n", .{my_num}); try stdout.print("my_num={}\n", .{my_num});
} }

View file

@ -20,7 +20,7 @@
const std = @import("std"); const std = @import("std");
// Please complete the enum! // Please complete the enum!
const Ops = enum { ??? }; const Ops = enum { inc, dec, pow };
pub fn main() void { pub fn main() void {
const operations = [_]Ops{ const operations = [_]Ops{

View file

@ -31,7 +31,7 @@ const std = @import("std");
const Color = enum(u32) { const Color = enum(u32) {
red = 0xff0000, red = 0xff0000,
green = 0x00ff00, green = 0x00ff00,
blue = ???, blue = 0x0000ff,
}; };
pub fn main() void { pub fn main() void {
@ -53,12 +53,12 @@ pub fn main() void {
\\<p> \\<p>
\\ <span style="color: #{x:0>6}">Red</span> \\ <span style="color: #{x:0>6}">Red</span>
\\ <span style="color: #{x:0>6}">Green</span> \\ <span style="color: #{x:0>6}">Green</span>
\\ <span style="color: #{}">Blue</span> \\ <span style="color: #{x:0>6}">Blue</span>
\\</p> \\</p>
\\ \\
, .{ , .{
@intFromEnum(Color.red), @intFromEnum(Color.red),
@intFromEnum(Color.green), @intFromEnum(Color.green),
@intFromEnum(???), // Oops! We're missing something! @intFromEnum(Color.blue), // Oops! We're missing something!
}); });
} }

View file

@ -24,7 +24,7 @@ const std = @import("std");
pub fn main() void { pub fn main() void {
var num1: u8 = 5; var num1: u8 = 5;
var num1_pointer: *u8 = &num1; const num1_pointer: *u8 = &num1;
var num2: u8 = undefined; var num2: u8 = undefined;

View file

@ -51,8 +51,6 @@ fn visitElephants(first_elephant: *Elephant) void {
// We should stop once we encounter a tail that // We should stop once we encounter a tail that
// does NOT point to another element. What can // does NOT point to another element. What can
// we put here to make that happen? // we put here to make that happen?
if (e.tail == null) ???; e = e.tail ???
e = e.tail.?;
} }
} }

View file

@ -24,7 +24,7 @@ const Elephant = struct {
pub fn print(self: *Elephant) void { pub fn print(self: *Elephant) void {
// Prints elephant letter and [v]isited // Prints elephant letter and [v]isited
var v: u8 = if (self.visited) 'v' else ' '; const v: u8 = if (self.visited) 'v' else ' ';
std.debug.print("{u}{u} ", .{ self.letter, v }); std.debug.print("{u}{u} ", .{ self.letter, v });
} }
}; };

View file

@ -37,7 +37,7 @@ const Elephant = struct {
pub fn print(self: *Elephant) void { pub fn print(self: *Elephant) void {
// Prints elephant letter and [v]isited // Prints elephant letter and [v]isited
var v: u8 = if (self.visited) 'v' else ' '; const v: u8 = if (self.visited) 'v' else ' ';
std.debug.print("{u}{u} ", .{ self.letter, v }); std.debug.print("{u}{u} ", .{ self.letter, v });
} }
}; };

View file

@ -141,9 +141,20 @@ pub fn main() void {
// //
// Moving along... // Moving along...
// //
// Passing arguments to functions is pretty much exactly like // When arguments are passed to a function,
// making an assignment to a const (since Zig enforces that ALL // they are ALWAYS passed as constants within the function,
// function parameters are const). // regardless of how they were declared in the calling function.
//
// Example:
// fn foo(arg: u8) void {
// arg = 42; // Error, 'arg' is const!
// }
//
// fn bar() void {
// var arg: u8 = 12;
// foo(arg);
// ...
// }
// //
// Knowing this, see if you can make levelUp() work as expected - // Knowing this, see if you can make levelUp() work as expected -
// it should add the specified amount to the supplied character's // it should add the specified amount to the supplied character's

View file

@ -53,8 +53,8 @@ const AntOrBee = enum { a, b };
pub fn main() void { pub fn main() void {
// We'll just make one bee and one ant to test them out: // We'll just make one bee and one ant to test them out:
var ant = Insect{ .still_alive = true }; const ant = Insect{ .still_alive = true };
var bee = Insect{ .flowers_visited = 15 }; const bee = Insect{ .flowers_visited = 15 };
std.debug.print("Insect report! ", .{}); std.debug.print("Insect report! ", .{});

View file

@ -38,8 +38,8 @@ const Insect = union(InsectStat) {
}; };
pub fn main() void { pub fn main() void {
var ant = Insect{ .still_alive = true }; const ant = Insect{ .still_alive = true };
var bee = Insect{ .flowers_visited = 16 }; const bee = Insect{ .flowers_visited = 16 };
std.debug.print("Insect report! ", .{}); std.debug.print("Insect report! ", .{});

View file

@ -21,8 +21,8 @@ const Insect = union(InsectStat) {
}; };
pub fn main() void { pub fn main() void {
var ant = Insect{ .still_alive = true }; const ant = Insect{ .still_alive = true };
var bee = Insect{ .flowers_visited = 17 }; const bee = Insect{ .flowers_visited = 17 };
std.debug.print("Insect report! ", .{}); std.debug.print("Insect report! ", .{});

View file

@ -273,7 +273,7 @@ const HermitsNotebook = struct {
// distance) than the one we'd noted before. If it is, we // distance) than the one we'd noted before. If it is, we
// overwrite the old entry with the new one. // overwrite the old entry with the new one.
fn checkNote(self: *HermitsNotebook, note: NotebookEntry) void { fn checkNote(self: *HermitsNotebook, note: NotebookEntry) void {
var existing_entry = self.getEntry(note.place); const existing_entry = self.getEntry(note.place);
if (existing_entry == null) { if (existing_entry == null) {
self.entries[self.end_of_entries] = note; self.entries[self.end_of_entries] = note;
@ -386,7 +386,7 @@ pub fn main() void {
// "start" entry we just added) until we run out, at which point // "start" entry we just added) until we run out, at which point
// we'll have checked every reachable Place. // we'll have checked every reachable Place.
while (notebook.hasNextEntry()) { while (notebook.hasNextEntry()) {
var place_entry = notebook.getNextEntry(); const place_entry = notebook.getNextEntry();
// For every Path that leads FROM the current Place, create a // For every Path that leads FROM the current Place, create a
// new note (in the form of a NotebookEntry) with the // new note (in the form of a NotebookEntry) with the

View file

@ -2,12 +2,12 @@
// Zig lets you express integer literals in several convenient // Zig lets you express integer literals in several convenient
// formats. These are all the same value: // formats. These are all the same value:
// //
// const a1: u8 = 65; // decimal // const a1: u8 = 65; // decimal
// const a2: u8 = 0x41; // hexadecimal // const a2: u8 = 0x41; // hexadecimal
// const a3: u8 = 0o101; // octal // const a3: u8 = 0o101; // octal
// const a4: u8 = 0b1000001; // binary // const a4: u8 = 0b1000001; // binary
// const a5: u8 = 'A'; // ASCII code point literal // const a5: u8 = 'A'; // ASCII code point literal
// const a6: u16 = 'Ȁ'; // Unicode code points can take up to 21 bits // const a6: u16 = '\u{0041}'; // Unicode code points can take up to 21 bits
// //
// You can also place underscores in numbers to aid readability: // You can also place underscores in numbers to aid readability:
// //

View file

@ -39,11 +39,11 @@ const print = @import("std").debug.print;
pub fn main() void { pub fn main() void {
// The approximate weight of the Space Shuttle upon liftoff // The approximate weight of the Space Shuttle upon liftoff
// (including boosters and fuel tank) was 2,200 tons. // (including boosters and fuel tank) was 4,480,000 lb.
// //
// We'll convert this weight from tons to kilograms at a // We'll convert this weight from pound to kilograms at a
// conversion of 907.18kg to the ton. // conversion of 0.453592kg to the pound.
const shuttle_weight: f16 = 907.18 * 2200; const shuttle_weight: f16 = 0.453592 * 4480e6;
// By default, float values are formatted in scientific // By default, float values are formatted in scientific
// notation. Try experimenting with '{d}' and '{d:.3}' to see // notation. Try experimenting with '{d}' and '{d:.3}' to see

View file

@ -58,7 +58,7 @@ pub fn main() void {
// There is a difference between // There is a difference between
// - a value, that overflowed at some point and is now corrupted // - a value, that overflowed at some point and is now corrupted
// - a single operation that overflows and maybe causes subsequent errors // - a single operation that overflows and maybe causes subsequent errors
// In practise we usually notice the overflowed value first and have to work // In practice we usually notice the overflowed value first and have to work
// our way backwards to the operation that caused the overflow. // our way backwards to the operation that caused the overflow.
// //
// If there was no overflow at all while adding 5 to a, what value would // If there was no overflow at all while adding 5 to a, what value would

View file

@ -38,16 +38,16 @@ pub fn main() void {
var count = 0; var count = 0;
count += 1; count += 1;
var a1: [count]u8 = .{'A'} ** count; const a1: [count]u8 = .{'A'} ** count;
count += 1; count += 1;
var a2: [count]u8 = .{'B'} ** count; const a2: [count]u8 = .{'B'} ** count;
count += 1; count += 1;
var a3: [count]u8 = .{'C'} ** count; const a3: [count]u8 = .{'C'} ** count;
count += 1; count += 1;
var a4: [count]u8 = .{'D'} ** count; const a4: [count]u8 = .{'D'} ** count;
print("{s} {s} {s} {s}\n", .{ a1, a2, a3, a4 }); print("{s} {s} {s} {s}\n", .{ a1, a2, a3, a4 });

View file

@ -83,19 +83,19 @@ const DuctError = error{UnmatchedDiameters};
pub fn main() void { pub fn main() void {
// This is a real duck! // This is a real duck!
var ducky1 = Duck{ const ducky1 = Duck{
.eggs = 0, .eggs = 0,
.loudness = 3, .loudness = 3,
}; };
// This is not a real duck, but it has quack() and waddle() // This is not a real duck, but it has quack() and waddle()
// abilities, so it's still a "duck". // abilities, so it's still a "duck".
var ducky2 = RubberDuck{ const ducky2 = RubberDuck{
.in_bath = false, .in_bath = false,
}; };
// This is not even remotely a duck. // This is not even remotely a duck.
var ducky3 = Duct{ const ducky3 = Duct{
.diameter = 17, .diameter = 17,
.length = 165, .length = 165,
.galvanized = true, .galvanized = true,

View file

@ -39,7 +39,7 @@ pub fn main() void {
// This gets the digit from the "instruction". Can you // This gets the digit from the "instruction". Can you
// figure out why we subtract '0' from it? // figure out why we subtract '0' from it?
comptime var digit = instructions[i + 1] - '0'; const digit = instructions[i + 1] - '0';
// This 'switch' statement contains the actual work done // This 'switch' statement contains the actual work done
// at runtime. At first, this doesn't seem exciting... // at runtime. At first, this doesn't seem exciting...

View file

@ -110,7 +110,7 @@ const HermitsNotebook = struct {
} }
fn checkNote(self: *HermitsNotebook, note: NotebookEntry) void { fn checkNote(self: *HermitsNotebook, note: NotebookEntry) void {
var existing_entry = self.getEntry(note.place); const existing_entry = self.getEntry(note.place);
if (existing_entry == null) { if (existing_entry == null) {
self.entries[self.end_of_entries] = note; self.entries[self.end_of_entries] = note;
@ -180,7 +180,7 @@ pub fn main() void {
notebook.checkNote(working_note); notebook.checkNote(working_note);
while (notebook.hasNextEntry()) { while (notebook.hasNextEntry()) {
var place_entry = notebook.getNextEntry(); const place_entry = notebook.getNextEntry();
for (place_entry.place.paths) |*path| { for (place_entry.place.paths) |*path| {
working_note = NotebookEntry{ working_note = NotebookEntry{

View file

@ -46,7 +46,7 @@ pub fn main() void {
var nums = [_:0]u32{ 1, 2, 3, 4, 5, 6 }; var nums = [_:0]u32{ 1, 2, 3, 4, 5, 6 };
// And here's a zero-terminated many-item pointer: // And here's a zero-terminated many-item pointer:
var ptr: [*:0]u32 = &nums; const ptr: [*:0]u32 = &nums;
// For fun, let's replace the value at position 3 with the // For fun, let's replace the value at position 3 with the
// sentinel value 0. This seems kind of naughty. // sentinel value 0. This seems kind of naughty.
@ -74,8 +74,8 @@ pub fn main() void {
fn printSequence(my_seq: anytype) void { fn printSequence(my_seq: anytype) void {
const my_typeinfo = @typeInfo(@TypeOf(my_seq)); const my_typeinfo = @typeInfo(@TypeOf(my_seq));
// The TypeInfo contained in my_type is a union. We use a // The TypeInfo contained in my_typeinfo is a union. We use
// switch to handle printing the Array or Pointer fields, // a switch to handle printing the Array or Pointer fields,
// depending on which type of my_seq was passed in: // depending on which type of my_seq was passed in:
switch (my_typeinfo) { switch (my_typeinfo) {
.Array => { .Array => {

View file

@ -48,13 +48,13 @@ pub fn main() void {
// * circle1 should hold i32 integers // * circle1 should hold i32 integers
// * circle2 should hold f32 floats // * circle2 should hold f32 floats
// //
var circle1 = ??? { const circle1 = ??? {
.center_x = 25, .center_x = 25,
.center_y = 70, .center_y = 70,
.radius = 15, .radius = 15,
}; };
var circle2 = ??? { const circle2 = ??? {
.center_x = 25.234, .center_x = 25.234,
.center_y = 70.999, .center_y = 70.999,
.radius = 15.714, .radius = 15.714,

View file

@ -96,7 +96,7 @@ const Insect = union(enum) {
}; };
pub fn main() !void { pub fn main() !void {
var my_insects = [_]Insect{ const my_insects = [_]Insect{
Insect{ .ant = Ant{ .still_alive = true } }, Insect{ .ant = Ant{ .still_alive = true } },
Insect{ .bee = Bee{ .flowers_visited = 17 } }, Insect{ .bee = Bee{ .flowers_visited = 17 } },
Insect{ .grasshopper = Grasshopper{ .distance_hopped = 32 } }, Insect{ .grasshopper = Grasshopper{ .distance_hopped = 32 } },

View file

@ -40,7 +40,7 @@
// our well-known "import" for Zig // our well-known "import" for Zig
const std = @import("std"); const std = @import("std");
// and here the new the import for C // and here the new import for C
const c = @cImport({ const c = @cImport({
@cInclude("unistd.h"); @cInclude("unistd.h");
}); });

View file

@ -1,19 +1,26 @@
// //
// Often, C functions are used where no equivalent Zig function exists // Often, C functions are used where no equivalent Zig function exists
// yet. Since the integration of a C function is very simple, as already // yet. Okay, that's getting less and less. ;-)
//
// Since the integration of a C function is very simple, as already
// seen in the last exercise, it naturally offers itself to use the // seen in the last exercise, it naturally offers itself to use the
// very large variety of C functions for our own programs. // very large variety of C functions for our own programs.
// As an example: // As an example:
// //
// Let's say we have a given angle of 765.2 degrees. If we want to // Let's say we have a given angle of 765.2 degrees. If we want to
// normalize that, it means that we have to subtract X * 360 degrees // normalize that, it means that we have to subtract X * 360 degrees
// to get the correct angle. How could we do that? A good method is // to get the correct angle.
// to use the modulo function. But if we write "765.2 % 360", it won't // How could we do that? A good method is to use the modulo function.
// work, because the standard modulo function works only with integer // But if we write "765.2 % 360", it only works with float values
// values. In the C library "math", there is a function called "fmod"; // that are known at compile time.
// the "f" stands for floating and means that we can solve modulo for // In Zig, we would use @mod(a, b) instead.
// real numbers. With this function, it should be possible to normalize //
// our angle. Let's go. // Let us now assume that we cannot do this in Zig, but only with
// a C function from the standard library. In the library "math",
// there is a function called "fmod"; the "f" stands for floating
// and means that we can solve modulo for real numbers. With this
// function, it should be possible to normalize our angle.
// Let's go.
const std = @import("std"); const std = @import("std");

View file

@ -30,9 +30,9 @@
// std.debug.print("slice_ptr={*}\n", .{slice_ptr}); // std.debug.print("slice_ptr={*}\n", .{slice_ptr});
// } // }
// Instead of a simple integer or a constant sized slice, this // Instead of a simple integer or a slice with a constant size,
// program requires a slice to be allocated that is the same size as // this program requires allocating a slice that is the same size
// an input array. // as an input array.
// Given a series of numbers, take the running average. In other // Given a series of numbers, take the running average. In other
// words, each item N should contain the average of the last N // words, each item N should contain the average of the last N
@ -52,7 +52,7 @@ fn runningAverage(arr: []const f64, avg: []f64) void {
pub fn main() !void { pub fn main() !void {
// pretend this was defined by reading in user input // pretend this was defined by reading in user input
var arr: []const f64 = &[_]f64{ 0.3, 0.2, 0.1, 0.1, 0.4 }; const arr: []const f64 = &[_]f64{ 0.3, 0.2, 0.1, 0.1, 0.4 };
// initialize the allocator // initialize the allocator
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
@ -64,7 +64,7 @@ pub fn main() !void {
const allocator = arena.allocator(); const allocator = arena.allocator();
// allocate memory for this array // allocate memory for this array
var avg: []f64 = ???; const avg: []f64 = ???;
runningAverage(arr, avg); runningAverage(arr, avg);
std.debug.print("Running Average: ", .{}); std.debug.print("Running Average: ", .{});

View file

@ -1,5 +1,5 @@
// //
// Bit manipulations is a very powerful tool just also from Zig. // Bit manipulation is a very powerful tool, also from Zig.
// Since the dawn of the computer age, numerous algorithms have been // Since the dawn of the computer age, numerous algorithms have been
// developed that solve tasks solely by moving, setting, or logically // developed that solve tasks solely by moving, setting, or logically
// combining bits. // combining bits.
@ -8,10 +8,10 @@
// functions where possible. And it is often possible with calculations // functions where possible. And it is often possible with calculations
// based on integers. // based on integers.
// //
// Often it is not easy to understand at first glance what exactly these // At first glance, it is often not easy to understand what exactly these
// algorithms do when only "numbers" in memory areas change outwardly. // algorithms do when only "numbers" in memory areas change outwardly.
// But it must never be forgotten that the numbers only represent the // However, it should never be forgotten that the numbers only represent
// interpretation of the bit sequences. // the interpretation of the bit sequences.
// //
// Quasi the reversed case we have otherwise, namely that we represent // Quasi the reversed case we have otherwise, namely that we represent
// numbers in bit sequences. // numbers in bit sequences.
@ -20,8 +20,8 @@
// //
// Zig provides all the necessary functions to change the bits inside // Zig provides all the necessary functions to change the bits inside
// a variable. It is distinguished whether the bit change leads to an // a variable. It is distinguished whether the bit change leads to an
// overflow or not.The details are in the Zig documentation in section // overflow or not. The details are in the Zig documentation in section
// 10.1 "Table of Operators". // "Table of Operators".
// //
// Here are some examples of how the bits of variables can be changed: // Here are some examples of how the bits of variables can be changed:
// //

View file

@ -1,5 +1,5 @@
// //
// Another useful practice for bit manipulation is setting bits as flags. // Another useful application for bit manipulation is setting bits as flags.
// This is especially useful when processing lists of something and storing // This is especially useful when processing lists of something and storing
// the states of the entries, e.g. a list of numbers and for each prime // the states of the entries, e.g. a list of numbers and for each prime
// number a flag is set. // number a flag is set.
@ -19,9 +19,9 @@
// For example, you could take an array of bool and set the value to 'true' // For example, you could take an array of bool and set the value to 'true'
// for each letter in the order of the alphabet (a=0; b=1; etc.) found in // for each letter in the order of the alphabet (a=0; b=1; etc.) found in
// the sentence. However, this is neither memory efficient nor particularly // the sentence. However, this is neither memory efficient nor particularly
// fast. Instead we take a simpler way, very similar in principle, we define // fast. Instead we choose a simpler approach that is very similar in principle:
// a variable with at least 26 bits (e.g. u32) and also set the bit for each // We define a variable with at least 26 bits (e.g. u32) and set the bit for
// letter found at the corresponding position. // each letter that is found in the corresponding position.
// //
// Zig provides functions for this in the standard library, but we prefer to // Zig provides functions for this in the standard library, but we prefer to
// solve it without these extras, after all we want to learn something. // solve it without these extras, after all we want to learn something.
@ -39,7 +39,7 @@ fn isPangram(str: []const u8) bool {
// first we check if the string has at least 26 characters // first we check if the string has at least 26 characters
if (str.len < 26) return false; if (str.len < 26) return false;
// we uses a 32 bit variable of which we need 26 bits // we use a 32 bit variable of which we need 26 bits
var bits: u32 = 0; var bits: u32 = 0;
// loop about all characters in the string // loop about all characters in the string
@ -49,7 +49,7 @@ fn isPangram(str: []const u8) bool {
// then we set the bit at the position // then we set the bit at the position
// //
// to do this, we use a little trick: // to do this, we use a little trick:
// since the letters in the ASCI table start at 65 // since the letters in the ASCII table start at 65
// and are numbered sequentially, we simply subtract the // and are numbered sequentially, we simply subtract the
// first letter (in this case the 'a') from the character // first letter (in this case the 'a') from the character
// found, and thus get the position of the desired bit // found, and thus get the position of the desired bit

View file

@ -19,10 +19,10 @@
// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29 // https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29
// //
// Zig already has a very nice selection of formatting options. // Zig already has a very nice selection of formatting options.
// These can be used in different ways, but typically to convert // These can be used in different ways, but generally to convert
// numerical values into various text representations. The // numerical values into various text representations. The results
// results can be used for direct output to a terminal or stored // can be used for direct output to a terminal or stored for
// for later use or written to a file. The latter is useful when // later use or written to a file. The latter is useful when
// large amounts of data are to be processed by other programs. // large amounts of data are to be processed by other programs.
// //
// In Ziglings, we are concerned with the output to the console. // In Ziglings, we are concerned with the output to the console.

View file

@ -1,9 +1,9 @@
// //
// The functionality of the standard library is becoming increasingly // The functionality of the standard library is becoming increasingly
// important in Zig. On the one hand, it is helpful to look at how // important in Zig. First of all, it is helpful to take a look at how
// the individual functions are implemented. Because this is wonderfully // the individual functions are implemented. Because this is wonderfully
// suitable as a template for your own functions. On the other hand, // suitable as a template for your own functions. In addition these
// these standard functions are part of the basic equipment of Zig. // standard functions are part of the basic configuration of Zig.
// //
// This means that they are always available on every system. // This means that they are always available on every system.
// Therefore it is worthwhile to deal with them also in Ziglings. // Therefore it is worthwhile to deal with them also in Ziglings.

134
exercises/104_threading.zig Normal file
View file

@ -0,0 +1,134 @@
//
// Whenever there is a lot to calculate, the question arises as to how
// tasks can be carried out simultaneously. We have already learned about
// one possibility, namely asynchronous processes, in Exercises 84-91.
//
// However, the computing power of the processor is only distributed to
// the started and running tasks, which always reaches its limits when
// pure computing power is called up.
//
// For example, in blockchains based on proof of work, the miners have
// to find a nonce for a certain character string so that the first m bits
// in the hash of the character string and the nonce are zeros.
// As the miner who can solve the task first receives the reward, everyone
// tries to complete the calculations as quickly as possible.
//
// This is where multithreading comes into play, where tasks are actually
// distributed across several cores of the CPU or GPU, which then really
// means a multiplication of performance.
//
// The following diagram roughly illustrates the difference between the
// various types of process execution.
// The 'Overall Time' column is intended to illustrate how the time is
// affected if, instead of one core as in synchronous and asynchronous
// processing, a second core now helps to complete the work in multithreading.
//
// In the ideal case shown, execution takes only half the time compared
// to the synchronous single thread. And even asynchronous processing
// is only slightly faster in comparison.
//
//
// Synchronous Asynchronous
// Processing Processing Multithreading
//
// Thread 1 Thread 1 Thread 1 Thread 2
// Overall Time
//
//
// T T T T
// a a a a
// s s s s
// k k k k
//
// 1 1 1 3
//
// 5 Sec
//
// Blocking T T T
// a a a
// s s s 8 Sec
// k k k
// T
// a 2 2 4
// s
// k 10 Sec
//
// 1 T
// a
// s
// k
// T
// a 1
// s
// k
//
// 2
//
//
//
//
//
// The diagram was modeled on the one in a blog in which the differences
// between asynchronous processing and multithreading are explained in detail:
// https://blog.devgenius.io/multi-threading-vs-asynchronous-programming-what-is-the-difference-3ebfe1179a5
//
// Our exercise is essentially about clarifying the approach in Zig and
// therefore we try to keep it as simple as possible.
// Multithreading in itself is already difficult enough. ;-)
//
const std = @import("std");
pub fn main() !void {
// This is where the preparatory work takes place
// before the parallel processing begins.
std.debug.print("Starting work...\n", .{});
// These curly brackets are very important, they are necessary
// to enclose the area where the threads are called.
// Without these brackets, the program would not wait for the
// end of the threads and they would continue to run beyond the
// end of the program.
{
// Now we start the first thread, with the number as parameter
const handle = try std.Thread.spawn(.{}, thread_function, .{1});
// Waits for the thread to complete,
// then deallocates any resources created on `spawn()`.
defer handle.join();
// Second thread
const handle2 = try std.Thread.spawn(.{}, thread_function, .{-4}); // that can't be right?
defer handle2.join();
// Third thread
const handle3 = try std.Thread.spawn(.{}, thread_function, .{3});
defer ??? // <-- something is missing
// 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.debug.print("Some weird stuff, after starting the threads.\n", .{});
}
// After we have left the closed area, we wait until
// the threads have run through, if this has not yet been the case.
std.debug.print("Zig is cool!\n", .{});
}
// 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.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.debug.print("thread {d}: {s}\n", .{ num, "finished." });
}
// This is the easiest way to run threads in parallel.
// In general, however, more management effort is required,
// e.g. by setting up a pool and allowing the threads to communicate
// with each other using semaphores.
//
// But that's a topic for another exercise.

View file

@ -0,0 +1,107 @@
//
// Now that we are familiar with the principles of multi-threading,
// let's boldly venture into a practical example from mathematics.
// We will determine the circle number PI with sufficient accuracy.
//
// There are different methods for this, and some of them are several
// hundred years old. For us, the dusty procedures are surprisingly well
// suited to our exercise. Because the mathematicians of the time didn't
// have fancy computers with which we can calculate something like this
// in seconds today.
// Whereby, of course, it depends on the accuracy, i.e. how many digits
// after the decimal point we are interested in.
// But these old procedures can still be tackled with paper and pencil,
// which is why they are easier for us to understand.
// At least for me. ;-)
//
// So let's take a mental leap back a few years.
// Around 1672 (if you want to know and read about it in detail, you can
// do so on Wikipedia, for example), various mathematicians once again
// discovered a method of approaching the circle number PI.
// 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
// "Acta Eruditorum".
// This is why this method has become known as the "Leibnitz 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:
//
// 4 4 4 4 4
// PI = --- - --- + --- - --- + --- ...
// 1 3 5 7 9
//
// As you can clearly see, the series starts with the whole number 4 and
// approaches the circle number by subtracting and adding smaller and
// smaller parts of 4. Pretty much everyone has learned PI = 3.14 at school,
// but very few people remember other digits, and this is rarely necessary
// 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
// to calculate for which accuracy?
//
// The answer is chewing, to get 8 digits after the decimal point we need
// 1,000,000,000 partial values. And for each additional digit we have to
// add a zero.
// Even fast computers - and I mean really fast computers - get a bit warmer
// on the CPU when it comes to really many digits. But the 8 digits are
// 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
// 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
// round.
// But wait! The partial values are alternately added and subtracted.
// This could also be achieved with one loop, but not very elegantly.
// It also makes sense to split this between two CPUs, one calculates
// the positive values and the other the negative values. And so we can
// simply start two threads and add everything up at the end and we're
// done.
// We just have to remember that if only the positive or negative values
// are calculated, the distances are twice as large, i.e. 4.
//
// So that the whole thing has a real learning effect, the first thread
// call is specified and you have to make the second.
// But don't worry, it will work out. :-)
//
const std = @import("std");
pub fn main() !void {
const count = 1_000_000_000;
var pi_plus: f64 = 0;
var pi_minus: f64 = 0;
{
// First thread to calculate the plus numbers.
const handle1 = try std.Thread.spawn(.{}, thread_pi, .{ &pi_plus, 5, count });
defer handle1.join();
// Second thread to calculate the minus numbers.
???
}
// Here we add up the results.
std.debug.print("PI ≈ {d:.8}\n", .{4 + pi_plus - pi_minus});
}
fn thread_pi(pi: *f64, begin: u64, end: u64) !void {
var n: u64 = begin;
while (n < end) : (n += 4) {
pi.* += 4 / @as(f64, @floatFromInt(n));
}
}
// If you wish, you can increase the number of loop passes, which
// improves the number of digits.
//
// But be careful:
// In order for parallel processing to really show its strengths,
// the compiler must be given the "-O ReleaseFast" flag when it
// is created. Otherwise the debug functions slow down the speed
// to such an extent that seconds become minutes during execution.
//
// And you should remove the formatting restriction in "print",
// otherwise you will not be able to see the additional digits.

92
exercises/106_files.zig Normal file
View file

@ -0,0 +1,92 @@
//
// Until now, we've only been printing our output in the console,
// which is good enough for fighting alien and hermit bookkeeping.
//
// 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 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, 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
// - write to the file.
//
// import std as always
const std = @import("std");
pub fn main() !void {
// first we get the current working directory
const cwd: std.fs.Dir = std.fs.cwd();
// then we'll try to make a new directory /output/
// to put our output files.
cwd.makeDir("output") catch |e| switch (e) {
// there are chance you might want to run this
// program more than once and the path might already
// been created, so we'll have to handle this error
// by doing nothing
//
// we want to catch error.PathAlreadyExists and do nothing
??? => {},
// if is 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
// opening a directory might fail!
// what should we do here?
var output_dir: std.fs.Dir = cwd.openDir("output", .{});
defer output_dir.close();
// we try to open the file `zigling.txt`,
// 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
// but here we are not yet done writing to the file
// if only there were a keyword in zig that
// allows you "defer" code execute to the end of scope...
file.close();
// !you are not allowed to switch 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 on your text editor, or
// 2. print the content of the file in the console with the following command
// >> cat ./output/zigling.txt
//
//
// More on Creating files
//
// notice in:
// ... try output_dir.createFile("zigling.txt", .{});
// ^^^
// we passed this anonymous struct to the function call
//
// this is the struct `CreateFlag` with default fields
// {
// read: bool = false,
// truncate: bool = true,
// exclusive: bool = false,
// lock: Lock = .none,
// lock_nonblocking: bool = false,
// mode: Mode = default_mode
// }
//
// Question:
// - what should you do if you want to also read the file after opening it?
// - 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?

52
exercises/107_files2.zig Normal file
View file

@ -0,0 +1,52 @@
//
// Prerequisite :
// - exercise/106_files.zig, or
// - create a file {project_root}/output/zigling.txt
// with content `It's zigling time!`(18 byte total)
//
// 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.
// - 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 to the array
// - Finally, we print out the read content
const std = @import("std");
pub fn main() !void {
// Get the current working directory
const cwd = std.fs.cwd();
// try to open ./output assuming you did your 106_files exercise
var output_dir = try cwd.openDir("output", .{});
defer output_dir.close();
// try to open the file
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.
// fix the initalization below
var content = ['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 ?
// https://ziglang.org/documentation/master/std/#std.fs.File
// hint: you might find two answers that are both vaild 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
// 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
});
}

View file

@ -1,11 +1,11 @@
--- exercises/025_errors5.zig 2023-10-03 22:15:22.122241138 +0200 --- exercises/025_errors5.zig 2023-11-21 14:22:48.159250165 +0100
+++ answers/025_errors5.zig 2023-10-05 20:04:06.952764946 +0200 +++ answers/025_errors5.zig 2023-11-21 14:25:01.338277886 +0100
@@ -26,7 +26,7 @@ @@ -26,7 +26,7 @@
// This function needs to return any error which might come back from detect(). // This function needs to return any error which might come back from detect().
// Please use a "try" statement rather than a "catch". // Please use a "try" statement rather than a "catch".
// //
- var x = detect(n); - const x = detect(n);
+ var x = try detect(n); + const x = try detect(n);
return x + 5; return x + 5;
} }

View file

@ -1,5 +1,5 @@
--- exercises/046_optionals2.zig 2023-10-03 22:15:22.122241138 +0200 --- exercises/046_optionals2.zig 2024-05-10 23:11:25.796632478 +0200
+++ answers/046_optionals2.zig 2023-10-05 20:04:07.049433424 +0200 +++ answers/046_optionals2.zig 2024-05-10 23:10:16.115335668 +0200
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
const Elephant = struct { const Elephant = struct {
@ -9,12 +9,11 @@
visited: bool = false, visited: bool = false,
}; };
@@ -51,7 +51,7 @@ @@ -51,6 +51,6 @@
// We should stop once we encounter a tail that // We should stop once we encounter a tail that
// does NOT point to another element. What can // does NOT point to another element. What can
// we put here to make that happen? // we put here to make that happen?
- if (e.tail == null) ???; - e = e.tail ???
+ if (e.tail == null) break; + e = e.tail orelse break;
e = e.tail.?;
} }
}

View file

@ -1,5 +1,5 @@
--- exercises/051_values.zig 2023-10-03 22:15:22.122241138 +0200 --- exercises/051_values.zig 2024-03-14 23:25:42.695020607 +0100
+++ answers/051_values.zig 2023-10-05 20:04:07.072767194 +0200 +++ answers/051_values.zig 2024-03-14 23:28:34.525109174 +0100
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
// Let's assign the std.debug.print function to a const named // Let's assign the std.debug.print function to a const named
// "print" so that we can use this new name later! // "print" so that we can use this new name later!
@ -9,7 +9,7 @@
// Now let's look at assigning and pointing to values in Zig. // Now let's look at assigning and pointing to values in Zig.
// //
@@ -152,13 +152,13 @@ @@ -163,13 +163,13 @@
print("XP before:{}, ", .{glorp.experience}); print("XP before:{}, ", .{glorp.experience});
// Fix 1 of 2 goes here: // Fix 1 of 2 goes here:

View file

@ -1,11 +1,11 @@
--- exercises/060_floats.zig 2023-10-03 22:15:22.125574535 +0200 --- exercises/060_floats.zig 2023-11-06 19:45:03.609687304 +0100
+++ answers/060_floats.zig 2023-10-05 20:04:07.112767942 +0200 +++ answers/060_floats.zig 2023-11-06 19:44:49.249419994 +0100
@@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
// //
// We'll convert this weight from tons to kilograms at a // We'll convert this weight from pound to kilograms at a
// conversion of 907.18kg to the ton. // conversion of 0.453592kg to the pound.
- const shuttle_weight: f16 = 907.18 * 2200; - const shuttle_weight: f16 = 0.453592 * 4480e6;
+ const shuttle_weight: f32 = 907.18 * 2200.0; + const shuttle_weight: f32 = 0.453592 * 4.480e6;
// By default, float values are formatted in scientific // By default, float values are formatted in scientific
// notation. Try experimenting with '{d}' and '{d:.3}' to see // notation. Try experimenting with '{d}' and '{d:.3}' to see

View file

@ -1,5 +1,5 @@
--- exercises/067_comptime2.zig 2023-10-03 22:15:22.125574535 +0200 --- exercises/067_comptime2.zig 2023-11-21 14:36:12.080295365 +0100
+++ answers/067_comptime2.zig 2023-10-05 20:04:07.146101899 +0200 +++ answers/067_comptime2.zig 2023-11-21 15:11:50.814098876 +0100
@@ -35,7 +35,7 @@ @@ -35,7 +35,7 @@
// In this contrived example, we've decided to allocate some // In this contrived example, we've decided to allocate some
// arrays using a variable count! But something's missing... // arrays using a variable count! But something's missing...
@ -8,4 +8,4 @@
+ comptime var count = 0; + comptime var count = 0;
count += 1; count += 1;
var a1: [count]u8 = .{'A'} ** count; const a1: [count]u8 = .{'A'} ** count;

View file

@ -1,5 +1,5 @@
--- exercises/075_quiz8.zig 2023-10-03 22:15:22.125574535 +0200 --- exercises/075_quiz8.zig 2023-11-21 14:48:15.440702720 +0100
+++ answers/075_quiz8.zig 2023-10-05 20:04:07.182769252 +0200 +++ answers/075_quiz8.zig 2023-11-21 14:50:23.453311616 +0100
@@ -49,7 +49,11 @@ @@ -49,7 +49,11 @@
// //
// Please fill in the body of this function! // Please fill in the body of this function!

View file

@ -1,18 +1,18 @@
--- exercises/080_anonymous_structs.zig 2023-10-03 22:15:22.125574535 +0200 --- exercises/080_anonymous_structs.zig 2023-11-21 14:52:54.312749682 +0100
+++ answers/080_anonymous_structs.zig 2023-10-05 20:04:07.202769626 +0200 +++ answers/080_anonymous_structs.zig 2023-11-21 14:52:43.909225238 +0100
@@ -48,13 +48,13 @@ @@ -48,13 +48,13 @@
// * circle1 should hold i32 integers // * circle1 should hold i32 integers
// * circle2 should hold f32 floats // * circle2 should hold f32 floats
// //
- var circle1 = ??? { - const circle1 = ??? {
+ var circle1 = Circle(i32){ + const circle1 = Circle(i32){
.center_x = 25, .center_x = 25,
.center_y = 70, .center_y = 70,
.radius = 15, .radius = 15,
}; };
- var circle2 = ??? { - const circle2 = ??? {
+ var circle2 = Circle(f32){ + const circle2 = Circle(f32){
.center_x = 25.234, .center_x = 25.234,
.center_y = 70.999, .center_y = 70.999,
.radius = 15.714, .radius = 15.714,

View file

@ -1,6 +1,6 @@
--- exercises/094_c_math.zig 2023-10-22 14:00:02.909379696 +0200 --- exercises/094_c_math.zig 2024-02-28 12:50:35.789939935 +0100
+++ answers/094_c_math.zig 2023-10-22 14:02:46.709025235 +0200 +++ answers/094_c_math.zig 2024-02-28 12:53:57.910309471 +0100
@@ -19,7 +19,7 @@ @@ -26,7 +26,7 @@
const c = @cImport({ const c = @cImport({
// What do we need here? // What do we need here?

View file

@ -1,11 +1,11 @@
--- exercises/096_memory_allocation.zig 2023-10-03 22:15:22.125574535 +0200 --- exercises/096_memory_allocation.zig 2023-11-21 14:55:33.805678390 +0100
+++ answers/096_memory_allocation.zig 2023-10-05 20:04:07.276104333 +0200 +++ answers/096_memory_allocation.zig 2023-11-21 14:56:00.236163484 +0100
@@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
const allocator = arena.allocator(); const allocator = arena.allocator();
// allocate memory for this array // allocate memory for this array
- var avg: []f64 = ???; - const avg: []f64 = ???;
+ var avg: []f64 = try allocator.alloc(f64, arr.len); + const avg: []f64 = try allocator.alloc(f64, arr.len);
runningAverage(arr, avg); runningAverage(arr, avg);
std.debug.print("Running Average: ", .{}); std.debug.print("Running Average: ", .{});

View file

@ -0,0 +1,17 @@
--- exercises/104_threading.zig 2024-04-10 19:12:29.878856370 +0200
+++ answers/104_threading.zig 2024-04-10 19:11:22.304265713 +0200
@@ -97,12 +97,12 @@
defer handle.join();
// Second thread
- const handle2 = try std.Thread.spawn(.{}, thread_function, .{-4}); // that can't be right?
+ const handle2 = try std.Thread.spawn(.{}, thread_function, .{2});
defer handle2.join();
// Third thread
const handle3 = try std.Thread.spawn(.{}, thread_function, .{3});
- defer ??? // <-- something is missing
+ defer handle3.join();
// After the threads have been started,
// they run in parallel and we can still do some work in between.

View file

@ -0,0 +1,13 @@
--- exercises/105_threading2.zig 2024-03-23 16:35:14.754540802 +0100
+++ answers/105_threading2.zig 2024-03-23 16:38:00.577539733 +0100
@@ -81,8 +81,8 @@
defer handle1.join();
// Second thread to calculate the minus numbers.
- ???
-
+ const handle2 = try std.Thread.spawn(.{}, thread_pi, .{ &pi_minus, 3, count });
+ defer handle2.join();
}
// Here we add up the results.
std.debug.print("PI ≈ {d:.8}\n", .{4 + pi_plus - pi_minus});

View file

@ -0,0 +1,29 @@
--- exercises/106_files.zig 2024-05-05 00:48:25.808548611 +0200
+++ answers/106_files.zig 2024-05-05 01:00:40.742969819 +0200
@@ -35,7 +35,7 @@
// by doing nothing
//
// we want to catch error.PathAlreadyExists and do nothing
- ??? => {},
+ error.PathAlreadyExists => {},
// if is any other unexpected error we just propagate it through
else => return e,
};
@@ -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", .{});
+ var output_dir: std.fs.Dir = try cwd.openDir("output", .{});
defer output_dir.close();
// we try to open the file `zigling.txt`,
@@ -55,7 +55,7 @@
// but here we are not yet done writing to the file
// if only there were a keyword in zig that
// allows you "defer" code execute to the end of scope...
- file.close();
+ defer file.close();
// !you are not allowed to switch these two lines above the file closing line!
const byte_written = try file.write("It's zigling time!");

View file

@ -0,0 +1,26 @@
--- exercises/107_files2.zig 2024-05-05 00:48:25.808548611 +0200
+++ answers/107_files2.zig 2024-05-05 01:14:03.866062288 +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});
@@ -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 vaild 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 ?
std.debug.print("Successfully Read {d} bytes: {s}\n", .{
bytes_read,
- content, // change this line only
+ content[0..bytes_read], // change this line only
});
}

View file

@ -8,8 +8,8 @@ const mem = std.mem;
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const Child = std.process.Child; const Child = std.process.Child;
const Build = std.build; const Build = std.Build;
const FileSource = std.Build.FileSource; const LazyPath = std.Build.LazyPath;
const Reader = fs.File.Reader; const Reader = fs.File.Reader;
const RunStep = std.Build.RunStep; const RunStep = std.Build.RunStep;
const Step = Build.Step; const Step = Build.Step;
@ -33,7 +33,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
const n = ex.number(); const n = ex.number();
const cmd = b.addSystemCommand(&.{ const cmd = b.addSystemCommand(&.{
b.zig_exe, b.graph.zig_exe,
"build", "build",
"-Dhealed", "-Dhealed",
b.fmt("-Dhealed-path={s}", .{tmp_path}), b.fmt("-Dhealed-path={s}", .{tmp_path}),
@ -69,7 +69,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
// TODO: when an exercise is modified, the cache is not invalidated. // TODO: when an exercise is modified, the cache is not invalidated.
const cmd = b.addSystemCommand(&.{ const cmd = b.addSystemCommand(&.{
b.zig_exe, b.graph.zig_exe,
"build", "build",
"-Dhealed", "-Dhealed",
b.fmt("-Dhealed-path={s}", .{tmp_path}), b.fmt("-Dhealed-path={s}", .{tmp_path}),
@ -99,7 +99,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
const n = ex.number(); const n = ex.number();
const cmd = b.addSystemCommand(&.{ const cmd = b.addSystemCommand(&.{
b.zig_exe, b.graph.zig_exe,
"build", "build",
b.fmt("-Dn={}", .{n}), b.fmt("-Dn={}", .{n}),
}); });
@ -132,9 +132,9 @@ fn createCase(b: *Build, name: []const u8) *Step {
const CheckNamedStep = struct { const CheckNamedStep = struct {
step: Step, step: Step,
exercise: Exercise, exercise: Exercise,
stderr: FileSource, stderr: LazyPath,
pub fn create(owner: *Build, exercise: Exercise, stderr: FileSource) *CheckNamedStep { pub fn create(owner: *Build, exercise: Exercise, stderr: LazyPath) *CheckNamedStep {
const self = owner.allocator.create(CheckNamedStep) catch @panic("OOM"); const self = owner.allocator.create(CheckNamedStep) catch @panic("OOM");
self.* = .{ self.* = .{
.step = Step.init(.{ .step = Step.init(.{
@ -152,7 +152,7 @@ const CheckNamedStep = struct {
fn make(step: *Step, _: *std.Progress.Node) !void { fn make(step: *Step, _: *std.Progress.Node) !void {
const b = step.owner; const b = step.owner;
const self = @fieldParentPtr(CheckNamedStep, "step", step); const self: *CheckNamedStep = @alignCast(@fieldParentPtr("step", step));
const ex = self.exercise; const ex = self.exercise;
const stderr_file = try fs.cwd().openFile( const stderr_file = try fs.cwd().openFile(
@ -180,12 +180,12 @@ const CheckNamedStep = struct {
const CheckStep = struct { const CheckStep = struct {
step: Step, step: Step,
exercises: []const Exercise, exercises: []const Exercise,
stderr: FileSource, stderr: LazyPath,
pub fn create( pub fn create(
owner: *Build, owner: *Build,
exercises: []const Exercise, exercises: []const Exercise,
stderr: FileSource, stderr: LazyPath,
) *CheckStep { ) *CheckStep {
const self = owner.allocator.create(CheckStep) catch @panic("OOM"); const self = owner.allocator.create(CheckStep) catch @panic("OOM");
self.* = .{ self.* = .{
@ -204,7 +204,7 @@ const CheckStep = struct {
fn make(step: *Step, _: *std.Progress.Node) !void { fn make(step: *Step, _: *std.Progress.Node) !void {
const b = step.owner; const b = step.owner;
const self = @fieldParentPtr(CheckStep, "step", step); const self: *CheckStep = @alignCast(@fieldParentPtr("step", step));
const exercises = self.exercises; const exercises = self.exercises;
const stderr_file = try fs.cwd().openFile( const stderr_file = try fs.cwd().openFile(
@ -327,7 +327,7 @@ const FailStep = struct {
fn make(step: *Step, _: *std.Progress.Node) !void { fn make(step: *Step, _: *std.Progress.Node) !void {
const b = step.owner; const b = step.owner;
const self = @fieldParentPtr(FailStep, "step", step); const self: *FailStep = @alignCast(@fieldParentPtr("step", step));
try step.result_error_msgs.append(b.allocator, self.error_msg); try step.result_error_msgs.append(b.allocator, self.error_msg);
return error.MakeFailed; return error.MakeFailed;
@ -370,7 +370,7 @@ const HealStep = struct {
fn make(step: *Step, _: *std.Progress.Node) !void { fn make(step: *Step, _: *std.Progress.Node) !void {
const b = step.owner; const b = step.owner;
const self = @fieldParentPtr(HealStep, "step", step); const self: *HealStep = @alignCast(@fieldParentPtr("step", step));
return heal(b.allocator, self.exercises, self.work_path); return heal(b.allocator, self.exercises, self.work_path);
} }