mirror of
https://codeberg.org/andyscott/exercism.git
synced 2024-12-21 22:33:11 -05:00
Zig: completed Hamming and Binary Search
This commit is contained in:
parent
9b61bc3783
commit
563d208eef
12 changed files with 423 additions and 0 deletions
19
zig/binary-search/.exercism/config.json
Normal file
19
zig/binary-search/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"massivelivefun"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"binary_search.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_binary_search.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Implement a binary search algorithm.",
|
||||||
|
"source": "Wikipedia",
|
||||||
|
"source_url": "https://en.wikipedia.org/wiki/Binary_search_algorithm"
|
||||||
|
}
|
1
zig/binary-search/.exercism/metadata.json
Normal file
1
zig/binary-search/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"binary-search","id":"9eaef7e9f3694a63b8f1aabd8a6a6a47","url":"https://exercism.org/tracks/zig/exercises/binary-search","handle":"Chomp1295","is_requester":true,"auto_approve":false}
|
53
zig/binary-search/HELP.md
Normal file
53
zig/binary-search/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 binary_search.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 Guide][zig-guide] 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-guide]: https://zig.guide/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
58
zig/binary-search/README.md
Normal file
58
zig/binary-search/README.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# Binary Search
|
||||||
|
|
||||||
|
Welcome to Binary Search on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
You have stumbled upon a group of mathematicians who are also singer-songwriters.
|
||||||
|
They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers (like [0][zero] or [73][seventy-three] or [6174][kaprekars-constant]).
|
||||||
|
|
||||||
|
You are curious to hear the song for your favorite number, but with so many songs to wade through, finding the right song could take a while.
|
||||||
|
Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about.
|
||||||
|
|
||||||
|
You realize that you can use a binary search algorithm to quickly find a song given the title.
|
||||||
|
|
||||||
|
[zero]: https://en.wikipedia.org/wiki/0
|
||||||
|
[seventy-three]: https://en.wikipedia.org/wiki/73_(number)
|
||||||
|
[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number)
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Your task is to implement a binary search algorithm.
|
||||||
|
|
||||||
|
A binary search algorithm finds an item in a list by repeatedly splitting it in half, only keeping the half which contains the item we're looking for.
|
||||||
|
It allows us to quickly narrow down the possible locations of our item until we find it, or until we've eliminated all possible locations.
|
||||||
|
|
||||||
|
~~~~exercism/caution
|
||||||
|
Binary search only works when a list has been sorted.
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
The algorithm looks like this:
|
||||||
|
|
||||||
|
- Find the middle element of a _sorted_ list and compare it with the item we're looking for.
|
||||||
|
- If the middle element is our item, then we're done!
|
||||||
|
- If the middle element is greater than our item, we can eliminate that element and all the elements **after** it.
|
||||||
|
- If the middle element is less than our item, we can eliminate that element and all the elements **before** it.
|
||||||
|
- If every element of the list has been eliminated then the item is not in the list.
|
||||||
|
- Otherwise, repeat the process on the part of the list that has not been eliminated.
|
||||||
|
|
||||||
|
Here's an example:
|
||||||
|
|
||||||
|
Let's say we're looking for the number 23 in the following sorted list: `[4, 8, 12, 16, 23, 28, 32]`.
|
||||||
|
|
||||||
|
- We start by comparing 23 with the middle element, 16.
|
||||||
|
- Since 23 is greater than 16, we can eliminate the left half of the list, leaving us with `[23, 28, 32]`.
|
||||||
|
- We then compare 23 with the new middle element, 28.
|
||||||
|
- Since 23 is less than 28, we can eliminate the right half of the list: `[23]`.
|
||||||
|
- We've found our item.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @massivelivefun
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Wikipedia - https://en.wikipedia.org/wiki/Binary_search_algorithm
|
21
zig/binary-search/binary_search.zig
Normal file
21
zig/binary-search/binary_search.zig
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Take a look at the tests, you might have to change the function arguments
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn binarySearch(comptime T: type, target: T, array: []const T) ?usize {
|
||||||
|
var start: usize = 0;
|
||||||
|
var end: usize = array.len;
|
||||||
|
|
||||||
|
while (start < end) {
|
||||||
|
const mid = start + (end - start) / 2;
|
||||||
|
|
||||||
|
if (array[mid] == target) return mid;
|
||||||
|
|
||||||
|
if (array[mid] < target) {
|
||||||
|
start = mid + 1;
|
||||||
|
} else {
|
||||||
|
end = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
82
zig/binary-search/test_binary_search.zig
Normal file
82
zig/binary-search/test_binary_search.zig
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const binary_search = @import("binary_search.zig");
|
||||||
|
const binarySearch = binary_search.binarySearch;
|
||||||
|
|
||||||
|
test "finds a value in an array with one element" {
|
||||||
|
const expected: ?usize = 0;
|
||||||
|
const array = [_]i4{6};
|
||||||
|
const actual = binarySearch(i4, 6, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "finds a value in the middle of an array" {
|
||||||
|
const expected: ?usize = 3;
|
||||||
|
const array = [_]u4{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(u4, 6, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "finds a value at the beginning of an array" {
|
||||||
|
const expected: ?usize = 0;
|
||||||
|
const array = [_]i8{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(i8, 1, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "finds a value at the end of an array" {
|
||||||
|
const expected: ?usize = 6;
|
||||||
|
const array = [_]u8{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(u8, 11, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "finds a value in an array of odd length" {
|
||||||
|
const expected: ?usize = 5;
|
||||||
|
const array = [_]i16{ 1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634 };
|
||||||
|
const actual = binarySearch(i16, 21, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "finds a value in an array of even length" {
|
||||||
|
const expected: ?usize = 5;
|
||||||
|
const array = [_]u16{ 1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377 };
|
||||||
|
const actual = binarySearch(u16, 21, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "identifies that a value is not included in the array" {
|
||||||
|
const expected: ?usize = null;
|
||||||
|
const array = [_]i32{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(i32, 7, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "a value smaller than the array's smallest value is not found" {
|
||||||
|
const expected: ?usize = null;
|
||||||
|
const array = [_]u32{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(u32, 0, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "a value larger than the array's largest value is not found" {
|
||||||
|
const expected: ?usize = null;
|
||||||
|
const array = [_]i64{ 1, 3, 4, 6, 8, 9, 11 };
|
||||||
|
const actual = binarySearch(i64, 13, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "nothing is found in an empty array" {
|
||||||
|
const expected: ?usize = null;
|
||||||
|
const array = [_]u64{};
|
||||||
|
const actual = binarySearch(u64, 13, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "nothing is found when the left and right bounds cross" {
|
||||||
|
const expected: ?usize = null;
|
||||||
|
const array = [_]isize{ 1, 2 };
|
||||||
|
const actual = binarySearch(isize, 13, &array);
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
19
zig/hamming/.exercism/config.json
Normal file
19
zig/hamming/.exercism/config.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"massivelivefun"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"hamming.zig"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test_hamming.zig"
|
||||||
|
],
|
||||||
|
"example": [
|
||||||
|
".meta/example.zig"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"blurb": "Calculate the Hamming difference between two DNA strands.",
|
||||||
|
"source": "The Calculating Point Mutations problem at Rosalind",
|
||||||
|
"source_url": "https://rosalind.info/problems/hamm/"
|
||||||
|
}
|
1
zig/hamming/.exercism/metadata.json
Normal file
1
zig/hamming/.exercism/metadata.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"track":"zig","exercise":"hamming","id":"0b3050ac7b884260a12dc74776f50561","url":"https://exercism.org/tracks/zig/exercises/hamming","handle":"Chomp1295","is_requester":true,"auto_approve":false}
|
53
zig/hamming/HELP.md
Normal file
53
zig/hamming/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 hamming.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 Guide][zig-guide] 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-guide]: https://zig.guide/
|
||||||
|
[ziglings]: https://codeberg.org/ziglings/exercises
|
42
zig/hamming/README.md
Normal file
42
zig/hamming/README.md
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# Hamming
|
||||||
|
|
||||||
|
Welcome to Hamming on Exercism's Zig Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Calculate the Hamming Distance between two DNA strands.
|
||||||
|
|
||||||
|
Your body is made up of cells that contain DNA.
|
||||||
|
Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells.
|
||||||
|
In fact, the average human body experiences about 10 quadrillion cell divisions in a lifetime!
|
||||||
|
|
||||||
|
When cells divide, their DNA replicates too.
|
||||||
|
Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information.
|
||||||
|
If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred.
|
||||||
|
This is known as the "Hamming Distance".
|
||||||
|
|
||||||
|
We read DNA using the letters C,A,G and T.
|
||||||
|
Two strands might look like this:
|
||||||
|
|
||||||
|
GAGCCTACTAACGGGAT
|
||||||
|
CATCGTAATGACGGCCT
|
||||||
|
^ ^ ^ ^ ^ ^^
|
||||||
|
|
||||||
|
They have 7 differences, and therefore the Hamming Distance is 7.
|
||||||
|
|
||||||
|
The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :)
|
||||||
|
|
||||||
|
## Implementation notes
|
||||||
|
|
||||||
|
The Hamming distance is only defined for sequences of equal length, so an attempt to calculate it between sequences of different lengths should not work.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @massivelivefun
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
The Calculating Point Mutations problem at Rosalind - https://rosalind.info/problems/hamm/
|
15
zig/hamming/hamming.zig
Normal file
15
zig/hamming/hamming.zig
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
pub const DnaError = error{
|
||||||
|
EmptyDnaStrands,
|
||||||
|
UnequalDnaStrands,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn compute(first: []const u8, second: []const u8) DnaError!usize {
|
||||||
|
if (first.len == 0 or second.len == 0) return DnaError.EmptyDnaStrands;
|
||||||
|
if (first.len != second.len) return DnaError.UnequalDnaStrands;
|
||||||
|
|
||||||
|
var count: usize = 0;
|
||||||
|
for (first, second) |i, j| {
|
||||||
|
if (i != j) count += 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
59
zig/hamming/test_hamming.zig
Normal file
59
zig/hamming/test_hamming.zig
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const testing = std.testing;
|
||||||
|
|
||||||
|
const hamming = @import("hamming.zig");
|
||||||
|
const DnaError = hamming.DnaError;
|
||||||
|
|
||||||
|
test "empty strands" {
|
||||||
|
const expected = DnaError.EmptyDnaStrands;
|
||||||
|
const actual = hamming.compute("", "");
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "single letter identical strands" {
|
||||||
|
const expected: usize = 0;
|
||||||
|
const actual = try hamming.compute("A", "A");
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "single letter different strands" {
|
||||||
|
const expected: usize = 1;
|
||||||
|
const actual = try hamming.compute("G", "T");
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "long identical strands" {
|
||||||
|
const expected: usize = 0;
|
||||||
|
const actual = try hamming.compute("GGACTGAAATCTG", "GGACTGAAATCTG");
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "long different strands" {
|
||||||
|
const expected: usize = 9;
|
||||||
|
const actual = try hamming.compute("GGACGGATTCTG", "AGGACGGATTCT");
|
||||||
|
try testing.expectEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "disallow first strand longer" {
|
||||||
|
const expected = DnaError.UnequalDnaStrands;
|
||||||
|
const actual = hamming.compute("AATG", "AAA");
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "disallow second strand longer" {
|
||||||
|
const expected = DnaError.UnequalDnaStrands;
|
||||||
|
const actual = hamming.compute("ATA", "AGTG");
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "disallow left empty strand" {
|
||||||
|
const expected = DnaError.EmptyDnaStrands;
|
||||||
|
const actual = hamming.compute("", "G");
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "disallow right empty strand" {
|
||||||
|
const expected = DnaError.EmptyDnaStrands;
|
||||||
|
const actual = hamming.compute("G", "");
|
||||||
|
try testing.expectError(expected, actual);
|
||||||
|
}
|
Loading…
Reference in a new issue