ruby_quiz_1 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +1 -0
- data/bin/ruby_quiz_1 +20 -0
- data/lib/ruby_quiz_1/card.rb +16 -0
- data/lib/ruby_quiz_1/character_group.rb +73 -0
- data/lib/ruby_quiz_1/deck.rb +20 -0
- data/lib/ruby_quiz_1/decks/standard_deck.rb +22 -0
- data/lib/ruby_quiz_1/joker.rb +9 -0
- data/lib/ruby_quiz_1/message.rb +40 -0
- data/lib/ruby_quiz_1/solitaire.rb +84 -0
- data/lib/ruby_quiz_1/suit.rb +11 -0
- data/lib/ruby_quiz_1/version.rb +3 -0
- data/lib/ruby_quiz_1.rb +13 -0
- data/ruby_quiz_1.gemspec +29 -0
- data/spec/lib/ruby_quiz_1/card_spec.rb +26 -0
- data/spec/lib/ruby_quiz_1/character_group_spec.rb +91 -0
- data/spec/lib/ruby_quiz_1/deck_spec.rb +17 -0
- data/spec/lib/ruby_quiz_1/decks/standard_deck_spec.rb +9 -0
- data/spec/lib/ruby_quiz_1/joker_spec.rb +9 -0
- data/spec/lib/ruby_quiz_1/message_spec.rb +57 -0
- data/spec/lib/ruby_quiz_1/solitaire_spec.rb +16 -0
- data/spec/lib/ruby_quiz_1/suit_spec.rb +25 -0
- data/spec/spec_helper.rb +3 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ac7532fb4c8411d3a869a05e2beabc53769bfcdf
|
4
|
+
data.tar.gz: 2e834133286ca532cb27485d4d9de654a75ed494
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 09708d3b6b755eeec103af2ec3741d7b8ad5728567b9a3c3a260c74ebee631965ea11a5d76614000f1695f94e6b59814ef9dfe9f3d6580d8caec62e0fa6e5605
|
7
|
+
data.tar.gz: c3dbe0c9e1f6c33eb8e4a065b0fb2fa6facc2a2809fa51813bd44ea90cdfb9abbaeac5b9c078e7126fc47944d61a4ce55b27f3a72164db086b1ff304b3c334e6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Sean Devine
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Ruby Quiz #1 Solution
|
2
|
+
|
3
|
+
A solution to the [first ever Ruby quiz](http://rubyquiz.com/quiz1.html).
|
4
|
+
|
5
|
+
The command line utility encrypts and decrypts messages using the [Solitaire Cipher](http://www.schneier.com/solitaire.html)
|
6
|
+
|
7
|
+
```bash
|
8
|
+
gem install 'ruby_quiz_1'
|
9
|
+
```
|
10
|
+
|
11
|
+
```bash
|
12
|
+
barelyknown$ ruby_quiz_1 encrypt 'Welcome to Ruby quiz'
|
13
|
+
ABVAW LWZSY OORYK DUPVH
|
14
|
+
barelyknown$ ruby_quiz_1 decrypt 'ABVAW LWZSY OORYK DUPVH'
|
15
|
+
WELCO METOR UBYQU IZXXX
|
16
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/ruby_quiz_1
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
require_relative "../lib/ruby_quiz_1"
|
4
|
+
|
5
|
+
module RubyQuiz1
|
6
|
+
class SolitaireCLI < Thor
|
7
|
+
|
8
|
+
desc "encrypt MESSAGE", "encrypt a message"
|
9
|
+
def encrypt(message)
|
10
|
+
puts Message.new(message).encrypt
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "decrypt MESSAGE", "decrypt a message"
|
14
|
+
def decrypt(message)
|
15
|
+
puts Message.new(message).decrypt
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
SolitaireCLI.start(ARGV)
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
class Card
|
3
|
+
|
4
|
+
attr_reader :value, :suit
|
5
|
+
|
6
|
+
def initialize(value, suit)
|
7
|
+
raise ArgumentError unless (1..13).to_a.include? value
|
8
|
+
@value, @suit = value, suit
|
9
|
+
end
|
10
|
+
|
11
|
+
def total_value
|
12
|
+
value + suit.value
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
class CharacterGroup
|
3
|
+
|
4
|
+
def initialize(value, solitaire=nil)
|
5
|
+
raise ArgumentError unless String(value) =~ /\A[A-Z]{1,5}\z/
|
6
|
+
@value = String(value)
|
7
|
+
@keystream = generate_keystream(solitaire) if solitaire
|
8
|
+
end
|
9
|
+
|
10
|
+
def characters
|
11
|
+
pad(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def numbers
|
15
|
+
@numbers ||= characters.chars.collect do |c|
|
16
|
+
("A".."Z").to_a.index(c) + 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def encrypted
|
21
|
+
return unless keystream
|
22
|
+
convert_to_characters(encrypted_numbers)
|
23
|
+
end
|
24
|
+
|
25
|
+
def decrypted
|
26
|
+
return unless keystream
|
27
|
+
convert_to_characters(decrypted_numbers)
|
28
|
+
end
|
29
|
+
|
30
|
+
def ==(other)
|
31
|
+
characters == other.characters
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def value
|
37
|
+
@value
|
38
|
+
end
|
39
|
+
|
40
|
+
def pad(value)
|
41
|
+
value + "X" * (5 - value.length)
|
42
|
+
end
|
43
|
+
|
44
|
+
def keystream
|
45
|
+
@keystream
|
46
|
+
end
|
47
|
+
|
48
|
+
def generate_keystream(solitaire)
|
49
|
+
self.class.new(characters.chars.collect { |l| solitaire.next_key }.join)
|
50
|
+
end
|
51
|
+
|
52
|
+
def encrypted_numbers
|
53
|
+
numbers.collect.with_index do |n, i|
|
54
|
+
e = n + keystream.numbers[i]
|
55
|
+
e -= 26 if e > 26
|
56
|
+
e
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def decrypted_numbers
|
61
|
+
numbers.collect.with_index do |n, i|
|
62
|
+
k = keystream.numbers[i]
|
63
|
+
n += 26 if n <= k
|
64
|
+
n - k
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def convert_to_characters(numbers)
|
69
|
+
numbers.collect { |n| ("A".."Z").to_a[n - 1] }.join
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
class StandardDeck < Deck
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
add_cards
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def add_cards
|
12
|
+
{club: 0, diamond: 13, heart: 26, spade: 39}.each do |suit_name, suit_value|
|
13
|
+
suit = Suit.new(suit_name, suit_value)
|
14
|
+
(1..13).each do |card_value|
|
15
|
+
cards << Card.new(card_value, suit)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
2.times { cards << Joker.new }
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
class Message
|
3
|
+
|
4
|
+
def initialize(value, solitaire=Solitaire.new(StandardDeck.new))
|
5
|
+
@value = value
|
6
|
+
@solitaire = solitaire
|
7
|
+
end
|
8
|
+
|
9
|
+
def encrypt
|
10
|
+
character_groups.collect(&:encrypted).join(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
def decrypt
|
14
|
+
character_groups.collect(&:decrypted).join(" ")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def value
|
20
|
+
@value
|
21
|
+
end
|
22
|
+
|
23
|
+
def stripped_value
|
24
|
+
value.upcase.gsub(/[^A-Z]/,"")
|
25
|
+
end
|
26
|
+
|
27
|
+
def solitaire
|
28
|
+
@solitaire
|
29
|
+
end
|
30
|
+
|
31
|
+
def character_groups
|
32
|
+
@character_groups ||= begin
|
33
|
+
stripped_value.chars.each_slice(5).collect do |character_group_value|
|
34
|
+
CharacterGroup.new character_group_value.join, solitaire
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
class Solitaire
|
3
|
+
|
4
|
+
attr_reader :deck
|
5
|
+
|
6
|
+
def initialize(deck)
|
7
|
+
@deck = deck
|
8
|
+
jokers = deck.select { |c| c.is_a?(Joker) }
|
9
|
+
raise ArgumentError, "#{jokers.size} jokers in the deck but 2 required" unless jokers.size == 2
|
10
|
+
@joker_a, @joker_b = jokers
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def next_key
|
15
|
+
key = nil
|
16
|
+
until key
|
17
|
+
move_card(joker_a, 1)
|
18
|
+
move_card(joker_b, 2)
|
19
|
+
triple_cut
|
20
|
+
count_cut
|
21
|
+
key = current_letter
|
22
|
+
end
|
23
|
+
key
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def joker_a_index
|
29
|
+
deck.cards.index(joker_a)
|
30
|
+
end
|
31
|
+
|
32
|
+
def joker_b_index
|
33
|
+
deck.cards.index(joker_b)
|
34
|
+
end
|
35
|
+
|
36
|
+
def joker_a
|
37
|
+
@joker_a
|
38
|
+
end
|
39
|
+
|
40
|
+
def joker_b
|
41
|
+
@joker_b
|
42
|
+
end
|
43
|
+
|
44
|
+
def max_index
|
45
|
+
deck.size - 1
|
46
|
+
end
|
47
|
+
|
48
|
+
def move_card(card, distance)
|
49
|
+
start_index = deck.cards.index(card)
|
50
|
+
end_index = start_index + distance
|
51
|
+
if end_index > max_index
|
52
|
+
end_index = end_index % max_index
|
53
|
+
end
|
54
|
+
deck.cards.insert(end_index, deck.cards.delete(card))
|
55
|
+
end
|
56
|
+
|
57
|
+
def triple_cut
|
58
|
+
c1, c2 = [joker_a_index, joker_b_index].sort
|
59
|
+
new_end = []
|
60
|
+
if c1 > 0
|
61
|
+
new_end = deck.cards[0..(c1 - 1)]
|
62
|
+
end
|
63
|
+
new_middle = deck.cards[c1..c2]
|
64
|
+
new_beginning = []
|
65
|
+
if c2 < max_index
|
66
|
+
new_beginning = deck.cards[(c2 + 1)..max_index]
|
67
|
+
end
|
68
|
+
deck.cards.replace(new_beginning + new_middle + new_end)
|
69
|
+
end
|
70
|
+
|
71
|
+
def count_cut
|
72
|
+
deck.cards.last.total_value.times do
|
73
|
+
deck.cards.insert(-2, deck.cards.shift)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def current_letter
|
78
|
+
letter_card = deck.cards[deck.cards[0].total_value]
|
79
|
+
return nil if letter_card.is_a? Joker
|
80
|
+
("A".."Z").to_a[(letter_card.total_value % 26) - 1]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
data/lib/ruby_quiz_1.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "ruby_quiz_1/version"
|
2
|
+
|
3
|
+
require "ruby_quiz_1/message"
|
4
|
+
require "ruby_quiz_1/character_group"
|
5
|
+
require "ruby_quiz_1/solitaire"
|
6
|
+
require "ruby_quiz_1/card"
|
7
|
+
require "ruby_quiz_1/joker"
|
8
|
+
require "ruby_quiz_1/suit"
|
9
|
+
require "ruby_quiz_1/deck"
|
10
|
+
|
11
|
+
module RubyQuiz1
|
12
|
+
|
13
|
+
end
|
data/ruby_quiz_1.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ruby_quiz_1/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ruby_quiz_1"
|
8
|
+
spec.version = RubyQuiz1::VERSION
|
9
|
+
spec.authors = ["Sean Devine"]
|
10
|
+
spec.email = ["barelyknown@icloud.com"]
|
11
|
+
spec.summary = %q{Solution to ruby quiz #1 @ http://rubyquiz.com/quiz1.html}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "thor"
|
22
|
+
|
23
|
+
spec.executables << "ruby_quiz_1"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec", ">= 3.0"
|
28
|
+
spec.add_development_dependency "rspec-context-private"
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe Card do
|
3
|
+
|
4
|
+
let :suit do
|
5
|
+
Suit.new :club, 0
|
6
|
+
end
|
7
|
+
|
8
|
+
it "can be initialized with a value from 1 to 13" do
|
9
|
+
(1..13).each do |n|
|
10
|
+
expect{described_class.new(n, suit)}.not_to raise_error
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "cannot be initialized with a value below 1 or above 13" do
|
15
|
+
[0,14].each do |n|
|
16
|
+
expect{described_class.new(n, suit)}.to raise_error ArgumentError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "calculates the total value" do
|
21
|
+
subject = described_class.new 1, Suit.new(:diamond, 13)
|
22
|
+
expect(subject.total_value).to eq 14
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe CharacterGroup do
|
3
|
+
|
4
|
+
let :solitaire do
|
5
|
+
Solitaire.new(StandardDeck.new)
|
6
|
+
end
|
7
|
+
|
8
|
+
context "when the value is valid and does not need padding" do
|
9
|
+
let(:value) { "ABCDE" }
|
10
|
+
subject { described_class.new value }
|
11
|
+
it "has characters that are the same as the value" do
|
12
|
+
expect(subject.characters).to eq value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when the value is valid and needs padding" do
|
17
|
+
(1..4).each do |n|
|
18
|
+
value = "A" * n
|
19
|
+
characters = value + "X" * (5 - n)
|
20
|
+
context "with #{5 - n} Xs (#{value})" do
|
21
|
+
subject do
|
22
|
+
described_class.new value
|
23
|
+
end
|
24
|
+
it "has the characters #{characters}" do
|
25
|
+
expect(subject.characters).to eq characters
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when the value is invalid" do
|
32
|
+
["a", "1", "!", nil, "ABCDEF"].each do |value|
|
33
|
+
context "such as #{value}" do
|
34
|
+
it "raises an argument error" do
|
35
|
+
expect{described_class.new(value)}.to raise_error ArgumentError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "compares equality to another character group using the characters" do
|
42
|
+
value = "ABCDE"
|
43
|
+
expect(described_class.new(value)).to eq described_class.new(value)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
describe "private methods", :private do
|
49
|
+
{
|
50
|
+
"CODEI" => [3,15,4,5,9],
|
51
|
+
"NRUBY" => [14,18,21,2,25],
|
52
|
+
"LIVEL" => [12,9,22,5,12],
|
53
|
+
"ONGER" => [15,14,7,5,18]
|
54
|
+
}.each do |k,v|
|
55
|
+
it "converts the value #{k} to the numbers #{v}" do
|
56
|
+
subject = described_class.new k
|
57
|
+
expect(subject.numbers).to eq v
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
{
|
62
|
+
[[3,15,4,5,9],[4,23,10,24,8]] => [7,12,14,3,17]
|
63
|
+
}.each do |k,v|
|
64
|
+
it "calculates the encrypted numbers" do
|
65
|
+
subject = described_class.new "CODEI"
|
66
|
+
allow(subject).to receive(:numbers).and_return(k[0])
|
67
|
+
allow(subject).to receive(:keystream).and_return(double(CharacterGroup, numbers: k[1]))
|
68
|
+
expect(subject.encrypted_numbers).to eq v
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
{
|
73
|
+
[[7,12,14,3,17],[4,23,10,24,8]] => [3,15,4,5,9]
|
74
|
+
}.each do |k,v|
|
75
|
+
it "calculates the decrypted numbers" do
|
76
|
+
subject = described_class.new "CODEI"
|
77
|
+
allow(subject).to receive(:numbers).and_return(k[0])
|
78
|
+
allow(subject).to receive(:keystream).and_return(double(CharacterGroup, numbers: k[1]))
|
79
|
+
expect(subject.decrypted_numbers).to eq v
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "converts numbers to characters" do
|
84
|
+
subject = described_class.new "CODEI"
|
85
|
+
expect(subject.convert_to_characters([3,15,4,5,9])).to eq "CODEI"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe Deck do
|
3
|
+
|
4
|
+
it "is enumerable" do
|
5
|
+
card = double(Card, total_value: 1)
|
6
|
+
expect(card).to receive(:total_value)
|
7
|
+
subject.cards << card
|
8
|
+
subject.each { |c| c.total_value }
|
9
|
+
end
|
10
|
+
|
11
|
+
it "calculates its size" do
|
12
|
+
subject.cards << double(Card)
|
13
|
+
expect(subject.size).to eq 1
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe Message do
|
3
|
+
|
4
|
+
describe "#decrypt" do
|
5
|
+
{
|
6
|
+
"CLEPK HHNIY CFPWH FDFEH" => "YOURC IPHER ISWOR KINGX",
|
7
|
+
"ABVAW LWZSY OORYK DUPVH" => "WELCO METOR UBYQU IZXXX"
|
8
|
+
}.each do |k,v|
|
9
|
+
context "with the encrypted message \"#{k}\"" do
|
10
|
+
subject do
|
11
|
+
described_class.new k
|
12
|
+
end
|
13
|
+
it "decrypts to \"#{v}\"" do
|
14
|
+
expect(subject.decrypt).to eq v
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#encrypt" do
|
21
|
+
{
|
22
|
+
"YOURC IPHER ISWOR KINGX" => "CLEPK HHNIY CFPWH FDFEH",
|
23
|
+
"WELCO METOR UBYQU IZXXX" => "ABVAW LWZSY OORYK DUPVH",
|
24
|
+
"WELCO METOR UBYQU IZ" => "ABVAW LWZSY OORYK DUPVH",
|
25
|
+
}.each do |k,v|
|
26
|
+
context "with the message #{k}" do
|
27
|
+
subject do
|
28
|
+
described_class.new k
|
29
|
+
end
|
30
|
+
it "encrypts to \"#{v}\"" do
|
31
|
+
puts subject.send(:character_groups).collect(&:characters).join(" ")
|
32
|
+
expect(subject.encrypt).to eq v
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#character_groups", :private do
|
39
|
+
{
|
40
|
+
"HELLO WORLD" => "HELLO WORLD",
|
41
|
+
"Hi There How Are You" => "HITHE REHOW AREYO UXXXX",
|
42
|
+
"HI! IT IS VERY NICE to see you" => "HIITI SVERY NICET OSEEY OUXXX"
|
43
|
+
}.each do |key, value|
|
44
|
+
context "with a message #{key}" do
|
45
|
+
subject { described_class.new key }
|
46
|
+
let :character_groups do
|
47
|
+
value.split(" ").collect { |v| CharacterGroup.new(v) }
|
48
|
+
end
|
49
|
+
it "builds the character groups #{value}" do
|
50
|
+
expect(subject.character_groups).to eq character_groups
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe Solitaire do
|
3
|
+
context "for a standard deck" do
|
4
|
+
subject do
|
5
|
+
described_class.new StandardDeck.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "calculates the correct first 10 keys" do
|
9
|
+
%w(D W J X H Y R F D G).each do |key|
|
10
|
+
expect(subject.next_key).to eq key
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RubyQuiz1
|
2
|
+
describe Suit do
|
3
|
+
|
4
|
+
let :name do
|
5
|
+
:club
|
6
|
+
end
|
7
|
+
|
8
|
+
let :value do
|
9
|
+
0
|
10
|
+
end
|
11
|
+
|
12
|
+
subject do
|
13
|
+
described_class.new name, value
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initiazes and gets the name" do
|
17
|
+
expect(subject.name).to eq name
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes and gets the name" do
|
21
|
+
expect(subject.value).to eq value
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby_quiz_1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Devine
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-context-private
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: 'Solution to ruby quiz #1 @ http://rubyquiz.com/quiz1.html'
|
84
|
+
email:
|
85
|
+
- barelyknown@icloud.com
|
86
|
+
executables:
|
87
|
+
- ruby_quiz_1
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".rspec"
|
93
|
+
- Gemfile
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.md
|
96
|
+
- Rakefile
|
97
|
+
- bin/ruby_quiz_1
|
98
|
+
- lib/ruby_quiz_1.rb
|
99
|
+
- lib/ruby_quiz_1/card.rb
|
100
|
+
- lib/ruby_quiz_1/character_group.rb
|
101
|
+
- lib/ruby_quiz_1/deck.rb
|
102
|
+
- lib/ruby_quiz_1/decks/standard_deck.rb
|
103
|
+
- lib/ruby_quiz_1/joker.rb
|
104
|
+
- lib/ruby_quiz_1/message.rb
|
105
|
+
- lib/ruby_quiz_1/solitaire.rb
|
106
|
+
- lib/ruby_quiz_1/suit.rb
|
107
|
+
- lib/ruby_quiz_1/version.rb
|
108
|
+
- ruby_quiz_1.gemspec
|
109
|
+
- spec/lib/ruby_quiz_1/card_spec.rb
|
110
|
+
- spec/lib/ruby_quiz_1/character_group_spec.rb
|
111
|
+
- spec/lib/ruby_quiz_1/deck_spec.rb
|
112
|
+
- spec/lib/ruby_quiz_1/decks/standard_deck_spec.rb
|
113
|
+
- spec/lib/ruby_quiz_1/joker_spec.rb
|
114
|
+
- spec/lib/ruby_quiz_1/message_spec.rb
|
115
|
+
- spec/lib/ruby_quiz_1/solitaire_spec.rb
|
116
|
+
- spec/lib/ruby_quiz_1/suit_spec.rb
|
117
|
+
- spec/spec_helper.rb
|
118
|
+
homepage: ''
|
119
|
+
licenses:
|
120
|
+
- MIT
|
121
|
+
metadata: {}
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 2.2.2
|
139
|
+
signing_key:
|
140
|
+
specification_version: 4
|
141
|
+
summary: 'Solution to ruby quiz #1 @ http://rubyquiz.com/quiz1.html'
|
142
|
+
test_files:
|
143
|
+
- spec/lib/ruby_quiz_1/card_spec.rb
|
144
|
+
- spec/lib/ruby_quiz_1/character_group_spec.rb
|
145
|
+
- spec/lib/ruby_quiz_1/deck_spec.rb
|
146
|
+
- spec/lib/ruby_quiz_1/decks/standard_deck_spec.rb
|
147
|
+
- spec/lib/ruby_quiz_1/joker_spec.rb
|
148
|
+
- spec/lib/ruby_quiz_1/message_spec.rb
|
149
|
+
- spec/lib/ruby_quiz_1/solitaire_spec.rb
|
150
|
+
- spec/lib/ruby_quiz_1/suit_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
has_rdoc:
|