add zig solutions
This commit is contained in:
commit
aa2deeb687
42 changed files with 1719 additions and 0 deletions
22
zig/collatz-conjecture/.exercism/config.json
Normal file
22
zig/collatz-conjecture/.exercism/config.json
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"massivelivefun"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"ee7"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"collatz_conjecture.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_collatz_conjecture.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.",
|
||||||
|
"source": "An unsolved problem in mathematics named after mathematician Lothar Collatz",
|
||||||
|
"source_url": "https://en.wikipedia.org/wiki/3x_%2B_1_problem"
|
||||||
|
}
|
1
zig/collatz-conjecture/.exercism/metadata.json
Normal file
1
zig/collatz-conjecture/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"collatz-conjecture","id":"af061fffe6b244cf823d3ced4d948326","url":"https://exercism.org/tracks/zig/exercises/collatz-conjecture","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/collatz-conjecture/HELP.md
Normal file
53
zig/collatz-conjecture/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit collatz_conjecture.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
67
zig/collatz-conjecture/README.md
Normal file
67
zig/collatz-conjecture/README.md
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Collatz Conjecture
|
||||||
|
|
||||||
|
Welcome to Collatz Conjecture on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
The Collatz Conjecture or 3x+1 problem can be summarized as follows:
|
||||||
|
|
||||||
|
Take any positive integer n.
|
||||||
|
If n is even, divide n by 2 to get n / 2.
|
||||||
|
If n is odd, multiply n by 3 and add 1 to get 3n + 1.
|
||||||
|
Repeat the process indefinitely.
|
||||||
|
The conjecture states that no matter which number you start with, you will always reach 1 eventually.
|
||||||
|
|
||||||
|
Given a number n, return the number of steps required to reach 1.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Starting with n = 12, the steps would be as follows:
|
||||||
|
|
||||||
|
0. 12
|
||||||
|
1. 6
|
||||||
|
2. 3
|
||||||
|
3. 10
|
||||||
|
4. 5
|
||||||
|
5. 16
|
||||||
|
6. 8
|
||||||
|
7. 4
|
||||||
|
8. 2
|
||||||
|
9. 1
|
||||||
|
|
||||||
|
Resulting in 9 steps.
|
||||||
|
So for input n = 12, the return value would be 9.
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
For this exercise you must add an error set `ComputationError` that contains the `IllegalArgument` error.
|
||||||
|
Remember to make it public!
|
||||||
|
The `steps` function must return `ComputationError.IllegalArgument` when its input is equal to zero.
|
||||||
|
|
||||||
|
Later exercises will usually omit explicit instructions like this.
|
||||||
|
In general, Exercism expects you to read the test file when implementing your solution.
|
||||||
|
|
||||||
|
For more details about errors in Zig, see:
|
||||||
|
|
||||||
|
- [Learning Zig - Errors][learning-zig-errors]
|
||||||
|
- [Ziglings - Exercise 21][ziglings-exercise-21]
|
||||||
|
- [Zighelp - Errors][zighelp-errors]
|
||||||
|
|
||||||
|
[learning-zig-errors]: https://www.openmymind.net/learning_zig/language_overview_2/#errors
|
||||||
|
[zighelp-errors]: https://zighelp.org/chapter-1/#errors
|
||||||
|
[ziglings-exercise-21]: https://codeberg.org/ziglings/exercises/src/commit/0d46acfa02d0c29fdfb3651e82a77284dd8f2e00/exercises/021_errors.zig
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @massivelivefun
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @ee7
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
An unsolved problem in mathematics named after mathematician Lothar Collatz - https://en.wikipedia.org/wiki/3x_%2B_1_problem
|
20
zig/collatz-conjecture/collatz_conjecture.zig
Normal file
20
zig/collatz-conjecture/collatz_conjecture.zig
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// Please implement the `ComputationError.IllegalArgument` error.
|
||||||
|
|
||||||
|
pub const ComputationError = error{IllegalArgument};
|
||||||
|
|
||||||
|
pub fn steps(number: usize) anyerror!usize {
|
||||||
|
if (number == 0) {
|
||||||
|
return ComputationError.IllegalArgument;
|
||||||
|
}
|
||||||
|
return collatz(number, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collatz(number: usize, acc: usize) usize {
|
||||||
|
if (number == 1) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = if (number % 2 == 0) number / 2 else number * 3 + 1;
|
||||||
|
|
||||||
|
return collatz(next, acc + 1);
|
||||||
|
}
|
8
zig/collatz-conjecture/lol.zig
Normal file
8
zig/collatz-conjecture/lol.zig
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const print = std.debug.print;
|
||||||
|
|
||||||
|
pub fn main() void {
|
||||||
|
const i = if (2 >= 2) 100 else 50;
|
||||||
|
|
||||||
|
print("your number was {d}", .{i});
|
||||||
|
}
|
35
zig/collatz-conjecture/test_collatz_conjecture.zig
Normal file
35
zig/collatz-conjecture/test_collatz_conjecture.zig
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const collatz_conjecture = @import("collatz_conjecture.zig");
|
||||||
|
const ComputationError = collatz_conjecture.ComputationError;
|
||||||
|
|
||||||
|
test "zero steps for one" {
|
||||||
|
const expected: usize = 0;
|
||||||
|
const actual = try collatz_conjecture.steps(1);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "divide if even" {
|
||||||
|
const expected: usize = 4;
|
||||||
|
const actual = try collatz_conjecture.steps(16);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "even and odd steps" {
|
||||||
|
const expected: usize = 9;
|
||||||
|
const actual = try collatz_conjecture.steps(12);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "large number of even and odd steps" {
|
||||||
|
const expected: usize = 152;
|
||||||
|
const actual = try collatz_conjecture.steps(1_000_000);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "zero is an error" {
|
||||||
|
const expected = ComputationError.IllegalArgument;
|
||||||
|
const actual = collatz_conjecture.steps(0);
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
19
zig/difference-of-squares/.exercism/config.json
Normal file
19
zig/difference-of-squares/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"massivelivefun"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"difference_of_squares.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_difference_of_squares.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.",
|
||||||
|
"source": "Problem 6 at Project Euler",
|
||||||
|
"source_url": "https://projecteuler.net/problem=6"
|
||||||
|
}
|
1
zig/difference-of-squares/.exercism/metadata.json
Normal file
1
zig/difference-of-squares/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"difference-of-squares","id":"a1fe4d3d6da444a8b36f9cc0e50182d0","url":"https://exercism.org/tracks/zig/exercises/difference-of-squares","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/difference-of-squares/HELP.md
Normal file
53
zig/difference-of-squares/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit difference_of_squares.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
29
zig/difference-of-squares/README.md
Normal file
29
zig/difference-of-squares/README.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Difference of Squares
|
||||||
|
|
||||||
|
Welcome to Difference of Squares on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Find the difference between the square of the sum and the sum of the squares of the first N natural numbers.
|
||||||
|
|
||||||
|
The square of the sum of the first ten natural numbers is
|
||||||
|
(1 + 2 + ... + 10)² = 55² = 3025.
|
||||||
|
|
||||||
|
The sum of the squares of the first ten natural numbers is
|
||||||
|
1² + 2² + ... + 10² = 385.
|
||||||
|
|
||||||
|
Hence the difference between the square of the sum of the first ten natural numbers and the sum of the squares of the first ten natural numbers is 3025 - 385 = 2640.
|
||||||
|
|
||||||
|
You are not expected to discover an efficient solution to this yourself from first principles; research is allowed, indeed, encouraged.
|
||||||
|
Finding the best algorithm for the problem is a key skill in software engineering.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @massivelivefun
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Problem 6 at Project Euler - https://projecteuler.net/problem=6
|
24
zig/difference-of-squares/box.zig
Normal file
24
zig/difference-of-squares/box.zig
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
const print = @import("std").debug.print;
|
||||||
|
const SomeStruct = struct { inner: ?usize = null };
|
||||||
|
|
||||||
|
pub fn Box(comptime T: type) type {
|
||||||
|
return struct {
|
||||||
|
inner: ?*T,
|
||||||
|
fn drop(self: *Box(T)) void {
|
||||||
|
self.inner.?.* = SomeStruct{ .inner = 1000 };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() void {
|
||||||
|
var s = SomeStruct{};
|
||||||
|
var box = Box(SomeStruct){ .inner = &s };
|
||||||
|
s.inner = 100;
|
||||||
|
|
||||||
|
print("{any}\n", .{box.inner == &s});
|
||||||
|
print("{any}\n", .{box.inner.?.inner});
|
||||||
|
box.drop();
|
||||||
|
print("{any}\n", .{box.inner == &s});
|
||||||
|
print("{any}\n", .{box.inner});
|
||||||
|
print("{any}\n", .{s});
|
||||||
|
}
|
16
zig/difference-of-squares/difference_of_squares.zig
Normal file
16
zig/difference-of-squares/difference_of_squares.zig
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
const pow = @import("std").math.pow;
|
||||||
|
pub fn squareOfSum(n: usize) usize {
|
||||||
|
return pow(usize, (n * (n + 1) / 2), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sumOfSquares(number: usize) usize {
|
||||||
|
var tot: usize = 0;
|
||||||
|
for (0..(number + 1)) |n| {
|
||||||
|
tot += pow(usize, n, 2);
|
||||||
|
}
|
||||||
|
return tot;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn differenceOfSquares(number: usize) usize {
|
||||||
|
return squareOfSum(number) - sumOfSquares(number);
|
||||||
|
}
|
10
zig/difference-of-squares/test.zig
Normal file
10
zig/difference-of-squares/test.zig
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const print = std.debug.print;
|
||||||
|
const pow = std.math.pow;
|
||||||
|
|
||||||
|
pub fn main() void {
|
||||||
|
// print("{d}", .{pow(usize, 3, 2)});
|
||||||
|
for (0..=10) |n| {
|
||||||
|
print("{d}", .{n});
|
||||||
|
}
|
||||||
|
}
|
58
zig/difference-of-squares/test_difference_of_squares.zig
Normal file
58
zig/difference-of-squares/test_difference_of_squares.zig
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const difference_of_squares = @import("difference_of_squares.zig");
|
||||||
|
|
||||||
|
test "square of sum up to 1" {
|
||||||
|
const expected: usize = 1;
|
||||||
|
const actual = difference_of_squares.squareOfSum(1);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "square of sum up to 5" {
|
||||||
|
const expected: usize = 225;
|
||||||
|
const actual = difference_of_squares.squareOfSum(5);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "square of sum up to 100" {
|
||||||
|
const expected: usize = 25_502_500;
|
||||||
|
const actual = difference_of_squares.squareOfSum(100);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "sum of squares up to 1" {
|
||||||
|
const expected: usize = 1;
|
||||||
|
const actual = difference_of_squares.sumOfSquares(1);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "sum of squares up to 5" {
|
||||||
|
const expected: usize = 55;
|
||||||
|
const actual = difference_of_squares.sumOfSquares(5);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "sum of squares up to 100" {
|
||||||
|
const expected: usize = 338_350;
|
||||||
|
const actual = difference_of_squares.sumOfSquares(100);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "difference of squares up to 1" {
|
||||||
|
const expected: usize = 0;
|
||||||
|
const actual = difference_of_squares.differenceOfSquares(1);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "difference of squares up to 5" {
|
||||||
|
const expected: usize = 170;
|
||||||
|
const actual = difference_of_squares.differenceOfSquares(5);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "difference of squares up to 100" {
|
||||||
|
const expected: usize = 25_164_150;
|
||||||
|
const actual = difference_of_squares.differenceOfSquares(100);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
18
zig/linked-list/.exercism/config.json
Normal file
18
zig/linked-list/.exercism/config.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"ee7"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"linked_list.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_linked_list.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Implement a doubly linked list.",
|
||||||
|
"source": "Classic computer science topic"
|
||||||
|
}
|
1
zig/linked-list/.exercism/metadata.json
Normal file
1
zig/linked-list/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"linked-list","id":"5e4f2325faa44e6caf53842c3815c3e5","url":"https://exercism.org/tracks/zig/exercises/linked-list","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/linked-list/HELP.md
Normal file
53
zig/linked-list/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit linked_list.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
53
zig/linked-list/README.md
Normal file
53
zig/linked-list/README.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Linked List
|
||||||
|
|
||||||
|
Welcome to Linked List on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
You are working on a project to develop a train scheduling system for a busy railway network.
|
||||||
|
|
||||||
|
You've been asked to develop a prototype for the train routes in the scheduling system.
|
||||||
|
Each route consists of a sequence of train stations that a given train stops at.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Your team has decided to use a doubly linked list to represent each train route in the schedule.
|
||||||
|
Each station along the train's route will be represented by a node in the linked list.
|
||||||
|
|
||||||
|
You don't need to worry about arrival and departure times at the stations.
|
||||||
|
Each station will simply be represented by a number.
|
||||||
|
|
||||||
|
Routes can be extended, adding stations to the beginning or end of a route.
|
||||||
|
They can also be shortened by removing stations from the beginning or the end of a route.
|
||||||
|
|
||||||
|
Sometimes a station gets closed down, and in that case the station needs to be removed from the route, even if it is not at the beginning or end of the route.
|
||||||
|
|
||||||
|
The size of a route is measured not by how far the train travels, but by how many stations it stops at.
|
||||||
|
|
||||||
|
~~~~exercism/note
|
||||||
|
The linked list is a fundamental data structure in computer science, often used in the implementation of other data structures.
|
||||||
|
As the name suggests, it is a list of nodes that are linked together.
|
||||||
|
It is a list of "nodes", where each node links to its neighbor or neighbors.
|
||||||
|
In a **singly linked list** each node links only to the node that follows it.
|
||||||
|
In a **doubly linked list** each node links to both the node that comes before, as well as the node that comes after.
|
||||||
|
|
||||||
|
If you want to dig deeper into linked lists, check out [this article][intro-linked-list] that explains it using nice drawings.
|
||||||
|
|
||||||
|
[intro-linked-list]: https://medium.com/basecs/whats-a-linked-list-anyway-part-1-d8b7e6508b9d
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
## Error handling
|
||||||
|
|
||||||
|
For this exercise, you don't need to think about errors.
|
||||||
|
In particular, the tests will never call `pop` or `shift` on an empty list.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @ee7
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Classic computer science topic
|
9
zig/linked-list/l.zig
Normal file
9
zig/linked-list/l.zig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const print = std.debug.print;
|
||||||
|
pub fn main() void {
|
||||||
|
const u: usize = 100;
|
||||||
|
var p: ?*const usize = &u;
|
||||||
|
const t = p;
|
||||||
|
p = null;
|
||||||
|
print("{any}", .{t.?.*});
|
||||||
|
}
|
97
zig/linked-list/linked_list.zig
Normal file
97
zig/linked-list/linked_list.zig
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
pub fn LinkedList(comptime T: type) type {
|
||||||
|
return struct {
|
||||||
|
// Please implement the doubly linked `Node` (replacing each `void`).
|
||||||
|
pub const Node = struct {
|
||||||
|
prev: ?*Node = null,
|
||||||
|
next: ?*Node = null,
|
||||||
|
data: T,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Please implement the fields of the linked list (replacing each `void`).
|
||||||
|
first: ?*Node = null,
|
||||||
|
last: ?*Node = null,
|
||||||
|
len: usize = 0,
|
||||||
|
|
||||||
|
// Please implement the below methods.
|
||||||
|
// You need to add the parameters to each method.
|
||||||
|
|
||||||
|
pub fn push(self: *LinkedList(T), item: *Node) void {
|
||||||
|
defer self.len += 1;
|
||||||
|
if (self.len == 0) {
|
||||||
|
self.first = item;
|
||||||
|
} else {
|
||||||
|
self.last.?.next = item;
|
||||||
|
item.prev = self.last;
|
||||||
|
}
|
||||||
|
self.last = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop(self: *LinkedList(T)) ?*Node {
|
||||||
|
defer self.len -= 1;
|
||||||
|
const last = self.last.?;
|
||||||
|
if (last.prev != null) {
|
||||||
|
self.last = last.prev;
|
||||||
|
self.last.?.next = null;
|
||||||
|
last.prev = null;
|
||||||
|
} else {
|
||||||
|
self.last = null;
|
||||||
|
self.first = null;
|
||||||
|
}
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shift(self: *LinkedList(T)) ?*Node {
|
||||||
|
defer self.len -= 1;
|
||||||
|
const first = self.first.?;
|
||||||
|
if (first != self.last) {
|
||||||
|
self.first = first.next.?;
|
||||||
|
self.first.?.prev = null;
|
||||||
|
first.next = null;
|
||||||
|
} else {
|
||||||
|
self.first = null;
|
||||||
|
self.last = null;
|
||||||
|
}
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unshift(self: *LinkedList(T), item: *Node) void {
|
||||||
|
defer self.len += 1;
|
||||||
|
if (self.len != 0) {
|
||||||
|
const first = self.first;
|
||||||
|
first.?.prev = item;
|
||||||
|
item.next = first;
|
||||||
|
} else {
|
||||||
|
self.last = item;
|
||||||
|
}
|
||||||
|
self.first = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(self: *LinkedList(T), item: *Node) void {
|
||||||
|
var n: ?*Node = self.first;
|
||||||
|
while (n != item and n != null) {
|
||||||
|
n = n.?.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n != null) {
|
||||||
|
defer self.len -= 1;
|
||||||
|
const prev = n.?.prev;
|
||||||
|
const next = n.?.next;
|
||||||
|
if (prev != null) {
|
||||||
|
prev.?.next = next;
|
||||||
|
}
|
||||||
|
if (next != null) {
|
||||||
|
next.?.prev = prev;
|
||||||
|
}
|
||||||
|
if (self.last == n) {
|
||||||
|
self.last = n.?.prev;
|
||||||
|
}
|
||||||
|
if (self.first == n) {
|
||||||
|
self.first = n.?.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.?.prev = null;
|
||||||
|
n.?.next = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
222
zig/linked-list/test_linked_list.zig
Normal file
222
zig/linked-list/test_linked_list.zig
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const linked_list = @import("linked_list.zig");
|
||||||
|
const List = linked_list.LinkedList(usize);
|
||||||
|
|
||||||
|
test "pop gets element from the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 7 };
|
||||||
|
list.push(&a);
|
||||||
|
try testing.expectEqual(@as(usize, 7), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "push/pop respectively add/remove at the end of the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 11 };
|
||||||
|
var b = List.Node{ .data = 13 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 13), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 11), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "shift gets an element from the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 17 };
|
||||||
|
list.push(&a);
|
||||||
|
try testing.expectEqual(@as(usize, 17), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "shift gets first element from the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 23 };
|
||||||
|
var b = List.Node{ .data = 5 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 23), list.shift().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 5), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "unshift adds element at start of the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 23 };
|
||||||
|
var b = List.Node{ .data = 5 };
|
||||||
|
list.unshift(&a);
|
||||||
|
list.unshift(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 5), list.shift().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 23), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "pop, push, shift, and unshift can be used in any order" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 1 };
|
||||||
|
var b = List.Node{ .data = 2 };
|
||||||
|
var c = List.Node{ .data = 3 };
|
||||||
|
var d = List.Node{ .data = 4 };
|
||||||
|
var e = List.Node{ .data = 5 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.pop().?.data);
|
||||||
|
list.push(&c);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.shift().?.data);
|
||||||
|
list.unshift(&d);
|
||||||
|
list.push(&e);
|
||||||
|
try testing.expectEqual(@as(usize, 4), list.shift().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 5), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 3), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "count an empty list" {
|
||||||
|
const list = List{};
|
||||||
|
try testing.expectEqual(@as(usize, 0), list.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "count a list with items" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 37 };
|
||||||
|
var b = List.Node{ .data = 1 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "count is correct after mutation" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 31 };
|
||||||
|
var b = List.Node{ .data = 43 };
|
||||||
|
list.push(&a);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
list.unshift(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.len);
|
||||||
|
_ = list.shift();
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
_ = list.pop();
|
||||||
|
try testing.expectEqual(@as(usize, 0), list.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "popping to empty doesn't break the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 41 };
|
||||||
|
var b = List.Node{ .data = 59 };
|
||||||
|
var c = List.Node{ .data = 47 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
_ = list.pop();
|
||||||
|
_ = list.pop();
|
||||||
|
list.push(&c);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 47), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "shifting to empty doesn't break the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 41 };
|
||||||
|
var b = List.Node{ .data = 59 };
|
||||||
|
var c = List.Node{ .data = 47 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
_ = list.shift();
|
||||||
|
_ = list.shift();
|
||||||
|
list.push(&c);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 47), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the only element" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 61 };
|
||||||
|
list.push(&a);
|
||||||
|
list.delete(&a);
|
||||||
|
try testing.expectEqual(@as(usize, 0), list.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the element with the specified value from the list" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 71 };
|
||||||
|
var b = List.Node{ .data = 83 };
|
||||||
|
var c = List.Node{ .data = 79 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.push(&c);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 79), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 71), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the element with the specified value from the list, re-assigns tail" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 71 };
|
||||||
|
var b = List.Node{ .data = 83 };
|
||||||
|
var c = List.Node{ .data = 79 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.push(&c);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 79), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 71), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the element with the specified value from the list, re-assigns head" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 71 };
|
||||||
|
var b = List.Node{ .data = 83 };
|
||||||
|
var c = List.Node{ .data = 79 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.push(&c);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 2), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 71), list.shift().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 79), list.shift().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the first of two elements" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 97 };
|
||||||
|
var b = List.Node{ .data = 101 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.delete(&a);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 101), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes the second of two elements" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 97 };
|
||||||
|
var b = List.Node{ .data = 101 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 97), list.pop().?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "delete does not modify the list if the element is not found" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 89 };
|
||||||
|
var b = List.Node{ .data = 103 };
|
||||||
|
list.push(&a);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 1), list.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "deletes only the first occurrence" {
|
||||||
|
var list = List{};
|
||||||
|
var a = List.Node{ .data = 73 };
|
||||||
|
var b = List.Node{ .data = 9 };
|
||||||
|
var c = List.Node{ .data = 9 };
|
||||||
|
var d = List.Node{ .data = 107 };
|
||||||
|
list.push(&a);
|
||||||
|
list.push(&b);
|
||||||
|
list.push(&c);
|
||||||
|
list.push(&d);
|
||||||
|
list.delete(&b);
|
||||||
|
try testing.expectEqual(@as(usize, 3), list.len);
|
||||||
|
try testing.expectEqual(@as(usize, 107), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 9), list.pop().?.data);
|
||||||
|
try testing.expectEqual(@as(usize, 73), list.pop().?.data);
|
||||||
|
}
|
19
zig/resistor-color/.exercism/config.json
Normal file
19
zig/resistor-color/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"massivelivefun"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"resistor_color.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_resistor_color.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Convert a resistor band's color to its numeric representation.",
|
||||||
|
"source": "Maud de Vries, Erik Schierboom",
|
||||||
|
"source_url": "https://github.com/exercism/problem-specifications/issues/1458"
|
||||||
|
}
|
1
zig/resistor-color/.exercism/metadata.json
Normal file
1
zig/resistor-color/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"resistor-color","id":"6f9b21444bb54050a08fc1546ff89370","url":"https://exercism.org/tracks/zig/exercises/resistor-color","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/resistor-color/HELP.md
Normal file
53
zig/resistor-color/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit resistor_color.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
54
zig/resistor-color/README.md
Normal file
54
zig/resistor-color/README.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Resistor Color
|
||||||
|
|
||||||
|
Welcome to Resistor Color on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
If you want to build something using a Raspberry Pi, you'll probably use _resistors_.
|
||||||
|
For this exercise, you need to know two things about them:
|
||||||
|
|
||||||
|
- Each resistor has a resistance value.
|
||||||
|
- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.
|
||||||
|
|
||||||
|
To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values.
|
||||||
|
Each band has a position and a numeric value.
|
||||||
|
|
||||||
|
The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number.
|
||||||
|
|
||||||
|
In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands.
|
||||||
|
|
||||||
|
These colors are encoded as follows:
|
||||||
|
|
||||||
|
- Black: 0
|
||||||
|
- Brown: 1
|
||||||
|
- Red: 2
|
||||||
|
- Orange: 3
|
||||||
|
- Yellow: 4
|
||||||
|
- Green: 5
|
||||||
|
- Blue: 6
|
||||||
|
- Violet: 7
|
||||||
|
- Grey: 8
|
||||||
|
- White: 9
|
||||||
|
|
||||||
|
The goal of this exercise is to create a way:
|
||||||
|
|
||||||
|
- to look up the numerical value associated with a particular color band
|
||||||
|
- to list the different band colors
|
||||||
|
|
||||||
|
Mnemonics map the colors to the numbers, that, when stored as an array, happen to map to their index in the array:
|
||||||
|
Better Be Right Or Your Great Big Values Go Wrong.
|
||||||
|
|
||||||
|
More information on the color encoding of resistors can be found in the [Electronic color code Wikipedia article][e-color-code].
|
||||||
|
|
||||||
|
[e-color-code]: https://en.wikipedia.org/wiki/Electronic_color_code
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @massivelivefun
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Maud de Vries, Erik Schierboom - https://github.com/exercism/problem-specifications/issues/1458
|
9
zig/resistor-color/resistor_color.zig
Normal file
9
zig/resistor-color/resistor_color.zig
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
pub const ColorBand = enum { black, brown, red, orange, yellow, green, blue, violet, grey, white };
|
||||||
|
|
||||||
|
pub fn colorCode(color: ColorBand) usize {
|
||||||
|
return @intFromEnum(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn colors() []const ColorBand {
|
||||||
|
return &[_]ColorBand{ .black, .brown, .red, .orange, .yellow, .green, .blue, .violet, .grey, .white };
|
||||||
|
}
|
32
zig/resistor-color/test_resistor_color.zig
Normal file
32
zig/resistor-color/test_resistor_color.zig
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const resistor_color = @import("resistor_color.zig");
|
||||||
|
const ColorBand = resistor_color.ColorBand;
|
||||||
|
|
||||||
|
test "black" {
|
||||||
|
const expected: usize = 0;
|
||||||
|
const actual = resistor_color.colorCode(.black);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "white" {
|
||||||
|
const expected: usize = 9;
|
||||||
|
const actual = resistor_color.colorCode(.white);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "orange" {
|
||||||
|
const expected: usize = 3;
|
||||||
|
const actual = resistor_color.colorCode(.orange);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "colors" {
|
||||||
|
const expected = &[_]ColorBand{
|
||||||
|
.black, .brown, .red, .orange, .yellow,
|
||||||
|
.green, .blue, .violet, .grey, .white,
|
||||||
|
};
|
||||||
|
const actual = resistor_color.colors();
|
||||||
|
try testing.expectEqualSlices(ColorBand, expected, actual);
|
||||||
|
}
|
19
zig/sum-of-multiples/.exercism/config.json
Normal file
19
zig/sum-of-multiples/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"ee7"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"sum_of_multiples.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_sum_of_multiples.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Given a number, find the sum of all the multiples of particular numbers up to but not including that number.",
|
||||||
|
"source": "A variation on Problem 1 at Project Euler",
|
||||||
|
"source_url": "https://projecteuler.net/problem=1"
|
||||||
|
}
|
1
zig/sum-of-multiples/.exercism/metadata.json
Normal file
1
zig/sum-of-multiples/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"sum-of-multiples","id":"abcf1217d71e4cf4b2679b7c10738eb2","url":"https://exercism.org/tracks/zig/exercises/sum-of-multiples","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/sum-of-multiples/HELP.md
Normal file
53
zig/sum-of-multiples/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit sum_of_multiples.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
33
zig/sum-of-multiples/README.md
Normal file
33
zig/sum-of-multiples/README.md
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Sum of Multiples
|
||||||
|
|
||||||
|
Welcome to Sum of Multiples on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Given a list of factors and a limit, add up all the unique multiples of the factors that are less than the limit.
|
||||||
|
All inputs will be greater than or equal to zero.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Suppose the limit is 20 and the list of factors is [3, 5].
|
||||||
|
We need to find the sum of all unique multiples of 3 and 5 that are less than 20.
|
||||||
|
|
||||||
|
Multiples of 3 less than 20: 3, 6, 9, 12, 15, 18
|
||||||
|
Multiples of 5 less than 20: 5, 10, 15
|
||||||
|
|
||||||
|
The unique multiples are: 3, 5, 6, 9, 10, 12, 15, 18
|
||||||
|
|
||||||
|
The sum of the unique multiples is: 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78
|
||||||
|
|
||||||
|
So, the answer is 78.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @ee7
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
A variation on Problem 1 at Project Euler - https://projecteuler.net/problem=1
|
21
zig/sum-of-multiples/sum_of_multiples.zig
Normal file
21
zig/sum-of-multiples/sum_of_multiples.zig
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
|
||||||
|
const FactorErrors = error{FactorOfZero};
|
||||||
|
|
||||||
|
pub fn sum(allocator: mem.Allocator, factors: []const u32, limit: u32) !u64 {
|
||||||
|
_ = allocator;
|
||||||
|
var s: u64 = 0;
|
||||||
|
for (0..limit) |i| {
|
||||||
|
for (factors) |f| {
|
||||||
|
if (f == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i % f == 0) {
|
||||||
|
s += i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
141
zig/sum-of-multiples/test_sum_of_multiples.zig
Normal file
141
zig/sum-of-multiples/test_sum_of_multiples.zig
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const sum = @import("sum_of_multiples.zig").sum;
|
||||||
|
|
||||||
|
test "no multiples within limit" {
|
||||||
|
const expected: u64 = 0;
|
||||||
|
const factors = [_]u32{ 3, 5 };
|
||||||
|
const limit = 1;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "one factor has multiples within limit" {
|
||||||
|
const expected: u64 = 3;
|
||||||
|
const factors = [_]u32{ 3, 5 };
|
||||||
|
const limit = 4;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "more than one multiple within limit" {
|
||||||
|
const expected: u64 = 9;
|
||||||
|
const factors = [_]u32{3};
|
||||||
|
const limit = 7;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "more than one factor with multiples within limit" {
|
||||||
|
const expected: u64 = 23;
|
||||||
|
const factors = [_]u32{ 3, 5 };
|
||||||
|
const limit = 10;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "each multiple is only counted once" {
|
||||||
|
const expected: u64 = 2318;
|
||||||
|
const factors = [_]u32{ 3, 5 };
|
||||||
|
const limit = 100;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "a much larger limit" {
|
||||||
|
const expected: u64 = 233_168;
|
||||||
|
const factors = [_]u32{ 3, 5 };
|
||||||
|
const limit = 1000;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "three factors" {
|
||||||
|
const expected: u64 = 51;
|
||||||
|
const factors = [_]u32{ 7, 13, 17 };
|
||||||
|
const limit = 20;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "factors not relatively prime" {
|
||||||
|
const expected: u64 = 30;
|
||||||
|
const factors = [_]u32{ 4, 6 };
|
||||||
|
const limit = 15;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "some pairs of factors relatively prime and some not" {
|
||||||
|
const expected: u64 = 4419;
|
||||||
|
const factors = [_]u32{ 5, 6, 8 };
|
||||||
|
const limit = 150;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "one factor is a multiple of another" {
|
||||||
|
const expected: u64 = 275;
|
||||||
|
const factors = [_]u32{ 5, 25 };
|
||||||
|
const limit = 51;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "much larger factors" {
|
||||||
|
const expected: u64 = 2_203_160;
|
||||||
|
const factors = [_]u32{ 43, 47 };
|
||||||
|
const limit = 10_000;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "all numbers are multiples of 1" {
|
||||||
|
const expected: u64 = 4_950;
|
||||||
|
const factors = [_]u32{1};
|
||||||
|
const limit = 100;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "no factors means an empty sum" {
|
||||||
|
const expected: u64 = 0;
|
||||||
|
const factors = [_]u32{};
|
||||||
|
const limit = 10_000;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "the only multiple of 0 is 0" {
|
||||||
|
const expected: u64 = 0;
|
||||||
|
const factors = [_]u32{0};
|
||||||
|
const limit = 1;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "the factor 0 does not affect the sum of multiples of other factors" {
|
||||||
|
const expected: u64 = 3;
|
||||||
|
const factors = [_]u32{ 3, 0 };
|
||||||
|
const limit = 4;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "solutions using include-exclude must extend to cardinality greater than 3" {
|
||||||
|
const expected: u64 = 39_614_537;
|
||||||
|
const factors = [_]u32{ 2, 3, 5, 7, 11 };
|
||||||
|
const limit = 10_000;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "sum is greater than maximum value of u32" {
|
||||||
|
// Note that for a u32 `limit`, the maximum sum of multiples fits in a u64.
|
||||||
|
const expected: u64 = 4_500_000_000;
|
||||||
|
const factors = [_]u32{100_000_000};
|
||||||
|
const limit = 1_000_000_000;
|
||||||
|
const actual = try sum(testing.allocator, &factors, limit);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
18
zig/word-count/.exercism/config.json
Normal file
18
zig/word-count/.exercism/config.json
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"ee7"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"word_count.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_word_count.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Given a phrase, count the occurrences of each word in that phrase.",
|
||||||
|
"source": "This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour."
|
||||||
|
}
|
1
zig/word-count/.exercism/metadata.json
Normal file
1
zig/word-count/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"word-count","id":"1a766232c629478b8e9943c94bbec1a1","url":"https://exercism.org/tracks/zig/exercises/word-count","handle":"seeplusplus","is_requester":true,"auto_approve":false}
|
53
zig/word-count/HELP.md
Normal file
53
zig/word-count/HELP.md
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
Write your code in `<exercise_name>.zig`.
|
||||||
|
|
||||||
|
To run the tests for an exercise, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zig test test_exercise_name.zig
|
||||||
|
```
|
||||||
|
|
||||||
|
in the exercise's root directory (replacing `exercise_name` with the name of the exercise).
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit word_count.zig` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Zig track's documentation](https://exercism.org/docs/tracks/zig)
|
||||||
|
- The [Zig track's programming category on the forum](https://forum.exercism.org/c/programming/zig)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
- [The Zig Programming Language Documentation][documentation] is a great overview of all of the language features that Zig provides to those who use it.
|
||||||
|
- [Zig Learn][zig-learn] is an excellent primer that explains the language features that Zig has to offer.
|
||||||
|
- [Ziglings][ziglings] is highly recommended.
|
||||||
|
Learn Zig by fixing tiny broken programs.
|
||||||
|
- [The Zig Programming Language Discord][discord-zig] is the main [Discord][discord].
|
||||||
|
It provides a great way to get in touch with the Zig community at large, and get some quick, direct help for any Zig related problem.
|
||||||
|
- [#zig][irc] on irc.freenode.net is the main Zig IRC channel.
|
||||||
|
- [/r/Zig][reddit] is the main Zig subreddit.
|
||||||
|
- [Stack Overflow][stack-overflow] can be used to discover code snippets and solutions to problems that may have already asked and maybe solved by others.
|
||||||
|
|
||||||
|
[discord]: https://discordapp.com
|
||||||
|
[discord-zig]: https://discord.com/invite/gxsFFjE
|
||||||
|
[documentation]: https://ziglang.org/documentation/master
|
||||||
|
[irc]: https://webchat.freenode.net/?channels=%23zig
|
||||||
|
[reddit]: https://www.reddit.com/r/Zig
|
||||||
|
[stack-overflow]: https://stackoverflow.com/questions/tagged/zig
|
||||||
|
[zig-learn]: https://ziglearn.org/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
71
zig/word-count/README.md
Normal file
71
zig/word-count/README.md
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Word Count
|
||||||
|
|
||||||
|
Welcome to Word Count on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
You teach English as a foreign language to high school students.
|
||||||
|
|
||||||
|
You've decided to base your entire curriculum on TV shows.
|
||||||
|
You need to analyze which words are used, and how often they're repeated.
|
||||||
|
|
||||||
|
This will let you choose the simplest shows to start with, and to gradually increase the difficulty as time passes.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Your task is to count how many times each word occurs in a subtitle of a drama.
|
||||||
|
|
||||||
|
The subtitles from these dramas use only ASCII characters.
|
||||||
|
|
||||||
|
The characters often speak in casual English, using contractions like _they're_ or _it's_.
|
||||||
|
Though these contractions come from two words (e.g. _we are_), the contraction (_we're_) is considered a single word.
|
||||||
|
|
||||||
|
Words can be separated by any form of punctuation (e.g. ":", "!", or "?") or whitespace (e.g. "\t", "\n", or " ").
|
||||||
|
The only punctuation that does not separate words is the apostrophe in contractions.
|
||||||
|
|
||||||
|
Numbers are considered words.
|
||||||
|
If the subtitles say _It costs 100 dollars._ then _100_ will be its own word.
|
||||||
|
|
||||||
|
Words are case insensitive.
|
||||||
|
For example, the word _you_ occurs three times in the following sentence:
|
||||||
|
|
||||||
|
> You come back, you hear me? DO YOU HEAR ME?
|
||||||
|
|
||||||
|
The ordering of the word counts in the results doesn't matter.
|
||||||
|
|
||||||
|
Here's an example that incorporates several of the elements discussed above:
|
||||||
|
|
||||||
|
- simple words
|
||||||
|
- contractions
|
||||||
|
- numbers
|
||||||
|
- case insensitive words
|
||||||
|
- punctuation (including apostrophes) to separate words
|
||||||
|
- different forms of whitespace to separate words
|
||||||
|
|
||||||
|
`"That's the password: 'PASSWORD 123'!", cried the Special Agent.\nSo I fled.`
|
||||||
|
|
||||||
|
The mapping for this subtitle would be:
|
||||||
|
|
||||||
|
```text
|
||||||
|
123: 1
|
||||||
|
agent: 1
|
||||||
|
cried: 1
|
||||||
|
fled: 1
|
||||||
|
i: 1
|
||||||
|
password: 2
|
||||||
|
so: 1
|
||||||
|
special: 1
|
||||||
|
that's: 1
|
||||||
|
the: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @ee7
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour.
|
19
zig/word-count/slices.zig
Normal file
19
zig/word-count/slices.zig
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
const print = @import("std").debug.print;
|
||||||
|
pub fn main() void {
|
||||||
|
const numbers = [_]u8{ 1, 2, 3, 4, 5 };
|
||||||
|
m(&numbers, numbers[3..4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn m(n: []const u8, s: []const u8) void {
|
||||||
|
print("{any}\n", .{s});
|
||||||
|
|
||||||
|
const max_ptr = @intFromPtr(n.ptr) + n.len;
|
||||||
|
|
||||||
|
if (max_ptr > (@intFromPtr(s.ptr) + s.len)) {
|
||||||
|
const start = @intFromPtr(s.ptr) - @intFromPtr(n.ptr);
|
||||||
|
const end = s.len + start + 1;
|
||||||
|
return m(n, n[start..end]);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
14
zig/word-count/strings.zig
Normal file
14
zig/word-count/strings.zig
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const print = std.debug.print;
|
||||||
|
const countWords = @import("./word_count.zig").countWords;
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
const alloc = std.heap.page_allocator;
|
||||||
|
const m = try countWords(alloc, "go Go GO Stop stop");
|
||||||
|
print("count: {d}\n", .{m.count()});
|
||||||
|
var iter = m.keyIterator();
|
||||||
|
while (iter.next()) |k| {
|
||||||
|
print("{s}: {d}\n", .{ k.*, m.get(k.*).? });
|
||||||
|
}
|
||||||
|
// print("{any}", .{m});
|
||||||
|
}
|
164
zig/word-count/test_word_count.zig
Normal file
164
zig/word-count/test_word_count.zig
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const countWords = @import("word_count.zig").countWords;
|
||||||
|
|
||||||
|
fn freeKeysAndDeinit(self: *std.StringHashMap(u32)) void {
|
||||||
|
var iter = self.keyIterator();
|
||||||
|
while (iter.next()) |key_ptr| {
|
||||||
|
self.allocator.free(key_ptr.*);
|
||||||
|
}
|
||||||
|
self.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
test "count one word" {
|
||||||
|
const s = "word";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 1), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("word"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "count one of each word" {
|
||||||
|
const s = "one of each";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 3), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("one"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("of"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("each"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "multiple occurrences of a word" {
|
||||||
|
const s = "one fish two fish red fish blue fish";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 5), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("one"));
|
||||||
|
try testing.expectEqual(@as(?u32, 4), map.get("fish"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("two"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("red"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("blue"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "handles cramped lists" {
|
||||||
|
const s = "one,two,three";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 3), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("one"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("two"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("three"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "handles expanded lists" {
|
||||||
|
const s = "one,\ntwo,\nthree";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 3), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("one"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("two"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("three"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ignore punctuation" {
|
||||||
|
const s = "car: carpet as java: javascript!!&@$%^&";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 5), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("car"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("carpet"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("as"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("java"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("javascript"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "include numbers" {
|
||||||
|
const s = "testing, 1, 2 testing";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 3), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 2), map.get("testing"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("1"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "normalize case" {
|
||||||
|
const s = "go Go GO Stop stop";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 2), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 3), map.get("go"));
|
||||||
|
try testing.expectEqual(@as(?u32, 2), map.get("stop"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "with apostrophes" {
|
||||||
|
const s = "'First: don't laugh. Then: don't cry. You're getting it.'";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 8), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("first"));
|
||||||
|
try testing.expectEqual(@as(?u32, 2), map.get("don't"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("laugh"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("then"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("cry"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("you're"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("getting"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("it"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "with quotations" {
|
||||||
|
const s = "Joe can't tell between 'large' and large.";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 6), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("joe"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("can't"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("tell"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("between"));
|
||||||
|
try testing.expectEqual(@as(?u32, 2), map.get("large"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("and"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "substrings from the beginning" {
|
||||||
|
const s = "Joe can't tell between app, apple and a.";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 8), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("joe"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("can't"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("tell"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("between"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("app"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("apple"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("and"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "multiple spaces not detected as a word" {
|
||||||
|
const s = " multiple whitespaces";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 2), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("multiple"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("whitespaces"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "alternating word separators not detected as a word" {
|
||||||
|
const s = ",\n,one,\n ,two \n 'three'";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 3), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("one"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("two"));
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("three"));
|
||||||
|
}
|
||||||
|
|
||||||
|
test "quotation for word with apostrophe" {
|
||||||
|
const s = "can, can't, 'can't'";
|
||||||
|
var map = try countWords(testing.allocator, s);
|
||||||
|
defer freeKeysAndDeinit(&map);
|
||||||
|
try testing.expectEqual(@as(u32, 2), map.count());
|
||||||
|
try testing.expectEqual(@as(?u32, 1), map.get("can"));
|
||||||
|
try testing.expectEqual(@as(?u32, 2), map.get("can't"));
|
||||||
|
}
|
74
zig/word-count/word_count.zig
Normal file
74
zig/word-count/word_count.zig
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
const HashMap = std.HashMap;
|
||||||
|
const ArrayList = std.ArrayList;
|
||||||
|
|
||||||
|
const StringHashMap = std.StringHashMap(u32);
|
||||||
|
/// Returns the counts of the words in `s`.
|
||||||
|
/// Caller owns the returned memory.
|
||||||
|
/// "That's the password: 'PASSWORD 123'!", cried the Special Agent.\nSo I fled.
|
||||||
|
pub fn countWords(allocator: mem.Allocator, s: []const u8) !StringHashMap {
|
||||||
|
var hashMap = StringHashMap.init(allocator);
|
||||||
|
try read_words(allocator, s, 0, null, &hashMap);
|
||||||
|
return hashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_words(allocator: mem.Allocator, s: []const u8, index: usize, currentWord: ?[]const u8, words: *StringHashMap) !void {
|
||||||
|
const next_idx = index + 1;
|
||||||
|
const isIntraWord = index < s.len and (isWordLetter(s[index]) or
|
||||||
|
(s[index] == '\'' and isBetweenLetters(s, index)));
|
||||||
|
|
||||||
|
if (!isIntraWord and currentWord != null) {
|
||||||
|
const l = currentWord.?.len;
|
||||||
|
var word = try ArrayList(u8).initCapacity(allocator, l);
|
||||||
|
for (currentWord.?, 0..) |n, i| {
|
||||||
|
try word.insert(i, toLowerCase(n));
|
||||||
|
}
|
||||||
|
const kword = try word.toOwnedSlice();
|
||||||
|
|
||||||
|
const count = words.get(kword);
|
||||||
|
|
||||||
|
try words.put(kword, (count orelse 0) + 1);
|
||||||
|
if (count != null) {
|
||||||
|
defer allocator.free(kword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index == s.len) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isIntraWord and currentWord == null) {
|
||||||
|
return read_words(allocator, s, next_idx, s[index..next_idx], words);
|
||||||
|
} else if (isIntraWord) {
|
||||||
|
return read_words(allocator, s, next_idx, growSubslice(s, currentWord.?), words);
|
||||||
|
} else {
|
||||||
|
return read_words(allocator, s, next_idx, null, words);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isBetweenLetters(s: []const u8, index: usize) bool {
|
||||||
|
return index > 0 and index < (s.len - 1) and isWordLetter(s[index - 1]) and isWordLetter(s[index + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isWordLetter(letter: u8) bool {
|
||||||
|
return (letter >= 'A' and letter <= 'Z') or (letter >= 'a' and letter <= 'z') or (letter >= '0' and letter <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
fn isUpperCase(letter: u8) bool {
|
||||||
|
return letter >= 'A' and letter <= 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
fn toLowerCase(letter: u8) u8 {
|
||||||
|
return if (isUpperCase(letter)) letter + 32 else letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn growSubslice(root: []const u8, child: []const u8) []const u8 {
|
||||||
|
const max_ptr = @intFromPtr(root.ptr) + root.len;
|
||||||
|
|
||||||
|
if (max_ptr > (@intFromPtr(child.ptr) + child.len)) {
|
||||||
|
const start = @intFromPtr(child.ptr) - @intFromPtr(root.ptr);
|
||||||
|
const end = child.len + start + 1;
|
||||||
|
return root[start..end];
|
||||||
|
} else {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue