From 40ffc9faa3199fc87a022820bb0e62cf9044a616 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Sat, 14 Sep 2024 11:24:39 -0400 Subject: [PATCH] Zig: completed Rotational Cipher --- zig/rotational-cipher/.exercism/config.json | 19 +++++ zig/rotational-cipher/.exercism/metadata.json | 1 + zig/rotational-cipher/HELP.md | 53 +++++++++++++ zig/rotational-cipher/README.md | 44 +++++++++++ zig/rotational-cipher/rotational_cipher.zig | 16 ++++ .../test_rotational_cipher.zig | 74 +++++++++++++++++++ 6 files changed, 207 insertions(+) create mode 100644 zig/rotational-cipher/.exercism/config.json create mode 100644 zig/rotational-cipher/.exercism/metadata.json create mode 100644 zig/rotational-cipher/HELP.md create mode 100644 zig/rotational-cipher/README.md create mode 100644 zig/rotational-cipher/rotational_cipher.zig create mode 100644 zig/rotational-cipher/test_rotational_cipher.zig diff --git a/zig/rotational-cipher/.exercism/config.json b/zig/rotational-cipher/.exercism/config.json new file mode 100644 index 0000000..fdbdc42 --- /dev/null +++ b/zig/rotational-cipher/.exercism/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "rotational_cipher.zig" + ], + "test": [ + "test_rotational_cipher.zig" + ], + "example": [ + ".meta/example.zig" + ] + }, + "blurb": "Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Caesar_cipher" +} diff --git a/zig/rotational-cipher/.exercism/metadata.json b/zig/rotational-cipher/.exercism/metadata.json new file mode 100644 index 0000000..673c83b --- /dev/null +++ b/zig/rotational-cipher/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"zig","exercise":"rotational-cipher","id":"febb4070e9eb44dabea37232f64c12c6","url":"https://exercism.org/tracks/zig/exercises/rotational-cipher","handle":"Chomp1295","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/zig/rotational-cipher/HELP.md b/zig/rotational-cipher/HELP.md new file mode 100644 index 0000000..fac901f --- /dev/null +++ b/zig/rotational-cipher/HELP.md @@ -0,0 +1,53 @@ +# Help + +## Running the tests + +Write your code in `.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 rotational_cipher.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 \ No newline at end of file diff --git a/zig/rotational-cipher/README.md b/zig/rotational-cipher/README.md new file mode 100644 index 0000000..32569ea --- /dev/null +++ b/zig/rotational-cipher/README.md @@ -0,0 +1,44 @@ +# Rotational Cipher + +Welcome to Rotational Cipher on Exercism's Zig Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Create an implementation of the rotational cipher, also sometimes called the Caesar cipher. + +The Caesar cipher is a simple shift cipher that relies on transposing all the letters in the alphabet using an integer key between `0` and `26`. +Using a key of `0` or `26` will always yield the same output due to modular arithmetic. +The letter is shifted for as many values as the value of the key. + +The general notation for rotational ciphers is `ROT + `. +The most commonly used rotational cipher is `ROT13`. + +A `ROT13` on the Latin alphabet would be as follows: + +```text +Plain: abcdefghijklmnopqrstuvwxyz +Cipher: nopqrstuvwxyzabcdefghijklm +``` + +It is stronger than the Atbash cipher because it has 27 possible keys, and 25 usable keys. + +Ciphertext is written out in the same formatting as the input including spaces and punctuation. + +## Examples + +- ROT5 `omg` gives `trl` +- ROT0 `c` gives `c` +- ROT26 `Cool` gives `Cool` +- ROT13 `The quick brown fox jumps over the lazy dog.` gives `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` +- ROT13 `Gur dhvpx oebja sbk whzcf bire gur ynml qbt.` gives `The quick brown fox jumps over the lazy dog.` + +## Source + +### Created by + +- @keiravillekode + +### Based on + +Wikipedia - https://en.wikipedia.org/wiki/Caesar_cipher \ No newline at end of file diff --git a/zig/rotational-cipher/rotational_cipher.zig b/zig/rotational-cipher/rotational_cipher.zig new file mode 100644 index 0000000..f534e29 --- /dev/null +++ b/zig/rotational-cipher/rotational_cipher.zig @@ -0,0 +1,16 @@ +const std = @import("std"); +const mem = std.mem; + +pub fn rotate(allocator: mem.Allocator, text: []const u8, shiftKey: u5) mem.Allocator.Error![]u8 { + const result = try allocator.alloc(u8, text.len); + + for (text, 0..) |c, i| { + result[i] = switch(c) { + 'a'...'z' => (c - 'a' + shiftKey) % 26 + 'a', + 'A'...'Z' => (c - 'A' + shiftKey) % 26 + 'A', + else => c, + }; + } + + return result; +} diff --git a/zig/rotational-cipher/test_rotational_cipher.zig b/zig/rotational-cipher/test_rotational_cipher.zig new file mode 100644 index 0000000..05dd284 --- /dev/null +++ b/zig/rotational-cipher/test_rotational_cipher.zig @@ -0,0 +1,74 @@ +const std = @import("std"); +const testing = std.testing; + +const rotational_cipher = @import("rotational_cipher.zig"); + +test "rotate a by 0, same output as input" { + const expected: []const u8 = "a"; + const actual = try rotational_cipher.rotate(testing.allocator, "a", 0); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate a by 1" { + const expected: []const u8 = "b"; + const actual = try rotational_cipher.rotate(testing.allocator, "a", 1); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate a by 26, same output as input" { + const expected: []const u8 = "a"; + const actual = try rotational_cipher.rotate(testing.allocator, "a", 26); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate m by 13" { + const expected: []const u8 = "z"; + const actual = try rotational_cipher.rotate(testing.allocator, "m", 13); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate n by 13 with wrap around alphabet" { + const expected: []const u8 = "a"; + const actual = try rotational_cipher.rotate(testing.allocator, "n", 13); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate capital letters" { + const expected: []const u8 = "TRL"; + const actual = try rotational_cipher.rotate(testing.allocator, "OMG", 5); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate spaces" { + const expected: []const u8 = "T R L"; + const actual = try rotational_cipher.rotate(testing.allocator, "O M G", 5); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate numbers" { + const expected: []const u8 = "Xiwxmrk 1 2 3 xiwxmrk"; + const actual = try rotational_cipher.rotate(testing.allocator, "Testing 1 2 3 testing", 4); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate punctuation" { + const expected: []const u8 = "Gzo'n zvo, Bmviyhv!"; + const actual = try rotational_cipher.rotate(testing.allocator, "Let's eat, Grandma!", 21); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +} + +test "rotate all letters" { + const expected: []const u8 = "Gur dhvpx oebja sbk whzcf bire gur ynml qbt."; + const actual = try rotational_cipher.rotate(testing.allocator, "The quick brown fox jumps over the lazy dog.", 13); + defer testing.allocator.free(actual); + try testing.expectEqualStrings(expected, actual); +}