Compare commits

...

205 Commits

Author SHA1 Message Date
Chris Boesch
cabbef97e8 Merge pull request '108: Make pretty' (#275) from felixrabe/exercises:felixrabe-patch-6 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/275
2025-06-03 23:11:57 +02:00
felixrabe
b1223f92ed 108: . 2025-06-01 01:08:07 +02:00
felixrabe
91f1c045bc 108: Make pretty 2025-06-01 01:05:37 +02:00
Chris Boesch
fd764e90ab Merge pull request 'Add ')'' (#268) from felixrabe/exercises:felixrabe-patch-1 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/268
2025-05-30 14:27:08 +02:00
felixrabe
76b8fcdb28 Add ')' 2025-05-30 12:12:26 +02:00
Chris Boesch
54b2b58b6a Merge pull request 'Exercise 097 - Changed the values for better understanding' (#251) from i210 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/251
2025-05-12 19:51:58 +00:00
Chris Boesch
761fb1a501
Changed the values for better understanding 2025-05-12 21:36:37 +02:00
chrboesch
377d184cdc new issue template 2025-04-14 17:05:40 +00:00
Chris Boesch
d7052e4137 Merge pull request 'fix: typos' (#222) from ddogfoodd/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/222
2025-03-22 10:47:00 +00:00
Jost Alemann
522b4673a4 fix: typos 2025-03-20 21:24:40 +01:00
Chris Boesch
7ce659f7fa Merge pull request 'Rectify 106 and 107 patches' (#219) from dustdfg/exercises:patch_rectify into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/219
2025-03-14 21:15:20 +00:00
Chris Boesch
02edb1f5c6 Merge branch 'main' into patch_rectify 2025-03-14 21:04:11 +00:00
Chris Boesch
5734e68789 Merge pull request 'Update type info for StructField type in 082' (#218) from dustdfg/exercises:update_struct_field into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/218
2025-03-14 20:49:25 +00:00
Yevhen Babiichuk (DustDFG)
1a9b7ec342 Rectify 106 and 107 patches
Signed-off-by: Yevhen Babiichuk (DustDFG) <dfgdust@gmail.com>
2025-03-14 22:26:20 +02:00
Yevhen Babiichuk (DustDFG)
6f3cdcf018 Update type info for StructField type in 082
Signed-off-by: Yevhen Babiichuk (DustDFG) <dfgdust@gmail.com>
2025-03-14 16:47:27 +02:00
Chris Boesch
eeb1246c2c Merge pull request 'Updated version number' (#215) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/215
2025-03-10 10:54:22 +00:00
Chris Boesch
e0ecff7045
Updated version number 2025-03-10 10:02:07 +01:00
Chris Boesch
ce64fe5a1a Merge pull request 'Shuttle weight fixed w.r.t. issue-211' (#212) from mz0/ziglings:shuttle-weight into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/212
2025-03-03 21:45:34 +00:00
mz0
a22f1df0a1 Shuttle weight fixed w.r.t. issue-211 2025-03-03 20:32:41 +04:00
Chris Boesch
2a9ef2d2c8 Merge pull request 'Shuttle weight fixed' (#208) from e60 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/208
2025-02-14 08:29:31 +00:00
Chris Boesch
f285bd59a4
Output from #60 adapted 2025-02-14 09:22:36 +01:00
Chris Boesch
7382949018
Shuttle weight fixed 2025-02-14 09:17:16 +01:00
Chris Boesch
0e0cafb71e Merge pull request 'Suggesting a third exercise for bit manipulation' (#202) from alexsisco/zigling-exercises:bit_man3 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/202
2025-02-13 22:27:29 +00:00
Chris Boesch
064184c8a7 Merge branch 'main' into bit_man3 2025-02-13 22:22:55 +00:00
Alexander Sisco
cd94f6023c fixed spelling of 'bitmask' 2025-02-13 13:14:29 -08:00
Alexander Sisco
90e90c997e fixed formatting 2025-02-13 12:45:46 -08:00
Alexander Sisco
8384d4d9bf fixed minor spelling and grammar typos 2025-02-12 12:59:29 -08:00
Alexander Sisco
2437edd51f fixed incorrect bitmask in xor example 2025-02-11 15:21:26 -08:00
Alexander Sisco
f7e8d4c444 added header for quiz problems 2025-02-11 15:13:25 -08:00
Alexander Sisco
b7b3297d06 added blank lines between sections to make them
easier to find
2025-02-11 15:11:55 -08:00
Alexander Sisco
6fbf81d929 edited the first two paragraphs 2025-02-11 15:07:51 -08:00
Alexander Sisco
465536baf0 made some simple changes to the wording to reflect
the fact that this is a quiz
2025-02-11 13:45:51 -08:00
Alexander Sisco
a7cd808bb8 moved explanatory content below the broken code in
main so that the exercise functions more like a quiz
2025-02-11 11:56:57 -08:00
Alexander Sisco
20596bc290 converted 110 to a quiz (quiz 9) 2025-02-10 21:33:15 -08:00
Chris Boesch
0af4f75e07 Merge pull request 'Fix repo link' (#207) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/207
2025-02-10 09:56:28 +00:00
Chris Boesch
d75f49b25b
Fix repo link 2025-02-10 10:50:57 +01:00
Chris Boesch
838fb4ab9d Merge branch 'main' into bit_man3 2025-02-09 20:58:41 +00:00
Chris Boesch
c13a00fc71 Merge pull request 'Added deletion of progress.txt for eowyn' (#206) from eowyn_fix into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/206
2025-02-09 20:57:18 +00:00
Chris Boesch
c1777f47d5
Added delte_progress additional to the end of eowyn 2025-02-09 21:42:31 +01:00
Chris Boesch
c02e6ead16
Added deletion of progress.txt for eowyn 2025-02-09 21:31:07 +01:00
Chris Boesch
b3dd04885d Merge pull request 'issue201-adding-progress-tracking' (#203) from zendril/exercises:issue201-adding-progress-tracking into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/203
2025-02-09 20:16:55 +00:00
Chris Boesch
bfa0e624f1 Merge pull request 'Skip 74, the compiler corrects this now.' (#205) from i204 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/205
2025-02-09 15:54:11 +00:00
Chris Boesch
b38d70002a
Skip 74, the compiler corrects this now. 2025-02-09 16:34:56 +01:00
Alexander Sisco
1478d41801 added patch file for exercise 110 2025-02-08 13:15:48 -08:00
Alexander Sisco
596d5e50ca format fix 2025-02-08 13:09:12 -08:00
Zendril
a9487c246f cleanup for PR 2025-02-04 22:24:52 -05:00
Zendril
e09c11a16a cleanup for PR 2025-02-04 21:29:56 -05:00
Zendril
92c7235362 cleanup for PR 2025-02-04 21:29:46 -05:00
Zendril
0903c5927b cleanup for PR 2025-02-04 21:14:41 -05:00
Zendril
8e6a52d5a6 tracking, skipping and reset all wired in 2025-02-04 21:13:33 -05:00
Zendril
e54b30f3d3 fmt 2025-02-04 15:37:01 -05:00
Zendril
4ac1d70f93 reset and completed exercise tracking wired in 2025-02-04 15:35:14 -05:00
Alexander Sisco
502ac8711e added newline between toggle and set sections to
make the expected output match
2025-02-04 09:31:29 -08:00
Alexander Sisco
0fa86eb8c8 rearranged order of expected output in build.zig 2025-02-04 09:06:23 -08:00
Alexander Sisco
657fd6aff0 changed the order of the sections to improve flow 2025-02-04 08:57:23 -08:00
Alexander Sisco
3faad6e17b Suggesting a third exercise for bit manipulation 2025-02-03 23:24:34 -08:00
Chris Boesch
fabedb4a24 Merge pull request 'Use print alias in exercise 100_for4.zig' (#198) from Zorgatone/ziglings-solutions:use-print-alias into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/198
2025-01-09 15:27:12 +00:00
Chris Boesch
b1fcca9d82 Merge pull request 'Update: 108 Labeled switch example to contain default case for exhaustion' (#196) from mikkurogue/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/196
closes #195
2025-01-08 14:30:04 +00:00
Chris Boesch
a47dfe1f4d Merge branch 'main' into main 2025-01-08 13:26:15 +00:00
chrboesch
90d05995b5 Update exercises/108_labeled_switch.zig
Fixed an error in the debug statement and made the text a bit more coherent.

Signed-off-by: chrboesch <chrboesch@noreply.codeberg.org>
2025-01-08 13:22:29 +00:00
chrboesch
54f743ba43 Update exercises/108_labeled_switch.zig
The sentence was slightly unclear

Signed-off-by: chrboesch <chrboesch@noreply.codeberg.org>
2025-01-08 12:18:25 +00:00
mikkurogue
87b258d0a9 Fix a typo: we need do we need to -> we need to
Morning delirium does not help when looking at lots of words
2025-01-07 18:00:16 +00:00
Zorgatone
6b29634279 Fix patch after print alias fix in 100_fo4.zig 2025-01-07 15:26:04 +00:00
Zorgatone
c2dcaf3099 Use print alias in exercise 100_for4.zig 2025-01-07 15:21:36 +00:00
mikkurogue
5cdaee7420 Update: Remove the 4th branch in favour of just making that the else branch
Probably easier to not have an "unused" branch that returns the same as the else branch in the example.

Signed-off-by: mikkurogue <mikkurogue@noreply.codeberg.org>
2025-01-07 10:15:59 +00:00
Chris Boesch
468e3d7eed Merge pull request 'Fix typo vaild → valid' (#197) from zyzzyxdonta/ziglings-exercises:fix-typo-vaild-valid into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/197
2025-01-04 23:45:10 +00:00
David Pape
26978cb2d3 Fix typo vaild → valid 2025-01-04 21:40:19 +01:00
mikkurogue
de353bcb3b Update: 108 Labeled switch example to contain default case for exhaustion
Update example text to give clarity on default/exhaustive case.

Reasoning:
The input for the example will not compile if user would want to test this for the logic of a labeled switch. Due the input not being an exhaustive input but rather "any u8 integer" (for the lack of better terminology) we need to use the else branch to indicate that the default case is handled, in this case by just emulating the '4' branch, but this could return an error.InvalidCaseProvided for example.

Signed-off-by: mikkurogue <michael.lindemans@outlook.com>
2025-01-04 11:56:25 +00:00
Chris Boesch
5ed3af57ee Merge pull request 'Updated credits' (#192) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/192
2024-12-22 15:50:29 +00:00
Chris Boesch
105c98782c
Updated credits 2024-12-22 15:59:21 +01:00
Chris Boesch
f446402105
Updated credits 2024-12-22 15:52:52 +01:00
Chris Boesch
8da60edb82 Merge pull request 'Minor case-related changes.' (#184) from innerviewer/exercises:fix-consistent-naming-106 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/184
2024-11-09 22:36:35 +00:00
innerviewer
83e00872b8
Added patch file. 2024-11-09 20:36:47 +01:00
innerviewer
02bd0b2022 Merge branch 'main' into fix-consistent-naming-106 2024-11-09 13:28:43 +00:00
Chris Boesch
63951df523 Merge pull request 'Deleted unnecessary pointer.' (#185) from fix-176 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/185
2024-11-08 22:02:07 +00:00
Chris Boesch
0d9458807e
Deleted unnecessary pointer. 2024-11-08 22:48:37 +01:00
Chris Boesch
ae541a0d9c Merge pull request 'Added SIMD.' (#178) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/178
2024-11-08 21:34:21 +00:00
Chris Boesch
fb46871dab Merge branch 'main' into readme 2024-11-08 21:34:00 +00:00
Chris Boesch
2606e53733 Merge pull request 'Added missing space after a sentence.' (#182) from innerviewer/exercises:fix-typo-105 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/182
2024-11-08 21:32:45 +00:00
innerviewer
33d61cb3c9
Minor case-related changes. 2024-11-08 13:29:44 +01:00
innerviewer
e55f8e8699
Added missing space after a sentence. 2024-11-07 22:05:00 +01:00
Chris Boesch
4d4eefa523 Merge pull request 'Fixed link to format source code.' (#180) from fix-link-99 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/180
2024-11-07 20:51:59 +00:00
Chris Boesch
37a0f42621
Fixed link to format source code. 2024-11-07 21:45:47 +01:00
Chris Boesch
97c2ea2f49
Added SIMD. 2024-11-07 15:30:13 +01:00
Chris Boesch
731a3eb0a6 Merge pull request 'vectors-addition' (#177) from vectors-addition into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/177

Thank you @bgthompson for this great exercise!
2024-11-07 14:24:51 +00:00
Chris Boesch
bfed660020
Fixed formating, created patch file. 2024-11-07 15:01:59 +01:00
bgthompson
46e8fc0b61 line ending format patch attempt 2024-11-07 13:42:53 +10:00
bgthompson
8cce587d3b added patch file for 109_vectors 2024-11-07 13:31:32 +10:00
bgthompson
75e5e53497 removed commented solution lines in vectors exercise, added ??? into lines instead 2024-11-03 11:18:18 +10:00
bgthompson
c90d6015e3 created a new exercise about vectors in zig, gave it number 109 2024-11-03 11:16:00 +10:00
Chris Boesch
150b3de299 Merge pull request 'Improved maximumNarcissism' (#174) from pr173 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/174
2024-11-02 16:13:53 +00:00
Chris Boesch
fb018d212c
Improved maximumNarcissism 2024-11-02 17:03:46 +01:00
Chris Boesch
d0d31ae73a Merge pull request 'reuse fields' (#173) from rofrol/ziglings--exercises:reuse-fields into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/173
2024-11-02 15:54:34 +00:00
Roman Frołow
530dcde3d4 patch 2024-11-02 14:38:53 +01:00
Roman Frołow
286439cddc zero 2024-11-02 14:37:41 +01:00
Roman Frołow
f629d78268 reuse fields 2024-11-02 10:48:50 +01:00
Chris Boesch
71b4f5ea81 Merge pull request 'Fixed patch from quiz7 after text changes' (#171) from quiz7 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/171
2024-10-28 19:41:59 +00:00
Chris Boesch
8f49400aa1
Fixed patch from quiz7 after text changes
#Please enter the commit message for your changes. Lines starting
2024-10-28 09:40:17 +01:00
Chris Boesch
e2b20b3406 Merge pull request 'Rephrase instruction for clarity' (#170) from factormystic/exercises:quiz-7-instruction-clarify into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/170
2024-10-27 15:03:25 +00:00
factormystic
02478759b4 Rephrase instruction for clarity 2024-10-26 20:43:47 +00:00
Chris Boesch
173af62d34 Merge pull request 'Deleted .devcontainer because ist was a test.' (#165) from rm_devcont into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/165
2024-09-20 17:15:58 +00:00
Chris Boesch
9d1da38d38
Deleted .devcontainer because ist was a test. 2024-09-20 18:48:30 +02:00
Chris Boesch
775f5ebd29 Merge pull request 'Added Dave as initiator of Ziglings.' (#164) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/164
2024-09-20 11:21:28 +00:00
Chris Boesch
96df8ba304
Added Dave as initiator of Ziglings. 2024-09-20 12:45:23 +02:00
Chris Boesch
67c824118e Merge pull request 'Minor improvements.' (#163) from patch_lbl_sw into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/163
2024-09-20 10:19:26 +00:00
Chris Boesch
d1b49f353e
Minor improvements. 2024-09-20 12:10:55 +02:00
Chris Boesch
94b5b4bf4b Merge pull request 'Add a new exercise for a labeled switch' (#161) from nm-remarkable/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/161
2024-09-19 10:16:08 +00:00
Nuno Mendes
f0c2c56087 update108 .patch due to line change 2024-09-18 23:29:08 +02:00
Nuno Mendes
ed1a20d51b improve explanantions in labeled switch 2024-09-18 23:26:33 +02:00
Nuno Mendes
d9ce18631d downgrade zig version to eowyn version
It is just 2 days behind so all features are already present for the new labeled switch test
2024-09-16 18:44:36 +02:00
Nuno Mendes
db569a1478 update labeled switch to also have a break statement 2024-09-16 18:39:54 +02:00
Nuno Mendes
798bb40396 update zig version in build and readme 2024-09-16 18:34:35 +02:00
Nuno Mendes
580e126266 Add .patch for 108_labeled_switch 2024-09-15 20:16:57 +02:00
Nuno Mendes
335a78f8f5 108: Add a exercise for a labeled switch 2024-09-15 20:14:49 +02:00
Chris Boesch
102ba8c894 Merge pull request 'Update README.md' (#160) from chrboesch-readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/160
2024-09-11 19:13:46 +00:00
chrboesch
827146f680 Update README.md
Added new todo for core lang
2024-09-11 17:49:54 +00:00
Chris Boesch
995a7c8f36 Merge pull request 'New patch file for 82' (#158) from p_struct_typeinfo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/158
2024-09-07 17:46:59 +00:00
Chris Boesch
f28346d009
New patch file for 82 2024-09-07 19:36:45 +02:00
Chris Boesch
3dc79ca9c3 Merge pull request 'Corrects the description of the new @typeInfo().@"struct".fields' (#157) from p_struct_typeinfo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/157
2024-09-07 17:25:35 +00:00
Chris Boesch
26f4785a99
Corrects the description of the new @typeInfo().@"struct".fields 2024-09-07 19:21:57 +02:00
Chris Boesch
b9cde40610 Merge pull request 'Update LICENSE' (#155) from chrboesch-lic-patch-1 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/155
2024-09-07 12:53:26 +00:00
chrboesch
c8b60f2c30 Update LICENSE 2024-09-07 12:53:07 +00:00
Chris Boesch
c9a98ad555 Merge pull request 'Reseted the simplification for de-referencing.' (#154) from i152 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/154
2024-09-04 18:59:51 +00:00
Chris Boesch
49e0c32ec5 Merge branch 'main' into i152 2024-09-04 18:59:27 +00:00
Chris Boesch
7f1df86938
Reseted the simplification for de-referencing. 2024-09-04 20:52:42 +02:00
Chris Boesch
b0f859c62f Merge pull request 'fixed typo: the date in version changes' (#153) from Seeingu/exercises:main-typo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/153
2024-09-04 18:29:15 +00:00
Seeingu
a6759458b0 fixed typo: the date in version changes 2024-09-04 10:09:21 +08:00
Chris Boesch
2e5b570aef Merge pull request 'Fixes several changes in std.builtin.zig' (#150) from i149 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/150
2024-09-02 17:57:42 +00:00
Chris Boesch
b2f56c7cea
Fixes several changes in std.builtin.zig 2024-09-02 19:33:59 +02:00
Chris Boesch
296a2b5c6a Merge pull request 'Fixes changes in zig build system.' (#148) from i_147 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/148
2024-08-22 16:44:30 +00:00
Chris Boesch
8e35cf7990
Insert wrong version number into build file. 2024-08-22 18:32:36 +02:00
Chris Boesch
dab5197027
Fixes changes in zig build system. 2024-08-22 18:19:21 +02:00
Chris Boesch
ed88236fa7 Merge pull request 'Added license to contributing' (#146) from contrib_lic into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/146
2024-08-19 12:19:05 +00:00
Chris Boesch
031e11aa61
Added license to contributing 2024-08-19 14:04:48 +02:00
Chris Boesch
118c1252be Merge pull request 'Simplified de-referencing for clarification' (#143) from i139 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/143
2024-08-11 16:43:17 +00:00
Chris Boesch
3baf0ae657
Simplified de-referencing for clarification 2024-08-11 18:23:48 +02:00
Chris Boesch
97c8bc39bc Merge pull request 'Clarification in description for ranges in loops.' (#142) from i141 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/142
2024-08-11 14:48:05 +00:00
Chris Boesch
17f9312034
Clarification in description for ranges in loops. 2024-08-11 16:29:14 +02:00
Chris Boesch
e2f356d95c Merge pull request 'Add build parameter to start at a specific exercise' (#140) from mythmon/ziglings-exercises:build-start-from into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/140
2024-08-09 10:21:08 +00:00
Michael Cooper
70b0522cb2
Add build parameter to start at a specific exercise 2024-08-08 08:23:14 -07:00
Chris Boesch
94d6a4da5f Merge pull request 'Changed needed zig version.' (#138) from pr_130 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/138
2024-08-04 13:19:44 +00:00
Chris Boesch
1ba74488e4
Changed needed zig version. 2024-08-04 15:05:11 +02:00
Chris Boesch
d6887f21c8 Merge pull request 'Fix #127 and #129 by updating the build files to account for recent 0.14.0-dev updates' (#130) from bsubei/exercises:fix-0.14.0-build-changes into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/130
2024-08-04 12:31:21 +00:00
Chris Boesch
a671def2cf Merge branch 'main' into fix-0.14.0-build-changes 2024-08-04 12:20:39 +00:00
Chris Boesch
28320b169f Merge pull request 'Fixed error message through a TAB in the comment, see https://github.com/ziglang/zig/issues/20928' (#137) from work into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/137
2024-08-04 12:20:10 +00:00
Chris Boesch
b26e3b2ac4
Fixed error message through a TAB in the comment, see https://github.com/ziglang/zig/issues/20928 2024-08-04 14:19:05 +02:00
bsubei
4cc1158fbc fix tests build file broken by addRemoveDirTree now requiring LazyPath 2024-07-21 13:01:59 -04:00
bsubei
e7dcf0b6ef fix build files broken by latest 0.14.0-dev changes to Build.Step.MakeOptions 2024-07-21 12:23:30 -04:00
Chris Boesch
e8f09190d6 Merge pull request 'document -Drandom' (#124) from hippietrail/exercises:random-exercise into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/124
2024-07-06 20:21:39 +00:00
Chris Boesch
1fd6aa1c65 Merge branch 'main' into random-exercise 2024-07-06 20:19:56 +00:00
Andrew Dunbar
4401cf8f49 document -Drandom 2024-07-06 14:18:56 +10:00
Chris Boesch
140c22e9f4 Merge pull request 'Update .woodpecker/eowyn.yaml' (#119) from chrboesch-wp-patch-3 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/119
2024-06-25 09:19:30 +00:00
chrboesch
c33898bc65 Update .woodpecker/eowyn.yaml
Add pull request
2024-06-25 09:11:04 +00:00
Chris Boesch
7705473447 Merge pull request 'Rename 'std.rand' to 'std.Random'' (#118) from fix_117 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/118
2024-06-25 08:53:25 +00:00
Chris Boesch
5bf56f03b0
Rename 'std.rand' to 'std.Random' 2024-06-25 10:45:54 +02:00
Chris Boesch
94fe012c77 Merge pull request 'attempt at implementing #113 "Add a way to do one random exercise"' (#117) from hippietrail/exercises:random-exercise into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/117
2024-06-25 08:30:14 +00:00
Andrew Dunbar
2259a18ece attempt at implementing #113 "Add a way to do one random exercise" 2024-06-25 17:22:57 +10:00
Chris Boesch
f496d79ab9 Merge pull request '046: Show usage of .? and hint towards new solution.' (#116) from alexmchughnz/ziglings:fix046 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/116
2024-06-24 19:13:25 +00:00
Alex McHugh
f656e950d5 Add patch. 2024-06-23 20:24:28 +12:00
Alex McHugh
3763f976eb 046: Show usage of .? and hint towards new solution. 2024-06-23 19:35:22 +12:00
Chris Boesch
da46008761 Merge pull request 'Fixes because of a new Zig version, which changes some functions.' (#114) from patch-106 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/114
2024-06-17 10:14:13 +00:00
Chris Boesch
5c000ce2d7
Fixes because of a new Zig version, which changes some functions. 2024-06-17 11:43:25 +02:00
Chris Boesch
c0c315b25a Merge pull request 'Calling split is deprecated' (#110) from cannero/zig-exercises:change_split into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/110
2024-06-17 08:00:44 +00:00
Sebastian
83f16709ba Calling split is deprecated
The `split` function in std mem is depreacted and a `@compileError`, splitSequence,
splitAny, or splitScalar should be used instead.
2024-06-16 18:58:48 +02:00
Chris Boesch
6d3d3651d0 Merge pull request 'English fixes for 107_files2.zig' (#108) from hippietrail/exercises:english-107 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/108
2024-06-14 09:06:53 +00:00
Andrew Dunbar
582a2558c7 English fixes for 106_files.zig 2024-06-12 17:52:33 +10:00
Andrew Dunbar
c9e5c7d561 English fixes for 107_files2.zig 2024-06-12 17:29:11 +10:00
Chris Boesch
65387dda45 Merge pull request 'fixed typo' (#107) from typo into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/107
2024-06-08 17:25:17 +00:00
Chris Boesch
1f5ec78df8
fixed typo 2024-06-08 19:20:30 +02:00
Chris Boesch
bb032fad40 Merge pull request 'New Zig version' (#106) from readme into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/106
2024-06-08 17:07:59 +00:00
Chris Boesch
984f4af3a1
New Zig version 2024-06-08 19:07:20 +02:00
Chris Boesch
99c9c42ff2 Merge pull request 'Verbs agree with the head of the noun phrase, not the closest noun' (#98) from hippietrail/exercises:grammar into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/98
2024-06-08 16:32:54 +00:00
Chris Boesch
7f78701d19 Merge branch 'main' into grammar 2024-06-08 16:31:06 +00:00
Chris Boesch
5c9b9bdc34 Merge pull request 'Ignore .zig-cache for new zig versions' (#102) from NicoElbers/exercises:main into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/102
2024-05-30 20:17:51 +00:00
Nico Elbers
0279826f5b
Ignore .zig-cache for new zig versions
zig cache directory was updated in ziglang/zig#20115
2024-05-30 18:23:28 +02:00
Chris Boesch
914141ec5a Merge pull request 'the Earth' (#97) from rofrol/ziglings--exercises:the-earth into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/97
2024-05-30 14:15:52 +00:00
Chris Boesch
c2caf1a32e Merge branch 'main' into the-earth 2024-05-30 14:15:27 +00:00
Chris Boesch
227bcb18db Merge pull request 'Fixed the changes from reworking std.Progress.' (#101) from v339 into main
Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/101
2024-05-29 19:29:56 +00:00
Chris Boesch
b224ed510e
Fixed the changes from reworking std.Progress.
For details: https://github.com/ziglang/zig/pull/20059
2024-05-29 21:20:28 +02:00
hippietrail
6223dc0f83 Verbs agree with the head of the noun phrase, not the closest noun
the result...are passed→the result...is passed
the number...vary→the number...varies
2024-05-25 11:25:09 +00:00
Roman Frołow
a6d13af0c2 the Earth 2024-05-20 21:32:32 +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
49 changed files with 1256 additions and 218 deletions

5
.gitea/issue_template.md Normal file
View File

@ -0,0 +1,5 @@
Ziglings is a progressive learning series — each exercise builds on previous ones.
Before opening an issue, please ensure you've followed the path and read the instructions carefully.
Respectful and constructive feedback is always welcome.

6
.gitignore vendored
View File

@ -1,5 +1,9 @@
/zig-cache/
/.zig-cache/
/zig-out/
/answers/
/patches/healed/
/output/
.progress.txt
# Leave this in here for older zig versions
/zig-cache/

View File

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

View File

@ -40,6 +40,7 @@ fit for one reason or another.
## Platforms and Zig Versions
Because it uses the Zig build system, Ziglings should work
wherever Zig does.
@ -75,6 +76,15 @@ interface. Specifically:
eternal Ziglings contributor glory is yours!
## Licence
If you submit your contribution to the repository/project,
you agree that your contribution will be licensed under
the license of this repository/this project.
Please note, it does not change your rights to use your own
contribution for any other purpose.
## The Secrets
If you want to peek at the secrets, take a look at the `patches/`

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 Dave Gauer
Copyright (c) 2021 Dave Gauer, Chris Boesch
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -10,11 +10,10 @@ Those broken programs need your help! (You'll also save the
planet from evil aliens and help some friendly elephants stick
together, which is very sweet of you.)
This project was directly inspired by the brilliant and fun
[rustlings](https://github.com/rust-lang/rustlings)
project for the [Rust](https://www.rust-lang.org/) language.
Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/)
and the Little LISPer/Little Schemer series of books.
This project was initiated by [Dave Gauer](https://ratfactor.com/) and is directly inspired
by the brilliant and fun [rustlings](https://github.com/rust-lang/rustlings) project.
Indirect inspiration comes from [Ruby Koans](http://rubykoans.com/) and the Little LISPer/Little
Schemer series of books.
## Intended Audience
@ -46,20 +45,20 @@ Verify the installation and build number of `zig` like so:
```
$ zig version
0.12.0-dev.xxxx+xxxxxxxxx
0.15.0-dev.xxxx+xxxxxxxxx
```
Clone this repository with Git:
```
$ git clone https://ziglings.org
$ cd ziglings.org
git clone https://codeberg.org/ziglings/exercises.git ziglings
cd ziglings
```
Then run `zig build` and follow the instructions to begin!
```
$ zig build
zig build
```
Note: The output of Ziglings is the unaltered output from the Zig
@ -69,13 +68,13 @@ reading these.
## A Note About Versions
**Hint:** To check out Ziglings for a stable release of Zig, you can use
the appropriate tag.
the appropriate tag.
The Zig language is under very active development. In order to be
current, Ziglings tracks **development** builds of the Zig
compiler rather than versioned **release** builds. The last
stable release was `0.11.0`, but Ziglings needs a dev build with
pre-release version "0.12.0" and a build number at least as high
stable release was `0.14.0`, but Ziglings needs a dev build with
pre-release version "0.15.0" and a build number at least as high
as that shown in the example version check above.
It is likely that you'll download a build which is _greater_ than
@ -88,7 +87,13 @@ that if you update one, you may need to also update the other.
### Version Changes
Version-0.12.0-dev.3518
Version-0.14.0-dev.1573
* *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257)
* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225)
* *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115)
* *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600)
* *2024-06-17* zig 0.14.0-dev.42 - changes in `std.mem.split and tokenize` - see [#15579](https://github.com/ziglang/zig/pull/15579)
* *2024-05-29* zig 0.13.0-dev.339 - rework std.Progress - see [#20059](https://github.com/ziglang/zig/pull/20059)
* *2024-03-21* zig 0.12.0-dev.3518 - change to @fieldParentPtr - see [#19470](https://github.com/ziglang/zig/pull/19470)
* *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)
@ -125,6 +130,18 @@ It can be handy to check just a single exercise:
zig build -Dn=19
```
Or run all exercises, starting from a specific one:
```
zig build -Ds=27
```
Or let Ziglings pick an exercise for you:
```
zig build -Drandom
```
You can also run without checking for correctness:
```
@ -156,6 +173,11 @@ zig build -Dn=19 -l
...
```
To reset the progress (have it run all the exercises that have already been completed):
```
zig build -Dreset
```
## What's Covered
The primary goal for Ziglings is to cover the core Zig language.
@ -211,7 +233,10 @@ Zig Core Language
* [X] Interfaces
* [X] Bit manipulation
* [X] Working with C
* [ ] Opaque types (anyopaque)
* [X] Threading
* [x] Labeled switch
* [x] Vector operations (SIMD)
Zig Standard Library

202
build.zig
View File

@ -15,7 +15,7 @@ const print = std.debug.print;
// 1) Getting Started
// 2) Version Changes
comptime {
const required_zig = "0.12.0-dev.3518";
const required_zig = "0.14.0-dev.1573";
const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
if (current_zig.order(min_zig) == .lt) {
@ -103,6 +103,8 @@ const Mode = enum {
normal,
/// Named build mode: `zig build -Dn=n`
named,
/// Random build mode: `zig build -Drandom`
random,
};
pub const logo =
@ -118,6 +120,8 @@ pub const logo =
\\
;
const progress_filename = ".progress.txt";
pub fn build(b: *Build) !void {
if (!validate_exercises()) std.process.exit(2);
@ -158,6 +162,9 @@ pub fn build(b: *Build) !void {
false;
const override_healed_path = b.option([]const u8, "healed-path", "Override healed path");
const exno: ?usize = b.option(usize, "n", "Select exercise");
const rand: ?bool = b.option(bool, "random", "Select random exercise");
const start: ?usize = b.option(usize, "s", "Start at exercise");
const reset: ?bool = b.option(bool, "reset", "Reset exercise progress");
const sep = std.fs.path.sep_str;
const healed_path = if (override_healed_path) |path|
@ -191,17 +198,108 @@ pub fn build(b: *Build) !void {
return;
}
if (rand) |_| {
// Random build mode: verifies one random exercise.
// like for 'exno' but chooses a random exercise number.
print("work in progress: check a random exercise\n", .{});
var prng = std.Random.DefaultPrng.init(blk: {
var seed: u64 = undefined;
try std.posix.getrandom(std.mem.asBytes(&seed));
break :blk seed;
});
const rnd = prng.random();
const ex = exercises[rnd.intRangeLessThan(usize, 0, exercises.len)];
print("random exercise: {s}\n", .{ex.main_file});
const zigling_step = b.step(
"random",
b.fmt("Check the solution of {s}", .{ex.main_file}),
);
b.default_step = zigling_step;
zigling_step.dependOn(&header_step.step);
const verify_step = ZiglingStep.create(b, ex, work_path, .random);
verify_step.step.dependOn(&header_step.step);
zigling_step.dependOn(&verify_step.step);
return;
}
if (start) |s| {
if (s == 0 or s > exercises.len - 1) {
print("unknown exercise number: {}\n", .{s});
std.process.exit(2);
}
const first = exercises[s - 1];
const ziglings_step = b.step("ziglings", b.fmt("Check ziglings starting with {s}", .{first.main_file}));
b.default_step = ziglings_step;
var prev_step = &header_step.step;
for (exercises[(s - 1)..]) |ex| {
const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal);
verify_stepn.step.dependOn(prev_step);
prev_step = &verify_stepn.step;
}
ziglings_step.dependOn(prev_step);
return;
}
if (reset) |_| {
std.fs.cwd().deleteFile(progress_filename) catch |err| {
switch (err) {
std.fs.Dir.DeleteFileError.FileNotFound => {},
else => {
print("Unable to remove progress file, Error: {}\n", .{err});
return err;
},
}
};
print("Progress reset, {s} removed.\n", .{progress_filename});
std.process.exit(0);
}
// Normal build mode: verifies all exercises according to the recommended
// order.
const ziglings_step = b.step("ziglings", "Check all ziglings");
b.default_step = ziglings_step;
var prev_step = &header_step.step;
for (exercises) |ex| {
const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal);
verify_stepn.step.dependOn(prev_step);
prev_step = &verify_stepn.step;
var starting_exercise: u32 = 0;
if (std.fs.cwd().openFile(progress_filename, .{})) |progress_file| {
defer progress_file.close();
const progress_file_size = try progress_file.getEndPos();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const contents = try progress_file.readToEndAlloc(allocator, progress_file_size);
defer allocator.free(contents);
starting_exercise = try std.fmt.parseInt(u32, contents, 10);
} else |err| {
switch (err) {
std.fs.File.OpenError.FileNotFound => {
// This is fine, may be the first time tests are run or progress have been reset
},
else => {
print("Unable to open {s}: {}\n", .{ progress_filename, err });
return err;
},
}
}
for (exercises) |ex| {
if (starting_exercise < ex.number()) {
const verify_stepn = ZiglingStep.create(b, ex, work_path, .normal);
verify_stepn.step.dependOn(prev_step);
prev_step = &verify_stepn.step;
}
}
ziglings_step.dependOn(prev_step);
@ -244,7 +342,7 @@ const ZiglingStep = struct {
return self;
}
fn make(step: *Step, prog_node: *std.Progress.Node) !void {
fn make(step: *Step, options: Step.MakeOptions) !void {
// NOTE: Using exit code 2 will prevent the Zig compiler to print the message:
// "error: the following build command failed with exit code 1:..."
const self: *ZiglingStep = @alignCast(@fieldParentPtr("step", step));
@ -255,7 +353,7 @@ const ZiglingStep = struct {
return;
}
const exe_path = self.compile(prog_node) catch {
const exe_path = self.compile(options.progress_node) catch {
self.printErrors();
if (self.exercise.hint) |hint|
@ -265,7 +363,7 @@ const ZiglingStep = struct {
std.process.exit(2);
};
self.run(exe_path.?, prog_node) catch {
self.run(exe_path, options.progress_node) catch {
self.printErrors();
if (self.exercise.hint) |hint|
@ -279,7 +377,7 @@ const ZiglingStep = struct {
self.printErrors();
}
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();
print("Checking: {s}\n", .{self.exercise.main_file});
@ -352,6 +450,18 @@ const ZiglingStep = struct {
, .{ red, reset, exercise_output, red, reset, output, red, reset });
}
const progress = try std.fmt.allocPrint(b.allocator, "{d}", .{self.exercise.number()});
defer b.allocator.free(progress);
const file = try std.fs.cwd().createFile(
progress_filename,
.{ .read = true, .truncate = true },
);
defer file.close();
try file.writeAll(progress);
try file.sync();
print("{s}PASSED:\n{s}{s}\n\n", .{ green_text, output, reset_text });
}
@ -375,7 +485,7 @@ const ZiglingStep = struct {
print("{s}PASSED{s}\n\n", .{ green_text, reset_text });
}
fn compile(self: *ZiglingStep, prog_node: *std.Progress.Node) !?[]const u8 {
fn compile(self: *ZiglingStep, prog_node: std.Progress.Node) ![]const u8 {
print("Compiling: {s}\n", .{self.exercise.main_file});
const b = self.step.owner;
@ -406,7 +516,21 @@ const ZiglingStep = struct {
zig_args.append("--listen=-") catch @panic("OOM");
return try self.step.evalZigProcess(zig_args.items, prog_node);
//
// NOTE: After many changes in zig build system, we need to create the cache path manually.
// See https://github.com/ziglang/zig/pull/21115
// Maybe there is a better way (in the future).
const exe_dir = try self.step.evalZigProcess(zig_args.items, prog_node, false);
const exe_name = switch (self.exercise.kind) {
.exe => self.exercise.name(),
.@"test" => "test",
};
const sep = std.fs.path.sep_str;
const root_path = exe_dir.?.root_dir.path.?;
const sub_path = exe_dir.?.subPathOrDot();
const exe_path = b.fmt("{s}{s}{s}{s}{s}", .{ root_path, sep, sub_path, sep, exe_name });
return exe_path;
}
fn help(self: *ZiglingStep) void {
@ -417,6 +541,7 @@ const ZiglingStep = struct {
const cmd = switch (self.mode) {
.normal => "zig build",
.named => b.fmt("zig build -Dn={s}", .{key}),
.random => "zig build -Drandom",
};
print("\n{s}Edit exercises/{s} and run '{s}' again.{s}\n", .{
@ -459,7 +584,7 @@ fn resetLine() void {
pub fn trimLines(allocator: std.mem.Allocator, buf: []const u8) ![]const u8 {
var list = try std.ArrayList(u8).initCapacity(allocator, buf.len);
var iter = std.mem.split(u8, buf, " \n");
var iter = std.mem.splitSequence(u8, buf, " \n");
while (iter.next()) |line| {
// TODO: trimming CR characters is probably not necessary.
const data = std.mem.trimRight(u8, line, " \r");
@ -494,7 +619,7 @@ const PrintStep = struct {
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
fn make(step: *Step, _: Step.MakeOptions) !void {
const self: *PrintStep = @alignCast(@fieldParentPtr("step", step));
print("{s}", .{self.message});
}
@ -521,7 +646,7 @@ fn validate_exercises() bool {
return false;
}
var iter = std.mem.split(u8, ex.output, "\n");
var iter = std.mem.splitScalar(u8, ex.output, '\n');
while (iter.next()) |line| {
const output = std.mem.trimRight(u8, line, " \r");
if (output.len != line.len) {
@ -838,7 +963,7 @@ const exercises = [_]Exercise{
},
.{
.main_file = "060_floats.zig",
.output = "Shuttle liftoff weight: 2032092kg",
.output = "Shuttle liftoff weight: 2032 metric tons",
},
.{
.main_file = "061_coercions.zig",
@ -904,6 +1029,7 @@ const exercises = [_]Exercise{
.{
.main_file = "074_comptime9.zig",
.output = "My llama value is 2.",
.skip = true,
},
.{
.main_file = "075_quiz8.zig",
@ -1020,7 +1146,7 @@ const exercises = [_]Exercise{
},
.{
.main_file = "097_bit_manipulation.zig",
.output = "x = 0; y = 1",
.output = "x = 1011; y = 1101",
},
.{
.main_file = "098_bit_manipulation2.zig",
@ -1128,9 +1254,51 @@ const exercises = [_]Exercise{
.main_file = "107_files2.zig",
.output =
\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
\\Successfully Read 18 byte: It's zigling time!
\\Successfully Read 18 bytes: It's zigling time!
,
},
.{
.main_file = "108_labeled_switch.zig",
.output = "The pull request has been merged.",
},
.{
.main_file = "109_vectors.zig",
.output =
\\Max difference (old fn): 0.014
\\Max difference (new fn): 0.014
,
},
.{ .main_file = "110_quiz9.zig", .output =
\\Toggle pins with XOR on PORTB
\\-----------------------------
\\ 1100 // (initial state of PORTB)
\\^ 0101 // (bitmask)
\\= 1001
\\
\\ 1100 // (initial state of PORTB)
\\^ 0011 // (bitmask)
\\= 1111
\\
\\Set pins with OR on PORTB
\\-------------------------
\\ 1001 // (initial state of PORTB)
\\| 0100 // (bitmask)
\\= 1101
\\
\\ 1001 // (reset state)
\\| 0100 // (bitmask)
\\= 1101
\\
\\Clear pins with AND and NOT on PORTB
\\------------------------------------
\\ 1110 // (initial state of PORTB)
\\& 1011 // (bitmask)
\\= 1010
\\
\\ 0111 // (reset state)
\\& 1110 // (bitmask)
\\= 0110
},
.{
.main_file = "999_the_end.zig",
.output =

View File

@ -17,7 +17,7 @@
//
// if (foo) |value| {
// ...
// } else |err| switch(err) {
// } else |err| switch (err) {
// ...
// }
//

View File

@ -5,7 +5,7 @@
// linked to the first elephant. This is because we had NO CONCEPT
// of a tail that didn't point to another elephant!
//
// We also introduce the handy ".?" shortcut:
// We also introduce the handy `.?` shortcut:
//
// const foo = bar.?;
//
@ -13,7 +13,8 @@
//
// const foo = bar orelse unreachable;
//
// See if you can find where we use this shortcut below.
// Check out where we use this shortcut below to change control flow
// based on if an optional value exists.
//
// Now let's make those elephant tails optional!
//
@ -31,14 +32,25 @@ pub fn main() void {
var elephantC = Elephant{ .letter = 'C' };
// Link the elephants so that each tail "points" to the next.
elephantA.tail = &elephantB;
elephantB.tail = &elephantC;
linkElephants(&elephantA, &elephantB);
linkElephants(&elephantB, &elephantC);
// `linkElephants` will stop the program if you try and link an
// elephant that doesn't exist! Uncomment and see what happens.
// const missingElephant: ?*Elephant = null;
// linkElephants(&elephantC, missingElephant);
visitElephants(&elephantA);
std.debug.print("\n", .{});
}
// If e1 and e2 are valid pointers to elephants,
// this function links the elephants so that e1's tail "points" to e2.
fn linkElephants(e1: ?*Elephant, e2: ?*Elephant) void {
e1.?.tail = e2.?;
}
// This function visits all elephants once, starting with the
// first elephant and following the tails to the next elephant.
fn visitElephants(first_elephant: *Elephant) void {
@ -51,8 +63,9 @@ fn visitElephants(first_elephant: *Elephant) void {
// We should stop once we encounter a tail that
// does NOT point to another element. What can
// we put here to make that happen?
if (e.tail == null) ???;
e = e.tail.?;
// HINT: We want something similar to what `.?` does,
// but instead of ending the program, we want to exit the loop...
e = e.tail ???
}
}

View File

@ -40,7 +40,7 @@
// Okay, you're armed.
//
// Now, please zap the alien structs until they're all gone or
// Earth will be doomed!
// the Earth will be doomed!
//
const std = @import("std");

View File

@ -43,7 +43,7 @@
//
// "void" is a _type_, not a value. It is the most popular of the
// Zero Bit Types (those types which take up absolutely no space
// and have only a semantic value. When compiled to executable
// and have only a semantic value). When compiled to executable
// code, zero bit types generate no code at all. The above example
// shows a variable foo of type void which is assigned the value
// of an empty expression. It's much more common to see void as

View File

@ -190,7 +190,7 @@ const TripItem = union(enum) {
fn printMe(self: TripItem) void {
switch (self) {
// Oops! The hermit forgot how to capture the union values
// in a switch statement. Please capture both values as
// in a switch statement. Please capture each value as
// 'p' so the print statements work!
.place => print("{s}", .{p.name}),
.path => print("--{}->", .{p.dist}),

View File

@ -41,14 +41,14 @@ pub fn main() void {
// The approximate weight of the Space Shuttle upon liftoff
// (including boosters and fuel tank) was 4,480,000 lb.
//
// We'll convert this weight from pound to kilograms at a
// conversion of 0.453592kg to the pound.
const shuttle_weight: f16 = 0.453592 * 4480e6;
// We'll convert this weight from pounds to metric units at a
// conversion of 0.453592 kg to the pound.
const shuttle_weight: f16 = 0.453592 * 4480e3;
// By default, float values are formatted in scientific
// notation. Try experimenting with '{d}' and '{d:.3}' to see
// how decimal formatting works.
print("Shuttle liftoff weight: {d:.0}kg\n", .{shuttle_weight});
print("Shuttle liftoff weight: {d:.0} metric tons\n", .{shuttle_weight});
}
// Floating further:

View File

@ -94,7 +94,7 @@ pub fn main() void {
print("He has room in his heart for:", .{});
// A StructFields array
const fields = @typeInfo(Narcissus).Struct.fields;
const fields = @typeInfo(Narcissus).@"struct".fields;
// 'fields' is a slice of StructFields. Here's the declaration:
//
@ -110,15 +110,15 @@ pub fn main() void {
// name will not be printed if the field is of type 'void'
// (which is a zero-bit type that takes up no space at all!):
if (fields[0].??? != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name});
print(" {s}", .{fields[0].name});
}
if (fields[1].??? != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name});
print(" {s}", .{fields[1].name});
}
if (fields[2].??? != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name});
print(" {s}", .{fields[2].name});
}
// Yuck, look at all that repeated code above! I don't know
@ -136,14 +136,16 @@ pub fn main() void {
// But a change after Zig 0.10.0 added the source file name to the
// type. "Narcissus" became "065_builtins2.Narcissus".
//
// To fix this, I've added this function to strip the filename from
// the front of the type name in the dumbest way possible. (It returns
// a slice of the type name starting at character 14 (assuming
// single-byte characters).
// To fix this, we've added this function to strip the filename from
// the front of the type name. (It returns a slice of the type name
// starting at the index + 1 of character ".")
//
// We'll be seeing @typeName again in Exercise 070. For now, you can
// see that it takes a Type and returns a u8 "string".
fn maximumNarcissism(myType: anytype) []const u8 {
// Turn '065_builtins2.Narcissus' into 'Narcissus'
return @typeName(myType)[14..];
const indexOf = @import("std").mem.indexOf;
// Turn "065_builtins2.Narcissus" into "Narcissus"
const name = @typeName(myType);
return name[indexOf(u8, name, ".").? + 1 ..];
}

View File

@ -7,7 +7,7 @@
// doing this work.
//
// An 'inline for' is performed at compile time, allowing you to
// programatically loop through a series of items in situations
// programmatically loop through a series of items in situations
// like those mentioned above where a regular runtime 'for' loop
// wouldn't be allowed:
//
@ -38,7 +38,7 @@ pub fn main() void {
// Please use an 'inline for' to implement the block below
// for each field in the slice 'fields'!
const fields = @typeInfo(Narcissus).Struct.fields;
const fields = @typeInfo(Narcissus).@"struct".fields;
??? {
if (field.type != void) {

View File

@ -78,7 +78,7 @@ fn printSequence(my_seq: anytype) void {
// a switch to handle printing the Array or Pointer fields,
// depending on which type of my_seq was passed in:
switch (my_typeinfo) {
.Array => {
.array => {
print("Array:", .{});
// Loop through the items in my_seq.
@ -86,7 +86,7 @@ fn printSequence(my_seq: anytype) void {
print("{}", .{s});
}
},
.Pointer => {
.pointer => {
// Check this out - it's pretty cool:
const my_sentinel = sentinel(@TypeOf(my_seq));
print("Many-item pointer:", .{});

View File

@ -75,11 +75,11 @@ fn printTuple(tuple: anytype) void {
// with fields specific to that type.
//
// The list of a struct type's fields can be found in
// TypeInfo's Struct.fields.
// TypeInfo's @"struct".fields.
//
// Example:
//
// @typeInfo(Circle).Struct.fields
// @typeInfo(Circle).@"struct".fields
//
// This will be an array of StructFields.
const fields = ???;
@ -95,13 +95,15 @@ fn printTuple(tuple: anytype) void {
// Each 'field' in this loop is one of these:
//
// pub const StructField = struct {
// name: []const u8,
// name: [:0]const u8,
// type: type,
// default_value: anytype,
// default_value_ptr: ?*const anyopaque,
// is_comptime: bool,
// alignment: comptime_int,
// };
//
// Note we will learn about 'anyopaque' type later
//
// You'll need this builtin:
//
// @field(lhs: anytype, comptime field_name: []const u8)

View File

@ -13,7 +13,7 @@
// How could we do that? A good method is to use the modulo function.
// But if we write "765.2 % 360", it only works with float values
// that are known at compile time.
// In Zig, we would use %mod(a, b) instead.
// In Zig, we would use @mod(a, b) instead.
//
// 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",

View File

@ -28,7 +28,7 @@
// 0..10 is a range from 0 to 9
// 1..4 is a range from 1 to 3
//
// At the moment, ranges are only supported in 'for' loops.
// At the moment, ranges in loops are only supported in 'for' loops.
//
// Perhaps you recall Exercise 13? We were printing a numeric
// sequence like so:

View File

@ -30,9 +30,9 @@
// std.debug.print("slice_ptr={*}\n", .{slice_ptr});
// }
// Instead of a simple integer or a constant sized slice, this
// program requires a slice to be allocated that is the same size as
// an input array.
// Instead of a simple integer or a slice with a constant size,
// this program requires allocating a slice that is the same size
// as an input array.
// Given a series of numbers, take the running average. In other
// words, each item N should contain the average of the last N

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
// developed that solve tasks solely by moving, setting, or logically
// combining bits.
@ -8,10 +8,10 @@
// functions where possible. And it is often possible with calculations
// 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.
// But it must never be forgotten that the numbers only represent the
// interpretation of the bit sequences.
// However, it should never be forgotten that the numbers only represent
// the interpretation of the bit sequences.
//
// Quasi the reversed case we have otherwise, namely that we represent
// numbers in bit sequences.
@ -21,7 +21,7 @@
// Zig provides all the necessary functions to change the bits inside
// a variable. It is distinguished whether the bit change leads to an
// 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:
//
@ -71,9 +71,9 @@ const print = std.debug.print;
pub fn main() !void {
// As in the example above, we use 1 and 0 as values for x and y
var x: u8 = 1;
var y: u8 = 0;
// Let us use 1101 and 1011 as values for x and y
var x: u8 = 0b1101;
var y: u8 = 0b1011;
// Now we swap the values of the two variables by doing xor on them
x ^= y;
@ -82,7 +82,7 @@ pub fn main() !void {
// What must be written here?
???;
print("x = {d}; y = {d}\n", .{ x, y });
print("x = {b}; y = {b}\n", .{ x, y });
}
// This variable swap takes advantage of the fact that the value resulting

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
// the states of the entries, e.g. a list of numbers and for each prime
// 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 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
// fast. Instead we take a simpler way, very similar in principle, we define
// a variable with at least 26 bits (e.g. u32) and also set the bit for each
// letter found at the corresponding position.
// fast. Instead we choose a simpler approach that is very similar in principle:
// We define a variable with at least 26 bits (e.g. u32) and set the bit for
// each letter that is found in the corresponding position.
//
// 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.
@ -39,7 +39,7 @@ fn isPangram(str: []const u8) bool {
// first we check if the string has at least 26 characters
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;
// loop about all characters in the string

View File

@ -16,13 +16,13 @@
// Therefore, the comments for the format() function are the only
// way to definitively learn how to format strings in Zig:
//
// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L29
// https://github.com/ziglang/zig/blob/master/lib/std/fmt.zig#L33
//
// Zig already has a very nice selection of formatting options.
// These can be used in different ways, but typically to convert
// numerical values into various text representations. The
// results can be used for direct output to a terminal or stored
// for later use or written to a file. The latter is useful when
// These can be used in different ways, but generally to convert
// numerical values into various text representations. The results
// can be used for direct output to a terminal or stored for
// later use or written to a file. The latter is useful when
// large amounts of data are to be processed by other programs.
//
// In Ziglings, we are concerned with the output to the console.
@ -45,7 +45,7 @@
// output. Escape sequences can also be written one after the
// other, e.g. "\n\n" will cause two line feeds.
//
// By the way, the result of these escape sequences are passed
// By the way, the result of these escape sequences is passed
// directly to the terminal program. Other than translating them
// into control codes, escape sequences have nothing to do with
// Zig. Zig knows nothing about "line feeds" or "tabs" or
@ -95,7 +95,7 @@
// ...
//
// Without string formatting, this would be a more challenging
// assignment because the number of digits in the numbers vary
// assignment because the number of digits in the numbers varies
// from 1 to 3. But formatting can help us with that.
//
const std = @import("std");

View File

@ -41,12 +41,12 @@ pub fn main() void {
for (hex_nums, ???) |hn, ???| {
if (hn != dn) {
std.debug.print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn });
print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn });
return;
}
}
std.debug.print("Arrays match!\n", .{});
print("Arrays match!\n", .{});
}
//
// You are perhaps wondering what happens if one of the two lists

View File

@ -119,9 +119,9 @@
// after all we need some practice. Suppose we want to count the words
// of this little poem:
//
// My name is Ozymandias, King of Kings;
// Look on my Works, ye Mighty, and despair!
// by Percy Bysshe Shelley
// My name is Ozymandias, King of Kings;
// Look on my Works, ye Mighty, and despair!
// by Percy Bysshe Shelley
//
//
const std = @import("std");

View File

@ -4,8 +4,8 @@
// one possibility, namely asynchronous processes, in Exercises 84-91.
//
// However, the computing power of the processor is only distributed to
// the started tasks, which always reaches its limits when pure computing
// power is called up.
// 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

View File

@ -1,6 +1,6 @@
//
// Now that we are familiar with the principles of multi threading, we
// boldly venture into a practical example from mathematics.
// 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
@ -21,9 +21,9 @@
// There were the Scottish mathematician Gregory and the German
// mathematician Leibniz, and even a few hundred years earlier the Indian
// mathematician Madhava. All of them independently developed the same
// formula, which was published by Leibnitz in 1682 in the journal
// formula, which was published by Leibniz in 1682 in the journal
// "Acta Eruditorum".
// This is why this method has become known as the "Leibnitz series",
// This is why this method has become known as the "Leibniz series",
// although the other names are also often used today.
// We will not go into the formula and its derivation in detail, but
// will deal with the series straight away:
@ -39,7 +39,7 @@
// in practice. Because either you don't need the precision, or you use a
// calculator in which the number is stored as a very precise constant.
// But at some point this constant was calculated and we are doing the same
// now.The question at this point is, how many partial values do we have
// now. The question at this point is, how many partial values do we have
// to calculate for which accuracy?
//
// The answer is chewing, to get 8 digits after the decimal point we need
@ -50,7 +50,7 @@
// enough for us for now, because we want to understand the principle and
// nothing more, right?
//
// As we have already discovered, the Leibnitz series is a series with a
// As we have already discovered, the Leibniz series is a series with a
// fixed distance of 2 between the individual partial values. This makes
// it easy to apply a simple loop to it, because if we start with n = 1
// (which is not necessarily useful now) we always have to add 2 in each
@ -104,4 +104,4 @@ fn thread_pi(pi: *f64, begin: u64, end: u64) !void {
// 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 diggits.
// otherwise you will not be able to see the additional digits.

View File

@ -1,22 +1,22 @@
//
// Until now, we've only been printing our output in the console,
// which is good enough for fighting alien and hermit bookkeeping.
// which is good enough for fighting aliens and hermit bookkeeping.
//
// However, many other task require some interaction with the file system,
// However, many other tasks 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.
// The file system provides a hierarchical structure for storing files
// by organizing them into directories, which hold files and other directories,
// thus creating a tree structure that can be navigated.
//
// Fortunately, zig standard library provide a simple api for interacting
// with the file system, see the detail documentation here
// Fortunately, the Zig Standard Library provides a simple API for interacting
// with the file system, see the detail documentation here:
//
// https://ziglang.org/documentation/master/std/#std.fs
//
// In this exercise, we'll try to
// - create a new directory
// - open a file in the directory
// In this exercise, we'll try to:
// - create a new directory,
// - open a file in the directory,
// - write to the file.
//
// import std as always
@ -27,43 +27,43 @@ pub fn main() !void {
const cwd: std.fs.Dir = std.fs.cwd();
// then we'll try to make a new directory /output/
// to put our output files.
// to store our output files.
cwd.makeDir("output") catch |e| switch (e) {
// there are chance you might want to run this
// there is a 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
// have 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
// if there's any other unexpected error we just propagate it through
else => return e,
};
// then we'll try to open our freshly created directory
// wait a minute
// wait a minute...
// 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
// and propagate any error up
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
// so that other program can read it and prevent data corruption
// 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 are a keyword in zig that
// allow you "defer" code execute to the end of scope...
// if only there were a keyword in Zig that
// allowed you to "defer" code execution to the end of the scope...
file.close();
// !you are not allow to switch this two lines to before file closing line!
// you are not allowed to move these two lines above the file closing line!
const byte_written = try file.write("It's zigling time!");
std.debug.print("Successfully wrote {d} bytes.\n", .{byte_written});
}
// to check if you actually write to the file, you can either,
// 1. open the file on your text editor, or
// 2. print the content of the file in the console with command
// 1. open the file in your text editor, or
// 2. print the content of the file in the console with the following command
// >> cat ./output/zigling.txt
//
//
@ -86,7 +86,7 @@ pub fn main() !void {
//
// 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
// - go to the 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 option can you uses with those function?
// - what kind of options can you use with those functions?

View File

@ -4,17 +4,17 @@
// - 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 wrote a program to read the content of the file that we just created.
// Now there's no point in writing to a file if we don't read from it, am I right?
// Let's write a program to read the content of the file that we just created.
//
// I am assuming you've created the appropriate files for this to work.
// I am assuming that you've created the appropriate files for this to work.
//
// Alright, bud, lean in close here's the game plan.
// Alright, bud, lean in close. Here's the game plan.
// - First, we open the {project_root}/output/ directory
// - Secondly, we open file `zigling.txt` in that directory
// - then, we initalize an array of character 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
// - Then, we initialize an array of characters with all letter 'A', and print it
// - After that, we read the content of the file into the array
// - Finally, we print out the content we just read
const std = @import("std");
@ -30,23 +30,23 @@ pub fn main() !void {
const file = try output_dir.openFile("zigling.txt", .{});
defer file.close();
// initalize an array of u8 with all letter 'A'.
// we need to pick a size of the array, 64 seems like a good number.
// fix the initalization below
// initialize an array of u8 with all letter 'A'
// we need to pick the size of the array, 64 seems like a good number
// fix the initialization below
var content = ['A']*64;
// this should print out : `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA`
std.debug.print("{s}\n", .{content});
// okay, seem like threat of violence is not the answer in this case
// can you go here to find a way to read the 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 answer that are both vaild in this case
const byte_read = zig_read_the_file_or_i_will_fight_you(&content);
// hint: you might find two answers that are both valid in this case
const bytes_read = zig_read_the_file_or_i_will_fight_you(&content);
// Woah, too screamy, I know you're excited for zigling time but tone it down a bit
// Can you print only what we read from the file ?
std.debug.print("Successfully Read {d} byte: {s}\n", .{
byte_read,
// 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

@ -0,0 +1,79 @@
//
// You've heard of while loops in exercises 011,012,013 and 014
// You've also heard of switch expressions in exercises 030 and 31.
// You've also seen how labels can be used in exercise 063.
//
// By combining while loops and switch statements with continue and break statements
// one can create very concise State Machines.
//
// One such example would be:
//
// pub fn main() void {
// var op: u8 = 1;
// while (true) {
// switch (op) {
// 1 => { op = 2; continue; },
// 2 => { op = 3; continue; },
// 3 => return,
// else => {},
// }
// break;
// }
// std.debug.print("This statement cannot be reached\n", .{});
// }
//
// By combining all we've learned so far, we can now proceed with a labeled switch.
//
// A labeled switch is some extra syntactic sugar, which comes with all sorts of
// candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367
//
// Here is the previous excerpt implemented as a labeled switch instead:
//
// pub fn main() void {
// foo: switch (@as(u8, 1)) {
// 1 => continue :foo 2,
// 2 => continue :foo 3,
// 3 => return,
// else => {},
// }
// std.debug.print("This statement cannot be reached\n", .{});
// }
//
// The flow of execution on this second case is:
// 1. The switch starts with value '1';
// 2. The switch evaluates to case '1' which in turn uses the continue statement
// to re-evaluate the labeled switch again, now providing the value '2';
// 3. In the case '2' we repeat the same pattern as case '1'
// but instead the value to be evaluated is now '3';
// 4. Finally we get to case '3', where we return from the function as a whole,
// so the debug statement is never executed.
// 5. In this example, since the input does not have clear, exhaustive patterns and
// can essentially be any 'u8' integer, we need to handle all cases not explicitly
// covered by using the 'else => {}' branch as the default case.
//
//
const std = @import("std");
const PullRequestState = enum(u8) {
Draft,
InReview,
Approved,
Rejected,
Merged,
};
pub fn main() void {
// Oh no, your pull request keeps being rejected,
// how would you fix it?
pr: switch (PullRequestState.Draft) {
PullRequestState.Draft => continue :pr PullRequestState.InReview,
PullRequestState.InReview => continue :pr PullRequestState.Rejected,
PullRequestState.Approved => continue :pr PullRequestState.Merged,
PullRequestState.Rejected => {
std.debug.print("The pull request has been rejected.\n", .{});
return;
},
PullRequestState.Merged => break, // Would you know where to break to?
}
std.debug.print("The pull request has been merged.\n", .{});
}

147
exercises/109_vectors.zig Normal file
View File

@ -0,0 +1,147 @@
// So far in Ziglings, we've seen how for loops can be used to
// repeat calculations across an array in several ways.
//
// For loops are generally great for this kind of task, but
// sometimes they don't fully utilize the capabilities of the
// CPU.
//
// Most modern CPUs can execute instructions in which SEVERAL
// calculations are performed WITHIN registers at the SAME TIME.
// These are known as "single instruction, multiple data" (SIMD)
// instructions. SIMD instructions can make code significantly
// more performant.
//
// To see why, imagine we have a program in which we take the
// square root of four (changing) f32 floats.
//
// A simple compiler would take the program and produce machine code
// which calculates each square root sequentially. Most registers on
// modern CPUs have 64 bits, so we could imagine that each float moves
// into a 64-bit register, and the following happens four times:
//
// 32 bits 32 bits
// +-------------------+
// register | 0 | x |
// +-------------------+
//
// |
// [SQRT instruction]
// V
//
// +-------------------+
// | 0 | sqrt(x) |
// +-------------------+
//
// Notice that half of the register contains blank data to which
// nothing happened. What a waste! What if we were able to use
// that space instead? This is the idea at the core of SIMD.
//
// Most modern CPUs contain specialized registers with at least 128 bits
// for performing SIMD instructions. On a machine with 128-bit SIMD
// registers, a smart compiler would probably NOT issue four sqrt
// instructions as above, but instead pack the floats into a single
// 128-bit register, then execute a single "packed" sqrt
// instruction to do ALL the square root calculations at once.
//
// For example:
//
//
// 32 bits 32 bits 32 bits 32 bits
// +---------------------------------------+
// register | 4.0 | 9.0 | 25.0 | 49.0 |
// +---------------------------------------+
//
// |
// [SIMD SQRT instruction]
// V
//
// +---------------------------------------+
// register | 2.0 | 3.0 | 5.0 | 7.0 |
// +---------------------------------------+
//
// Pretty cool, right?
//
// Code with SIMD instructions is usually more performant than code
// without SIMD instructions. Zig cares a lot about performance,
// so it has built-in support for SIMD! It has a data structure that
// directly supports SIMD instructions:
//
// +-----------+
// | Vectors |
// +-----------+
//
// Operations performed on vectors in Zig will be done in parallel using
// SIMD instructions, whenever possible.
//
// Defining vectors in Zig is straightforwards. No library import is needed.
const v1 = @Vector(3, i32){ 1, 10, 100 };
const v2 = @Vector(3, f32){ 2.0, 3.0, 5.0 };
// Vectors support the same builtin operators as their underlying base types.
const v3 = v1 + v1; // { 2, 20, 200};
const v4 = v2 * v2; // { 4.0, 9.0, 25.0};
// Intrinsics that apply to base types usually extend to vectors.
const v5: @Vector(3, f32) = @floatFromInt(v3); // { 2.0, 20.0, 200.0}
const v6 = v4 - v5; // { 2.0, -11.0, -175.0}
const v7 = @abs(v6); // { 2.0, 11.0, 175.0}
// We can make constant vectors, and reduce vectors.
const v8: @Vector(4, u8) = @splat(2); // { 2, 2, 2, 2}
const v8_sum = @reduce(.Add, v8); // 8
const v8_min = @reduce(.Min, v8); // 2
// Fixed-length arrays can be automatically assigned to vectors (and vice-versa).
const single_digit_primes = [4]i8{ 2, 3, 5, 7 };
const prime_vector: @Vector(4, i8) = single_digit_primes;
// Now let's use vectors to simplify and optimize some code!
//
// Ewa is writing a program in which they frequently want to compare
// two lists of four f32s. Ewa expects the lists to be similar, and
// wants to determine the largest pairwise difference between the lists.
//
// Ewa wrote the following function to figure this out.
fn calcMaxPairwiseDiffOld(list1: [4]f32, list2: [4]f32) f32 {
var max_diff: f32 = 0;
for (list1, list2) |n1, n2| {
const abs_diff = @abs(n1 - n2);
if (abs_diff > max_diff) {
max_diff = abs_diff;
}
}
return max_diff;
}
// Ewa heard about vectors in Zig, and started writing a new vector
// version of the function, but has got stuck!
//
// Help Ewa finish the vector version! The examples above should help.
const Vec4 = @Vector(4, f32);
fn calcMaxPairwiseDiffNew(a: Vec4, b: Vec4) f32 {
const abs_diff_vec = ???;
const max_diff = @reduce(???, abs_diff_vec);
return max_diff;
}
// Quite the simplification! We could even write the function in one line
// and it would still be readable.
//
// Since the entire function is now expressed in terms of vector operations,
// the Zig compiler will easily be able to compile it down to machine code
// which utilizes the all-powerful SIMD instructions and does a lot of the
// computation in parallel.
const std = @import("std");
const print = std.debug.print;
pub fn main() void {
const l1 = [4]f32{ 3.141, 2.718, 0.577, 1.000 };
const l2 = [4]f32{ 3.154, 2.707, 0.591, 0.993 };
const mpd_old = calcMaxPairwiseDiffOld(l1, l2);
const mpd_new = calcMaxPairwiseDiffNew(l1, l2);
print("Max difference (old fn): {d: >5.3}\n", .{mpd_old});
print("Max difference (new fn): {d: >5.3}\n", .{mpd_new});
}

484
exercises/110_quiz9.zig Normal file
View File

@ -0,0 +1,484 @@
// ----------------------------------------------------------------------------
// Quiz Time: Toggling, Setting, and Clearing Bits
// ----------------------------------------------------------------------------
//
// Another exciting thing about Zig is its suitability for embedded
// programming. Your Zig code doesn't have to remain on your laptop; you can
// also deploy your code to microcontrollers! This means you can write Zig to
// drive your next robot or greenhouse climate control system! Ready to enter
// the exciting world of embedded programming? Let's get started!
//
// ----------------------------------------------------------------------------
// Some Background
// ----------------------------------------------------------------------------
//
// A common activity in microcontroller programming is setting and clearing
// bits on input and output pins. This lets you control LEDs, sensors, motors
// and more! In a previous exercise (097_bit_manipulation.zig) you learned how
// to swap two bytes using the ^ (XOR - exclusive or) operator. This quiz will
// test your knowledge of bit manipulation in Zig while giving you a taste of
// what it's like to control registers in a real microcontroller. Included at
// the end are some helper functions that demonstrate how we might make our
// code a little more readable.
//
// Below is a pinout diagram for the famous ATmega328 AVR microcontroller used
// as the primary microchip on popular microcontroller platforms like the
// Arduino UNO.
//
// ============ PINOUT DIAGRAM FOR ATMEGA328 MICROCONTROLLER ============
// _____ _____
// | U |
// (RESET) PC6 --| 1 28 |-- PC5
// PD0 --| 2 27 |-- PC4
// PD1 --| 3 26 |-- PC3
// PD2 --| 4 25 |-- PC2
// PD3 --| 5 24 |-- PC1
// PD4 --| 6 23 |-- PC0
// VCC --| 7 22 |-- GND
// GND --| 8 21 |-- AREF
// |-- PB6 --| 9 20 |-- AVCC
// |-- PB7 --| 10 19 |-- PB5 --|
// | PD5 --| 11 18 |-- PB4 --|
// | PD6 --| 12 17 |-- PB3 --|
// | PD7 --| 13 16 |-- PB2 --|
// |-- PB0 --| 14 15 |-- PB1 --|
// | |___________| |
// \_______________________________/
// |
// PORTB
//
// Drawing inspiration from this diagram, we'll use the pins for PORTB as our
// mental model for this quiz on bit manipulation. It should be noted that
// in the following problems we are using ordinary variables, one of which we
// have named PORTB, to simulate modifying the bits of real hardware registers.
// But in actual microcontroller code, PORTB would be defined something like
// this:
// pub const PORTB = @as(*volatile u8, @ptrFromInt(0x25));
//
// This lets the compiler know not to make any optimizations to PORTB so that
// the IO pins are properly mapped to our code.
//
// NOTE : To keep things simple, the following problems are given using type
// u4, so applying the output to PORTB would only affect the lower four pins
// PB0..PB3. Of course, there is nothing to prevent you from swapping the u4
// with a u8 so you can control all 8 of PORTB's IO pins.
const std = @import("std");
const print = std.debug.print;
const testing = std.testing;
pub fn main() !void {
var PORTB: u4 = 0b0000; // only 4 bits wide for simplicity
// ------------------------------------------------------------------------
// Quiz
// ------------------------------------------------------------------------
// See if you can solve the following problems. The last two problems throw
// you a bit of a curve ball. Try solving them on your own. If you need
// help, scroll to the bottom of main to see some in depth explanations on
// toggling, setting, and clearing bits in Zig.
print("Toggle pins with XOR on PORTB\n", .{});
print("-----------------------------\n", .{});
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0101});
PORTB ^= (1 << 1) | (1 << 0); // What's wrong here?
checkAnswer(0b1001, PORTB);
newline();
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0011});
PORTB ^= (1 << 1) & (1 << 0); // What's wrong here?
checkAnswer(0b1111, PORTB);
newline();
print("Set pins with OR on PORTB\n", .{});
print("-------------------------\n", .{});
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
PORTB = PORTB ??? (1 << 2); // What's missing here?
checkAnswer(0b1101, PORTB);
newline();
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
PORTB ??? (1 << 2); // What's missing here?
checkAnswer(0b1101, PORTB);
newline();
print("Clear pins with AND and NOT on PORTB\n", .{});
print("------------------------------------\n", .{});
PORTB = 0b1110; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1011});
PORTB = PORTB & ???@as(u4, 1 << 2); // What character is missing here?
checkAnswer(0b1010, PORTB);
newline();
PORTB = 0b0111; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1110});
PORTB &= ~(1 << 0); // What's missing here?
checkAnswer(0b0110, PORTB);
newline();
newline();
}
// ************************************************************************
// IN-DEPTH EXPLANATIONS BELOW
// ************************************************************************
//
//
//
//
//
//
//
//
//
//
//
// ------------------------------------------------------------------------
// Toggling bits with XOR:
// ------------------------------------------------------------------------
// XOR stands for "exclusive or". We can toggle bits with the ^ (XOR)
// bitwise operator, like so:
//
//
// In order to output a 1, the logic of an XOR operation requires that the
// two input bits are of different values. Therefore, 0 ^ 1 and 1 ^ 0 will
// both yield a 1 but 0 ^ 0 and 1 ^ 1 will output 0. XOR's unique behavior
// of outputting a 0 when both inputs are 1s is what makes it different from
// the OR operator; it also gives us the ability to toggle bits by putting
// 1s into our bitmask.
//
// - 1s in our bitmask operand, can be thought of as causing the
// corresponding bits in the other operand to flip to the opposite value.
// - 0s cause no change.
//
// The 0s in our bitmask preserve these values
// -XOR op- ---expanded--- in the output.
// _______________/
// / /
// 1100 1 1 0 0
// ^ 0101 0 1 0 1 (bitmask)
// ------ - - - -
// = 1001 1 0 0 1 <- This bit was already cleared.
// \_______\
// \
// We can think of these bits having flipped
// because of the presence of 1s in those columns
// of our bitmask.
//
// Now let's take a look at setting bits with the | operator.
//
//
//
//
//
// ------------------------------------------------------------------------
// Setting bits with OR:
// ------------------------------------------------------------------------
// We can set bits on PORTB with the | (OR) operator, like so:
//
// var PORTB: u4 = 0b1001;
// PORTB = PORTB | 0b0010;
// print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011
//
// -OR op- ---expanded---
// _ Set only this bit.
// /
// 1001 1 0 0 1
// | 0010 0 0 1 0 (bitmask)
// ------ - - - -
// = 1011 1 0 1 1
// \___\_______\
// \
// These bits remain untouched because OR-ing with
// a 0 effects no change.
//
// ------------------------------------------------------------------------
// To create a bitmask like 0b0010 used above:
//
// 1. First, shift the value 1 over one place with the bitwise << (shift
// left) operator as indicated below:
// 1 << 0 -> 0001
// 1 << 1 -> 0010 <-- Shift 1 one place to the left
// 1 << 2 -> 0100
// 1 << 3 -> 1000
//
// This allows us to rewrite the above code like this:
//
// var PORTB: u4 = 0b1001;
// PORTB = PORTB | (1 << 1);
// print("PORTB: {b:0>4}\n", .{PORTB}); // output: 1011
//
// Finally, as in the C language, Zig allows us to use the |= operator, so
// we can rewrite our code again in an even more compact and idiomatic
// form: PORTB |= (1 << 1)
// So now we've covered how to toggle and set bits. What about clearing
// them? Well, this is where Zig throws us a curve ball. Don't worry we'll
// go through it step by step.
//
//
//
//
//
// ------------------------------------------------------------------------
// Clearing bits with AND and NOT:
// ------------------------------------------------------------------------
// We can clear bits with the & (AND) bitwise operator, like so:
// PORTB = 0b1110; // reset PORTB
// PORTB = PORTB & 0b1011;
// print("PORTB: {b:0>4}\n", .{PORTB}); // output -> 1010
//
// - 0s clear bits when used in conjunction with a bitwise AND.
// - 1s do nothing, thus preserving the original bits.
//
// -AND op- ---expanded---
// __________ Clear only this bit.
// /
// 1110 1 1 1 0
// & 1011 1 0 1 1 (bitmask)
// ------ - - - -
// = 1010 1 0 1 0 <- This bit was already cleared.
// \_______\
// \
// These bits remain untouched because AND-ing with a
// 1 preserves the original bit value whether 0 or 1.
//
// ------------------------------------------------------------------------
// We can use the ~ (NOT) operator to easily create a bitmask like 1011:
//
// 1. First, shift the value 1 over two places with the bit-wise << (shift
// left) operator as indicated below:
// 1 << 0 -> 0001
// 1 << 1 -> 0010
// 1 << 2 -> 0100 <- The 1 has been shifted two places to the left
// 1 << 3 -> 1000
//
// 2. The second step in creating our bitmask is to invert the bits
// ~0100 -> 1011
// in C we would write this as:
// ~(1 << 2) -> 1011
//
// But if we try to compile ~(1 << 2) in Zig, we'll get an error:
// unable to perform binary not operation on type 'comptime_int'
//
// Before Zig can invert our bits, it needs to know the number of
// bits it's being asked to invert.
//
// We do this with the @as (cast as) built-in like this:
// @as(u4, 1 << 2) -> 0100
//
// Finally, we can invert our new mask by placing the NOT ~ operator
// before our expression, like this:
// ~@as(u4, 1 << 2) -> 1011
//
// If you are offput by the fact that you can't simply invert bits like
// you can in languages such as C without casting to a particular size
// of integer, you're not alone. However, this is actually another
// instance where Zig is really helpful because it protects you from
// difficult to debug integer overflow bugs that can have you tearing
// your hair out. In the interest of keeping things sane, Zig requires
// you simply to tell it the size of number you are inverting. In the
// words of Andrew Kelley, "If you want to invert the bits of an
// integer, zig has to know how many bits there are."
//
// For more insight into the Zig team's position on why the language
// takes the approach it does with the ~ operator, take a look at
// Andrew's comments on the following github issue:
// https://github.com/ziglang/zig/issues/1382#issuecomment-414459529
//
// Whew, so after all that what we end up with is:
// PORTB = PORTB & ~@as(u4, 1 << 2);
//
// We can shorten this with the &= combined AND and assignment operator,
// which applies the AND operator on PORTB and then reassigns PORTB. Here's
// what that looks like:
// PORTB &= ~@as(u4, 1 << 2);
//
// ------------------------------------------------------------------------
// Conclusion
// ------------------------------------------------------------------------
//
// While the examples in this quiz have used only 4-bit wide variables,
// working with 8 bits is no different. Here's an example where we set
// every other bit beginning with the two's place:
// var PORTD: u8 = 0b0000_0000;
// print("PORTD: {b:0>8}\n", .{PORTD});
// PORTD |= (1 << 1);
// PORTD = setBit(u8, PORTD, 3);
// PORTD |= (1 << 5) | (1 << 7);
// print("PORTD: {b:0>8} // set every other bit\n", .{PORTD});
// PORTD = ~PORTD;
// print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD});
// newline();
//
// // Here we clear every other bit beginning with the two's place.
//
// PORTD = 0b1111_1111;
// print("PORTD: {b:0>8}\n", .{PORTD});
// PORTD &= ~@as(u8, 1 << 1);
// PORTD = clearBit(u8, PORTD, 3);
// PORTD &= ~@as(u8, (1 << 5) | (1 << 7));
// print("PORTD: {b:0>8} // clear every other bit\n", .{PORTD});
// PORTD = ~PORTD;
// print("PORTD: {b:0>8} // bits flipped with NOT (~)\n", .{PORTD});
// newline();
// ----------------------------------------------------------------------------
// Here are some helper functions for manipulating bits
// ----------------------------------------------------------------------------
// Functions for setting, clearing, and toggling a single bit
fn setBit(comptime T: type, byte: T, comptime bit_pos: T) !T {
return byte | (1 << bit_pos);
}
test "setBit" {
try testing.expectEqual(setBit(u8, 0b0000_0000, 3), 0b0000_1000);
}
fn clearBit(comptime T: type, byte: T, comptime bit_pos: T) T {
return byte & ~@as(T, (1 << bit_pos));
}
test "clearBit" {
try testing.expectEqual(clearBit(u8, 0b1111_1111, 0), 0b1111_1110);
}
fn toggleBit(comptime T: type, byte: T, comptime bit_pos: T) T {
return byte ^ (1 << bit_pos);
}
test "toggleBit" {
var byte = toggleBit(u8, 0b0000_0000, 0);
try testing.expectEqual(byte, 0b0000_0001);
byte = toggleBit(u8, byte, 0);
try testing.expectEqual(byte, 0b0000_0000);
}
// ----------------------------------------------------------------------------
// Some additional functions for setting, clearing, and toggling multiple bits
// at once with a tuple because, hey, why not?
// ----------------------------------------------------------------------------
//
fn createBitmask(comptime T: type, comptime bits: anytype) !T {
comptime var bitmask: T = 0;
inline for (bits) |bit| {
if (bit >= @bitSizeOf(T)) return error.BitPosTooLarge;
if (bit < 0) return error.BitPosTooSmall;
bitmask |= (1 << bit);
}
return bitmask;
}
test "creating bitmasks from a tuple" {
try testing.expectEqual(createBitmask(u8, .{0}), 0b0000_0001);
try testing.expectEqual(createBitmask(u8, .{1}), 0b0000_0010);
try testing.expectEqual(createBitmask(u8, .{2}), 0b0000_0100);
try testing.expectEqual(createBitmask(u8, .{3}), 0b0000_1000);
//
try testing.expectEqual(createBitmask(u8, .{ 0, 4 }), 0b0001_0001);
try testing.expectEqual(createBitmask(u8, .{ 1, 5 }), 0b0010_0010);
try testing.expectEqual(createBitmask(u8, .{ 2, 6 }), 0b0100_0100);
try testing.expectEqual(createBitmask(u8, .{ 3, 7 }), 0b1000_1000);
try testing.expectError(error.BitPosTooLarge, createBitmask(u4, .{4}));
}
fn setBits(byte: u8, bits: anytype) !u8 {
const bitmask = try createBitmask(u8, bits);
return byte | bitmask;
}
test "setBits" {
try testing.expectEqual(setBits(0b0000_0000, .{0}), 0b0000_0001);
try testing.expectEqual(setBits(0b0000_0000, .{7}), 0b1000_0000);
try testing.expectEqual(setBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111);
try testing.expectEqual(setBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111);
try testing.expectEqual(setBits(0b0000_0000, .{ 2, 3, 4, 5 }), 0b0011_1100);
try testing.expectError(error.BitPosTooLarge, setBits(0b1111_1111, .{8}));
try testing.expectError(error.BitPosTooSmall, setBits(0b1111_1111, .{-1}));
}
fn clearBits(comptime byte: u8, comptime bits: anytype) !u8 {
const bitmask: u8 = try createBitmask(u8, bits);
return byte & ~@as(u8, bitmask);
}
test "clearBits" {
try testing.expectEqual(clearBits(0b1111_1111, .{0}), 0b1111_1110);
try testing.expectEqual(clearBits(0b1111_1111, .{7}), 0b0111_1111);
try testing.expectEqual(clearBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000);
try testing.expectEqual(clearBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000);
try testing.expectEqual(clearBits(0b1111_1111, .{ 0, 1, 6, 7 }), 0b0011_1100);
try testing.expectError(error.BitPosTooLarge, clearBits(0b1111_1111, .{8}));
try testing.expectError(error.BitPosTooSmall, clearBits(0b1111_1111, .{-1}));
}
fn toggleBits(comptime byte: u8, comptime bits: anytype) !u8 {
const bitmask = try createBitmask(u8, bits);
return byte ^ bitmask;
}
test "toggleBits" {
try testing.expectEqual(toggleBits(0b0000_0000, .{0}), 0b0000_0001);
try testing.expectEqual(toggleBits(0b0000_0000, .{7}), 0b1000_0000);
try testing.expectEqual(toggleBits(0b1111_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b000_0000);
try testing.expectEqual(toggleBits(0b0000_0000, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_1111);
try testing.expectEqual(toggleBits(0b0000_1111, .{ 0, 1, 2, 3, 4, 5, 6, 7 }), 0b1111_0000);
try testing.expectEqual(toggleBits(0b0000_1111, .{ 0, 1, 2, 3 }), 0b0000_0000);
try testing.expectEqual(toggleBits(0b0000_0000, .{ 0, 2, 4, 6 }), 0b0101_0101);
try testing.expectError(error.BitPosTooLarge, toggleBits(0b1111_1111, .{8}));
try testing.expectError(error.BitPosTooSmall, toggleBits(0b1111_1111, .{-1}));
}
// ----------------------------------------------------------------------------
// Utility functions
// ----------------------------------------------------------------------------
fn newline() void {
print("\n", .{});
}
fn checkAnswer(expected: u4, answer: u4) void {
if (expected != answer) {
print("*************************************************************\n", .{});
print("= {b:0>4} <- INCORRECT! THE EXPECTED OUTPUT IS {b:0>4}\n", .{ answer, expected });
print("*************************************************************\n", .{});
} else {
print("= {b:0>4}", .{answer});
}
newline();
}

View File

@ -12,6 +12,12 @@
# using the patches in this directory and convey them
# to convalesce in the healed directory.
#
delete_progress() {
progress_file=".progress.txt"
if [ -f $progress_file ]; then
rm $progress_file
fi
}
set -e
# We check ourselves before we wreck ourselves.
@ -23,9 +29,12 @@ fi
# Which version we have?
echo "Zig version" $(zig version)
echo "Eowyn version 23.10.5.1, let's try our magic power."
echo "Eowyn version 25.1.9, let's try our magic power."
echo ""
# Remove progress file
delete_progress
# Create directory of healing if it doesn't already exist.
mkdir -p patches/healed
@ -54,3 +63,6 @@ zig fmt --check patches/healed
# Test the healed exercises. May the compiler have mercy upon us.
zig build -Dhealed
# Remove progress file again
delete_progress

View File

@ -1,20 +1,19 @@
--- exercises/046_optionals2.zig 2023-10-03 22:15:22.122241138 +0200
+++ answers/046_optionals2.zig 2023-10-05 20:04:07.049433424 +0200
@@ -21,7 +21,7 @@
--- exercises/046_optionals2.zig 2024-11-08 22:46:25.592875338 +0100
+++ answers/046_optionals2.zig 2024-11-08 22:46:20.699447951 +0100
@@ -22,7 +22,7 @@
const Elephant = struct {
letter: u8,
- tail: *Elephant = null, // Hmm... tail needs something...
+ tail: ?*Elephant = null, // <---- make this optional!
+ tail: ?*Elephant = null, // Hmm... tail needs something...
visited: bool = false,
};
@@ -51,7 +51,7 @@
// We should stop once we encounter a tail that
// does NOT point to another element. What can
// we put here to make that happen?
- if (e.tail == null) ???;
+ if (e.tail == null) break;
@@ -66,6 +66,6 @@
e = e.tail.?;
// HINT: We want something similar to what `.?` does,
// but instead of ending the program, we want to exit the loop...
- e = e.tail ???
+ e = e.tail orelse break;
}
}

View File

@ -1,8 +1,8 @@
--- exercises/058_quiz7.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/058_quiz7.zig 2023-10-05 20:04:07.106101152 +0200
--- exercises/058_quiz7.zig 2024-10-28 09:06:49.448505460 +0100
+++ answers/058_quiz7.zig 2024-10-28 09:35:14.631932322 +0100
@@ -192,8 +192,8 @@
// Oops! The hermit forgot how to capture the union values
// in a switch statement. Please capture both values as
// in a switch statement. Please capture each value as
// 'p' so the print statements work!
- .place => print("{s}", .{p.name}),
- .path => print("--{}->", .{p.dist}),

View File

@ -1,11 +1,11 @@
--- exercises/060_floats.zig 2023-11-06 19:45:03.609687304 +0100
+++ answers/060_floats.zig 2023-11-06 19:44:49.249419994 +0100
--- exercises/060_floats.zig 2025-03-03 20:23:40.255443963 +0400
+++ answers/060_floats.zig 2025-03-03 20:29:58.554854977 +0400
@@ -43,7 +43,7 @@
//
// We'll convert this weight from pound to kilograms at a
// conversion of 0.453592kg to the pound.
- const shuttle_weight: f16 = 0.453592 * 4480e6;
+ const shuttle_weight: f32 = 0.453592 * 4.480e6;
// We'll convert this weight from pounds to metric units at a
// conversion of 0.453592 kg to the pound.
- const shuttle_weight: f16 = 0.453592 * 4480e3;
+ const shuttle_weight: f32 = 0.453592 * 4.480e3;
// By default, float values are formatted in scientific
// notation. Try experimenting with '{d}' and '{d:.3}' to see

View File

@ -1,5 +1,5 @@
--- exercises/065_builtins2.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/065_builtins2.zig 2023-10-05 20:04:07.136101712 +0200
--- exercises/065_builtins2.zig 2024-11-02 16:58:30.607829441 +0100
+++ answers/065_builtins2.zig 2024-11-02 16:58:33.821220588 +0100
@@ -58,7 +58,7 @@
// Oops! We cannot leave the 'me' and 'myself' fields
// undefined. Please set them here:
@ -24,16 +24,16 @@
// (which is a zero-bit type that takes up no space at all!):
- if (fields[0].??? != void) {
+ if (fields[0].type != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[0].name});
print(" {s}", .{fields[0].name});
}
- if (fields[1].??? != void) {
+ if (fields[1].type != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[1].name});
print(" {s}", .{fields[1].name});
}
- if (fields[2].??? != void) {
+ if (fields[2].type != void) {
print(" {s}", .{@typeInfo(Narcissus).Struct.fields[2].name});
print(" {s}", .{fields[2].name});
}

View File

@ -1,8 +1,8 @@
--- exercises/071_comptime6.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/071_comptime6.zig 2023-10-05 20:04:07.162768879 +0200
--- exercises/071_comptime6.zig 2024-09-02 19:21:50.250454978 +0200
+++ answers/071_comptime6.zig 2024-09-02 19:21:23.553250563 +0200
@@ -40,7 +40,7 @@
const fields = @typeInfo(Narcissus).Struct.fields;
const fields = @typeInfo(Narcissus).@"struct".fields;
- ??? {
+ inline for (fields) |field| {

View File

@ -1,5 +1,5 @@
--- exercises/076_sentinels.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/076_sentinels.zig 2023-10-05 20:04:07.186102649 +0200
--- exercises/076_sentinels.zig 2024-09-02 19:27:04.336781039 +0200
+++ answers/076_sentinels.zig 2024-09-02 19:26:15.709134934 +0200
@@ -82,7 +82,7 @@
print("Array:", .{});

View File

@ -1,11 +1,11 @@
--- exercises/082_anonymous_structs3.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/082_anonymous_structs3.zig 2023-10-05 20:04:07.212769813 +0200
--- exercises/082_anonymous_structs3.zig 2025-03-14 16:41:17.892873287 +0200
+++ answers/082_anonymous_structs3.zig 2025-03-14 16:40:56.043829543 +0200
@@ -82,14 +82,14 @@
// @typeInfo(Circle).Struct.fields
// @typeInfo(Circle).@"struct".fields
//
// This will be an array of StructFields.
- const fields = ???;
+ const fields = @typeInfo(@TypeOf(tuple)).Struct.fields;
+ const fields = @typeInfo(@TypeOf(tuple)).@"struct".fields;
// 2. Loop through each field. This must be done at compile
// time.
@ -17,7 +17,7 @@
// 3. Print the field's name, type, and value.
//
// Each 'field' in this loop is one of these:
@@ -117,9 +117,9 @@
@@ -119,9 +119,9 @@
//
// The first field should print as: "0"(bool):true
print("\"{s}\"({any}):{any} ", .{

View File

@ -1,5 +1,5 @@
--- exercises/097_bit_manipulation.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/097_bit_manipulation.zig 2023-10-05 20:04:07.282771124 +0200
--- exercises/097_bit_manipulation.zig 2025-05-12 21:25:03.395385743 +0200
+++ answers/097_bit_manipulation.zig 2025-05-12 21:22:57.472986976 +0200
@@ -80,7 +80,7 @@
y ^= x;
@ -7,5 +7,5 @@
- ???;
+ x ^= y;
print("x = {d}; y = {d}\n", .{ x, y });
print("x = {b}; y = {b}\n", .{ x, y });
}

View File

@ -1,5 +1,5 @@
--- exercises/099_formatting.zig 2023-10-03 22:15:22.125574535 +0200
+++ answers/099_formatting.zig 2023-10-05 20:04:07.292771311 +0200
--- exercises/099_formatting.zig 2024-11-07 21:45:10.459123650 +0100
+++ answers/099_formatting.zig 2024-11-07 21:43:55.154345991 +0100
@@ -131,7 +131,7 @@
for (0..size) |b| {
// What formatting is needed here to make our columns

View File

@ -7,5 +7,5 @@
- for (hex_nums, ???) |hn, ???| {
+ for (hex_nums, dec_nums) |hn, dn| {
if (hn != dn) {
std.debug.print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn });
print("Uh oh! Found a mismatch: {d} vs {d}\n", .{ hn, dn });
return;

View File

@ -1,16 +1,16 @@
--- exercises/106_files.zig 2024-03-27 16:52:05.660910200 +0800
+++ answers/106_files.zig 2024-03-27 16:52:09.649422200 +0800
--- exercises/106_files.zig 2025-03-13 15:26:59.532367792 +0200
+++ answers/106_files.zig 2025-03-14 22:04:52.243435159 +0200
@@ -35,7 +35,7 @@
// by doing nothing
//
// we want to catch error.PathAlreadyExists and do nothing
- ??? => {},
+ error.PathAlreadyExists => {},
// if is any other unexpected error we just propagate it through
// if there's any other unexpected error we just propagate it through
else => return e,
};
@@ -44,7 +44,7 @@
// wait a minute
// wait a minute...
// opening a directory might fail!
// what should we do here?
- var output_dir: std.fs.Dir = cwd.openDir("output", .{});
@ -20,10 +20,10 @@
// 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 are a keyword in zig that
// allow you "defer" code execute to the end of scope...
// if only there were a keyword in Zig that
// allowed you to "defer" code execution to the end of the scope...
- file.close();
+ defer file.close();
// !you are not allow to switch this two lines to before file closing line!
// you are not allowed to move these two lines above the file closing line!
const byte_written = try file.write("It's zigling time!");

View File

@ -1,26 +1,26 @@
--- exercises/107_files2.zig 2024-03-27 16:51:56.199719600 +0800
+++ answers/107_files2.zig 2024-03-27 16:52:01.650935300 +0800
--- exercises/107_files2.zig 2025-03-13 15:26:59.532367792 +0200
+++ answers/107_files2.zig 2025-03-14 22:08:35.167953736 +0200
@@ -33,7 +33,7 @@
// initalize an array of u8 with all letter 'A'.
// we need to pick a size of the array, 64 seems like a good number.
// fix the initalization below
// initialize an array of u8 with all letter 'A'
// we need to pick the size of the array, 64 seems like a good number
// fix the initialization 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 ?
// 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 answer that are both vaild in this case
- const byte_read = zig_read_the_file_or_i_will_fight_you(&content);
+ const byte_read = try file.read(&content);
// hint: you might find two answers that are both valid in this case
- const bytes_read = zig_read_the_file_or_i_will_fight_you(&content);
+ const bytes_read = try file.read(&content);
// Woah, too screamy, I know you're excited for zigling time but tone it down a bit
// Can you print only what we read from the file ?
std.debug.print("Successfully Read {d} byte: {s}\n", .{
byte_read,
// 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..byte_read], // change this line only
+ content[0..bytes_read], // change this line only
});
}

View File

@ -0,0 +1,18 @@
--- exercises/108_labeled_switch.zig 2024-09-20 12:09:24.370066539 +0200
+++ answers/108_labeled_switch.zig 2024-09-20 12:09:06.499711739 +0200
@@ -65,13 +65,13 @@
// how would you fix it?
pr: switch (PullRequestState.Draft) {
PullRequestState.Draft => continue :pr PullRequestState.InReview,
- PullRequestState.InReview => continue :pr PullRequestState.Rejected,
+ PullRequestState.InReview => continue :pr PullRequestState.Approved,
PullRequestState.Approved => continue :pr PullRequestState.Merged,
PullRequestState.Rejected => {
std.debug.print("The pull request has been rejected.\n", .{});
return;
},
- PullRequestState.Merged => break, // Would you know where to break to?
+ PullRequestState.Merged => break :pr, // Would you know where to break to?
}
std.debug.print("The pull request has been merged.\n", .{});
}

View File

@ -0,0 +1,13 @@
--- exercises/109_vectors.zig 2024-11-07 14:57:09.673383618 +0100
+++ answers/109_vectors.zig 2024-11-07 14:22:59.069150138 +0100
@@ -121,8 +121,8 @@
const Vec4 = @Vector(4, f32);
fn calcMaxPairwiseDiffNew(a: Vec4, b: Vec4) f32 {
- const abs_diff_vec = ???;
- const max_diff = @reduce(???, abs_diff_vec);
+ const abs_diff_vec = @abs(a - b);
+ const max_diff = @reduce(.Max, abs_diff_vec);
return max_diff;
}

View File

@ -0,0 +1,56 @@
--- exercises/110_quiz9.zig 2025-02-08 13:19:48.522641785 -0800
+++ answers/110_quiz9.zig 2025-02-10 17:42:04.525004335 -0800
@@ -108,7 +108,7 @@
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0101});
- PORTB ^= (1 << 1) | (1 << 0); // What's wrong here?
+ PORTB ^= (1 << 2) | (1 << 0);
checkAnswer(0b1001, PORTB);
newline();
@@ -116,7 +116,7 @@
PORTB = 0b1100;
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("^ {b:0>4} // (bitmask)\n", .{0b0011});
- PORTB ^= (1 << 1) & (1 << 0); // What's wrong here?
+ PORTB ^= (1 << 1) | (1 << 0);
checkAnswer(0b1111, PORTB);
newline();
@@ -170,7 +170,7 @@
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
- PORTB = PORTB ??? (1 << 2); // What's missing here?
+ PORTB = PORTB | (1 << 2);
checkAnswer(0b1101, PORTB);
newline();
@@ -178,7 +178,7 @@
PORTB = 0b1001; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("| {b:0>4} // (bitmask)\n", .{0b0100});
- PORTB ??? (1 << 2); // What's missing here?
+ PORTB |= (1 << 2);
checkAnswer(0b1101, PORTB);
newline();
@@ -269,7 +269,7 @@
PORTB = 0b1110; // reset PORTB
print(" {b:0>4} // (initial state of PORTB)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1011});
- PORTB = PORTB & ???@as(u4, 1 << 2); // What character is missing here?
+ PORTB = PORTB & ~@as(u4, 1 << 2);
checkAnswer(0b1010, PORTB);
newline();
@@ -277,7 +277,7 @@
PORTB = 0b0111; // reset PORTB
print(" {b:0>4} // (reset state)\n", .{PORTB});
print("& {b:0>4} // (bitmask)\n", .{0b1110});
- PORTB &= ~(1 << 0); // What's missing here?
+ PORTB &= ~@as(u4, 1 << 0);
checkAnswer(0b0110, PORTB);
newline();

View File

@ -50,7 +50,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
case_step.dependOn(&verify.step);
}
const cleanup = b.addRemoveDirTree(tmp_path);
const cleanup = b.addRemoveDirTree(.{ .src_path = .{ .owner = b, .sub_path = tmp_path } });
cleanup.step.dependOn(case_step);
step.dependOn(&cleanup.step);
@ -82,7 +82,7 @@ pub fn addCliTests(b: *std.Build, exercises: []const Exercise) *Step {
const verify = CheckStep.create(b, exercises, stderr);
verify.step.dependOn(&cmd.step);
const cleanup = b.addRemoveDirTree(tmp_path);
const cleanup = b.addRemoveDirTree(.{ .src_path = .{ .owner = b, .sub_path = tmp_path } });
cleanup.step.dependOn(&verify.step);
step.dependOn(&cleanup.step);
@ -150,7 +150,7 @@ const CheckNamedStep = struct {
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
fn make(step: *Step, _: Step.MakeOptions) !void {
const b = step.owner;
const self: *CheckNamedStep = @alignCast(@fieldParentPtr("step", step));
const ex = self.exercise;
@ -202,7 +202,7 @@ const CheckStep = struct {
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
fn make(step: *Step, _: Step.MakeOptions) !void {
const b = step.owner;
const self: *CheckStep = @alignCast(@fieldParentPtr("step", step));
const exercises = self.exercises;
@ -325,7 +325,7 @@ const FailStep = struct {
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
fn make(step: *Step, _: Step.MakeOptions) !void {
const b = step.owner;
const self: *FailStep = @alignCast(@fieldParentPtr("step", step));
@ -368,7 +368,7 @@ const HealStep = struct {
return self;
}
fn make(step: *Step, _: *std.Progress.Node) !void {
fn make(step: *Step, _: Step.MakeOptions) !void {
const b = step.owner;
const self: *HealStep = @alignCast(@fieldParentPtr("step", step));