~telemachus/Exercism

5475d33e45abf1e157884b7a7ade4336c1e9cfab — Peter Aronoff 5 months ago 3928855
Rotational cipher
A go/rotational-cipher/.exercism/config.json => go/rotational-cipher/.exercism/config.json +27 -0
@@ 0,0 1,27 @@
{
  "blurb": "Create an implementation of the rotational cipher, also sometimes called the Caesar cipher.",
  "authors": [
    "magic003"
  ],
  "contributors": [
    "bitfield",
    "ekingery",
    "ferhatelmas",
    "hilary",
    "leenipper",
    "sebito91"
  ],
  "files": {
    "solution": [
      "rotational_cipher.go"
    ],
    "test": [
      "rotational_cipher_test.go"
    ],
    "example": [
      ".meta/example.go"
    ]
  },
  "source": "Wikipedia",
  "source_url": "https://en.wikipedia.org/wiki/Caesar_cipher"
}

A go/rotational-cipher/.exercism/metadata.json => go/rotational-cipher/.exercism/metadata.json +1 -0
@@ 0,0 1,1 @@
{"track":"go","exercise":"rotational-cipher","id":"92ea268b879143a598b0732cfdf534ba","url":"https://exercism.org/tracks/go/exercises/rotational-cipher","handle":"telemachus","is_requester":true,"auto_approve":false}
\ No newline at end of file

A go/rotational-cipher/HELP.md => go/rotational-cipher/HELP.md +40 -0
@@ 0,0 1,40 @@
# Help

## Running the tests

To run the tests run the command `go test` from within the exercise directory.

If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:

    go test -v --bench . --benchmem

Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.

## Submitting your solution

You can submit your solution using the `exercism submit rotational_cipher.go` 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 [Go track's documentation](https://exercism.org/docs/tracks/go)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)

Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.

To get help if you're having trouble, you can use one of the following resources:

- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
\ No newline at end of file

A go/rotational-cipher/README.md => go/rotational-cipher/README.md +55 -0
@@ 0,0 1,55 @@
# Rotational Cipher

Welcome to Rotational Cipher on Exercism's Go 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 + <key>`.
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

- @magic003

### Contributed to by

- @bitfield
- @ekingery
- @ferhatelmas
- @hilary
- @leenipper
- @sebito91

### Based on

Wikipedia - https://en.wikipedia.org/wiki/Caesar_cipher
\ No newline at end of file

A go/rotational-cipher/go.mod => go/rotational-cipher/go.mod +3 -0
@@ 0,0 1,3 @@
module rotationalcipher

go 1.16

A go/rotational-cipher/rotational_cipher.go => go/rotational-cipher/rotational_cipher.go +20 -0
@@ 0,0 1,20 @@
package rotationalcipher

import "strings"

func RotationalCipher(plain string, shiftKey int) string {
	var rot strings.Builder
	shiftByte := byte(shiftKey)
	// Assume ASCII input.
	for _, c := range []byte(plain) {
		switch {
		case c >= 'a' && c <= 'z':
			rot.WriteByte(((c - 'a' + shiftByte) % 26) + 'a')
		case c >= 'A' && c <= 'Z':
			rot.WriteByte(((c - 'A' + shiftByte) % 26) + 'A')
		default:
			rot.WriteByte(c)
		}
	}
	return rot.String()
}

A go/rotational-cipher/rotational_cipher_test.go => go/rotational-cipher/rotational_cipher_test.go +89 -0
@@ 0,0 1,89 @@
package rotationalcipher

import (
	"testing"
)

var testCases = []struct {
	description   string
	inputPlain    string
	inputShiftKey int
	expected      string
}{
	{
		description:   "rotate a by 0, same output as input",
		inputPlain:    "a",
		inputShiftKey: 0,
		expected:      "a",
	},
	{
		description:   "rotate a by 1",
		inputPlain:    "a",
		inputShiftKey: 1,
		expected:      "b",
	},
	{
		description:   "rotate a by 26, same output as input",
		inputPlain:    "a",
		inputShiftKey: 26,
		expected:      "a",
	},
	{
		description:   "rotate n by 13 with wrap around alphabet",
		inputPlain:    "n",
		inputShiftKey: 13,
		expected:      "a",
	},
	{
		description:   "rotate capital letters",
		inputPlain:    "OMG",
		inputShiftKey: 5,
		expected:      "TRL",
	},
	{
		description:   "rotate spaces",
		inputPlain:    "O M G",
		inputShiftKey: 5,
		expected:      "T R L",
	},
	{
		description:   "rotate numbers",
		inputPlain:    "Testing 1 2 3 testing",
		inputShiftKey: 4,
		expected:      "Xiwxmrk 1 2 3 xiwxmrk",
	},
	{
		description:   "rotate punctuation",
		inputPlain:    "Let's eat, Grandma!",
		inputShiftKey: 21,
		expected:      "Gzo'n zvo, Bmviyhv!",
	},
	{
		description:   "rotate all letters",
		inputPlain:    "The quick brown fox jumps over the lazy dog.",
		inputShiftKey: 13,
		expected:      "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.",
	},
}

func TestRotationalCipher(t *testing.T) {
	for _, testCase := range testCases {
		cipher := RotationalCipher(testCase.inputPlain, testCase.inputShiftKey)
		if cipher != testCase.expected {
			t.Fatalf("FAIL: %s\n\tRotationalCipher(%s, %d)\nexpected: %s, \ngot:      %s",
				testCase.description, testCase.inputPlain, testCase.inputShiftKey, testCase.expected, cipher)
		}
		t.Logf("PASS: %s", testCase.description)
	}
}

func BenchmarkRotationalCipher(b *testing.B) {
	if testing.Short() {
		b.Skip("skipping benchmark in short mode.")
	}
	for i := 0; i < b.N; i++ {
		for _, testCase := range testCases {
			RotationalCipher(testCase.inputPlain, testCase.inputShiftKey)
		}
	}
}