diff --git a/exercises/crypto-square/.meta/.version b/exercises/crypto-square/.meta/.version new file mode 100644 index 0000000000..56a6051ca2 --- /dev/null +++ b/exercises/crypto-square/.meta/.version @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/exercises/crypto-square/.meta/generator/crypto_square_case.rb b/exercises/crypto-square/.meta/generator/crypto_square_case.rb new file mode 100644 index 0000000000..129531e321 --- /dev/null +++ b/exercises/crypto-square/.meta/generator/crypto_square_case.rb @@ -0,0 +1,19 @@ +require 'generator/exercise_case' + +class CryptoSquareCase < Generator::ExerciseCase + + def workload + indent_lines([plaintext_setter, assertion], 4) + end + + private + + def plaintext_setter + "plaintext = '#{plaintext}'" + end + + def assertion + assert_equal { "Crypto.new(plaintext).ciphertext" } + end + +end diff --git a/exercises/crypto-square/.meta/solutions/crypto_square.rb b/exercises/crypto-square/.meta/solutions/crypto_square.rb index c0469e36f5..92a2319e93 100644 --- a/exercises/crypto-square/.meta/solutions/crypto_square.rb +++ b/exercises/crypto-square/.meta/solutions/crypto_square.rb @@ -4,36 +4,41 @@ def initialize(plaintext) @plaintext = plaintext end + def ciphertext + transposed.join(' ') + end + + private + def normalize_plaintext @normalized ||= @plaintext.downcase.gsub(/\W/, '') end def plaintext_segments - normalize_plaintext.chars. - each_slice(size). - map{ |s| s.join('') }. - to_a + if size > 0 + normalize_plaintext.chars. + each_slice(size). + map{ |s| s.join('') }. + to_a + else + [] + end end def size Math.sqrt(normalize_plaintext.length).ceil end - def ciphertext - transposed.join('') - end - - def normalize_ciphertext - transposed.join(' ') - end - - private - def transposed chunk_size = size chunks = plaintext_segments.map do |s| - Array.new(chunk_size) { |i| s[i] or '' } + Array.new(chunk_size) { |i| s[i] or ' ' } end chunks.transpose.map{ |s| s.join('') } end + +end + +module BookKeeping + VERSION = 1 end diff --git a/exercises/crypto-square/README.md b/exercises/crypto-square/README.md index 2ee9115506..d9be46aea1 100644 --- a/exercises/crypto-square/README.md +++ b/exercises/crypto-square/README.md @@ -26,7 +26,7 @@ and `r` is the number of rows. Our normalized text is 54 characters long, dictating a rectangle with `c = 8` and `r = 7`: -```plain +```text ifmanwas meanttos tayonthe @@ -41,22 +41,24 @@ right. The message above is coded as: -```plain +```text imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau ``` -Output the encoded text in chunks. Phrases that fill perfect squares -`(r X r)` should be output in `r`-length chunks separated by spaces. -Imperfect squares will have `n` empty spaces. Those spaces should be distributed evenly across the last `n` rows. +Output the encoded text in chunks. Phrases that fill perfect rectangles +`(r X c)` should be output `c` chunks of `r` length, separated by spaces. +Phrases that do not fill perfect rectangles will have `n` empty spaces. +Those spaces should be distributed evenly, added to the end of the last +`n` chunks. -```plain -imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau +```text +imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau ``` Notice that were we to stack these, we could visually decode the cyphertext back in to the original message: -```plain +```text imtgdvs fearwer mayoogo diff --git a/exercises/crypto-square/crypto_square_test.rb b/exercises/crypto-square/crypto_square_test.rb index 188ea9f129..e0348b5d22 100644 --- a/exercises/crypto-square/crypto_square_test.rb +++ b/exercises/crypto-square/crypto_square_test.rb @@ -1,105 +1,69 @@ require 'minitest/autorun' require_relative 'crypto_square' -class CryptoTest < Minitest::Test - def test_normalize_strange_characters - crypto = Crypto.new('s#$%^&plunk') - assert_equal 'splunk', crypto.normalize_plaintext +# Common test data version: 3.1.0 e937744 +class CryptoSquareTest < Minitest::Test + def test_empty_plaintext_results_in_an_empty_ciphertext + # skip + plaintext = '' + assert_equal "", Crypto.new(plaintext).ciphertext end - def test_normalize_uppercase_characters + def test_lowercase skip - crypto = Crypto.new('WHOA HEY!') - assert_equal 'whoahey', crypto.normalize_plaintext + plaintext = 'A' + assert_equal "a", Crypto.new(plaintext).ciphertext end - def test_normalize_with_numbers + def test_remove_spaces skip - crypto = Crypto.new('1, 2, 3 GO!') - assert_equal '123go', crypto.normalize_plaintext + plaintext = ' b ' + assert_equal "b", Crypto.new(plaintext).ciphertext end - def test_size_of_small_square + def test_remove_punctuation skip - crypto = Crypto.new('1234') - assert_equal 2, crypto.size + plaintext = '@1,%!' + assert_equal "1", Crypto.new(plaintext).ciphertext end - def test_size_of_slightly_larger_square + def test_9_character_plaintext_results_in_3_chunks_of_3_characters skip - crypto = Crypto.new('123456789') - assert_equal 3, crypto.size + plaintext = 'This is fun!' + assert_equal "tsf hiu isn", Crypto.new(plaintext).ciphertext end - def test_size_of_non_perfect_square + def test_8_character_plaintext_results_in_3_chunks_the_last_one_with_a_trailing_space skip - crypto = Crypto.new('123456789abc') - assert_equal 4, crypto.size + plaintext = 'Chill out.' + assert_equal "clu hlt io ", Crypto.new(plaintext).ciphertext end - def test_size_is_determined_by_normalized_plaintext + def test_54_character_plaintext_results_in_7_chunks_the_last_two_with_trailing_spaces skip - crypto = Crypto.new('Oh hey, this is nuts!') - assert_equal 4, crypto.size - end - - def test_plaintext_segments - skip - crypto = Crypto.new('Never vex thine heart with idle woes') - expected = %w(neverv exthin eheart withid lewoes) - assert_equal expected, crypto.plaintext_segments - end - - def test_other_plaintext_segments - skip - crypto = Crypto.new('ZOMG! ZOMBIES!!!') - assert_equal %w(zomg zomb ies), crypto.plaintext_segments - end - - def test_ciphertext - skip - crypto = Crypto.new('Time is an illusion. Lunchtime doubly so.') - assert_equal 'tasneyinicdsmiohooelntuillibsuuml', crypto.ciphertext - end - - def test_another_ciphertext - skip - crypto = Crypto.new('We all know interspecies romance is weird.') - assert_equal 'wneiaweoreneawssciliprerlneoidktcms', crypto.ciphertext - end - - def test_normalized_ciphertext - skip - crypto = Crypto.new('Vampires are people too!') - assert_equal 'vrel aepe mset paoo irpo', crypto.normalize_ciphertext - end - - def test_normalized_ciphertext_spills_into_short_segment - skip - crypto = Crypto.new('Madness, and then illumination.') - expected = 'msemo aanin dnin ndla etlt shui' - assert_equal expected, crypto.normalize_ciphertext - end - - def test_another_normalized_ciphertext - skip - crypto = Crypto.new( - 'If man was meant to stay on the ground god would have given us roots', - ) - expected = 'imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau' - assert_equal expected, crypto.normalize_ciphertext - end - - def test_normalized_ciphertext_with_punctuation - skip - crypto = Crypto.new('Have a nice day. Feed the dog & chill out!') - expected = 'hifei acedl veeol eddgo aatcu nyhht' - assert_equal expected, crypto.normalize_ciphertext - end - - def test_normalized_ciphertext_when_just_less_then_a_full_square + plaintext = 'If man was meant to stay on the ground, god would have given us roots.' + assert_equal "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau ", Crypto.new(plaintext).ciphertext + end + + # Problems in exercism evolve over time, as we find better ways to ask + # questions. + # The version number refers to the version of the problem you solved, + # not your solution. + # + # Define a constant named VERSION inside of the top level BookKeeping + # module, which may be placed near the end of your file. + # + # In your file, it will look like this: + # + # module BookKeeping + # VERSION = 1 # Where the version number matches the one in the test. + # end + # + # If you are curious, read more about constants on RubyDoc: + # http://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/constants.html + + def test_bookkeeping skip - crypto = Crypto.new('I am') - assert_equal 'im a', crypto.normalize_ciphertext + assert_equal 1, BookKeeping::VERSION end end