Skip to content

Commit ef234e8

Browse files
authored
Merge pull request #694 from adimasuhid/features/implement-rotational-cipher
rotational-cipher: Implement Rotational Cipher
2 parents ed0d6c8 + 013f1fd commit ef234e8

File tree

5 files changed

+153
-0
lines changed

5 files changed

+153
-0
lines changed

config.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,19 @@
859859
"Mathematics"
860860
]
861861
},
862+
{
863+
"uuid": "af5ccf14-eff2-4dc6-b1db-e209cddca62a",
864+
"slug": "rotational-cipher",
865+
"core": false,
866+
"unlocked_by": null,
867+
"difficulty": 1,
868+
"topics": [
869+
"Control-flow (conditionals)",
870+
"Control-flow (loops)",
871+
"Logic",
872+
"Strings"
873+
]
874+
},
862875
{
863876
"uuid": "cae4e000-3aac-41f7-b727-f9cce12d058d",
864877
"slug": "octal",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
1
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
require 'generator/exercise_case'
2+
3+
class RotationalCipherCase < Generator::ExerciseCase
4+
5+
def workload
6+
assert_equal { %Q[RotationalCipher.rotate("#{text}", #{shiftKey})] }
7+
end
8+
9+
end
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module BookKeeping
2+
VERSION = 1
3+
end
4+
5+
class RotationalCipher
6+
SMALL_LETTERS_RANGE = (97..122)
7+
BIG_LETTERS_RANGE = (65..90)
8+
ROTATION_MODIFIER = 1
9+
10+
attr_reader :text
11+
12+
def initialize(text, key)
13+
@text = text
14+
@shift_key = key
15+
end
16+
17+
def self.rotate(text, key)
18+
new(text, key).rotate
19+
end
20+
21+
def rotate
22+
text.split('').map { |char| shift_char(char) }.join
23+
end
24+
25+
private
26+
27+
def shift_char(char)
28+
shift_ascii(char.ord).chr
29+
end
30+
31+
def shift_key
32+
@shift_key % 26
33+
end
34+
35+
def shift_ascii(char_ascii)
36+
case char_ascii
37+
when SMALL_LETTERS_RANGE
38+
shift_within(char_ascii, SMALL_LETTERS_RANGE.min, SMALL_LETTERS_RANGE.max)
39+
when BIG_LETTERS_RANGE
40+
shift_within(char_ascii, BIG_LETTERS_RANGE.min, BIG_LETTERS_RANGE.max)
41+
else
42+
char_ascii
43+
end
44+
end
45+
46+
def shift_within(char_ascii, lower_limit, upper_limit)
47+
shifted_ascii = char_ascii + shift_key
48+
49+
return shifted_ascii if shifted_ascii <= upper_limit
50+
51+
lower_limit + (shifted_ascii - upper_limit - ROTATION_MODIFIER)
52+
end
53+
end
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
require 'minitest/autorun'
2+
require_relative 'rotational_cipher'
3+
4+
# Common test data version: 1.1.0 9c658d1
5+
class RotationalCipherTest < Minitest::Test
6+
def test_rotate_a_by_0_same_output_as_input
7+
# skip
8+
assert_equal "a", RotationalCipher.rotate("a", 0)
9+
end
10+
11+
def test_rotate_a_by_1
12+
skip
13+
assert_equal "b", RotationalCipher.rotate("a", 1)
14+
end
15+
16+
def test_rotate_a_by_26_same_output_as_input
17+
skip
18+
assert_equal "a", RotationalCipher.rotate("a", 26)
19+
end
20+
21+
def test_rotate_m_by_13
22+
skip
23+
assert_equal "z", RotationalCipher.rotate("m", 13)
24+
end
25+
26+
def test_rotate_n_by_13_with_wrap_around_alphabet
27+
skip
28+
assert_equal "a", RotationalCipher.rotate("n", 13)
29+
end
30+
31+
def test_rotate_capital_letters
32+
skip
33+
assert_equal "TRL", RotationalCipher.rotate("OMG", 5)
34+
end
35+
36+
def test_rotate_spaces
37+
skip
38+
assert_equal "T R L", RotationalCipher.rotate("O M G", 5)
39+
end
40+
41+
def test_rotate_numbers
42+
skip
43+
assert_equal "Xiwxmrk 1 2 3 xiwxmrk", RotationalCipher.rotate("Testing 1 2 3 testing", 4)
44+
end
45+
46+
def test_rotate_punctuation
47+
skip
48+
assert_equal "Gzo'n zvo, Bmviyhv!", RotationalCipher.rotate("Let's eat, Grandma!", 21)
49+
end
50+
51+
def test_rotate_all_letters
52+
skip
53+
assert_equal "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", RotationalCipher.rotate("The quick brown fox jumps over the lazy dog.", 13)
54+
end
55+
56+
# Problems in exercism evolve over time, as we find better ways to ask
57+
# questions.
58+
# The version number refers to the version of the problem you solved,
59+
# not your solution.
60+
#
61+
# Define a constant named VERSION inside of the top level BookKeeping
62+
# module, which may be placed near the end of your file.
63+
#
64+
# In your file, it will look like this:
65+
#
66+
# module BookKeeping
67+
# VERSION = 1 # Where the version number matches the one in the test.
68+
# end
69+
#
70+
# If you are curious, read more about constants on RubyDoc:
71+
# http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html
72+
73+
def test_bookkeeping
74+
skip
75+
assert_equal 1, BookKeeping::VERSION
76+
end
77+
end

0 commit comments

Comments
 (0)