From 3a170a7bc909684beb8121dd83e60efd9fb6e6e0 Mon Sep 17 00:00:00 2001 From: Nick Holden Date: Mon, 9 Oct 2017 13:37:42 -0700 Subject: [PATCH 1/5] Generate crypto-square test from canonical data --- exercises/crypto-square/.meta/.version | 1 + .../.meta/generator/crypto_square_case.rb | 19 +++ exercises/crypto-square/crypto_square_test.rb | 126 +++++++----------- 3 files changed, 65 insertions(+), 81 deletions(-) create mode 100644 exercises/crypto-square/.meta/.version create mode 100644 exercises/crypto-square/.meta/generator/crypto_square_case.rb 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/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 From 5a5eb825994d7400470b0b5c0da970fb79d1f997 Mon Sep 17 00:00:00 2001 From: Nick Holden Date: Mon, 9 Oct 2017 13:38:14 -0700 Subject: [PATCH 2/5] Update crypto-square example solution to pass new tests --- .../.meta/solutions/crypto_square.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/exercises/crypto-square/.meta/solutions/crypto_square.rb b/exercises/crypto-square/.meta/solutions/crypto_square.rb index c0469e36f5..d2d82b6fe4 100644 --- a/exercises/crypto-square/.meta/solutions/crypto_square.rb +++ b/exercises/crypto-square/.meta/solutions/crypto_square.rb @@ -9,10 +9,14 @@ def normalize_plaintext 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 @@ -20,10 +24,6 @@ def size end def ciphertext - transposed.join('') - end - - def normalize_ciphertext transposed.join(' ') end @@ -32,7 +32,7 @@ def normalize_ciphertext 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 From a6ff1766649275c1e7e14a44792b80b9ba7c33c1 Mon Sep 17 00:00:00 2001 From: Nick Holden Date: Mon, 9 Oct 2017 13:40:40 -0700 Subject: [PATCH 3/5] Update crypto-square README to match problem-specifications description The description was updated as part of https://github.com/exercism/problem-specifications/pull/929/files --- exercises/crypto-square/README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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 From 723a90fbae4c8ce0a1c66b00ccee79be9e75bfc2 Mon Sep 17 00:00:00 2001 From: Nick Holden Date: Sun, 15 Oct 2017 09:35:12 -0700 Subject: [PATCH 4/5] Include BookKeeping version in crypto-square example solution --- exercises/crypto-square/.meta/solutions/crypto_square.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exercises/crypto-square/.meta/solutions/crypto_square.rb b/exercises/crypto-square/.meta/solutions/crypto_square.rb index d2d82b6fe4..b2c4a4a2d7 100644 --- a/exercises/crypto-square/.meta/solutions/crypto_square.rb +++ b/exercises/crypto-square/.meta/solutions/crypto_square.rb @@ -37,3 +37,7 @@ def transposed chunks.transpose.map{ |s| s.join('') } end end + +module BookKeeping + VERSION = 1 +end From c1b7b583bc83c14e754915fe5fef907e38ffcf2e Mon Sep 17 00:00:00 2001 From: Nick Holden Date: Sun, 15 Oct 2017 17:34:29 -0700 Subject: [PATCH 5/5] Make methods not called by tests private --- .../crypto-square/.meta/solutions/crypto_square.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/exercises/crypto-square/.meta/solutions/crypto_square.rb b/exercises/crypto-square/.meta/solutions/crypto_square.rb index b2c4a4a2d7..92a2319e93 100644 --- a/exercises/crypto-square/.meta/solutions/crypto_square.rb +++ b/exercises/crypto-square/.meta/solutions/crypto_square.rb @@ -4,6 +4,12 @@ def initialize(plaintext) @plaintext = plaintext end + def ciphertext + transposed.join(' ') + end + + private + def normalize_plaintext @normalized ||= @plaintext.downcase.gsub(/\W/, '') end @@ -23,12 +29,6 @@ def size Math.sqrt(normalize_plaintext.length).ceil end - def ciphertext - transposed.join(' ') - end - - private - def transposed chunk_size = size chunks = plaintext_segments.map do |s| @@ -36,6 +36,7 @@ def transposed end chunks.transpose.map{ |s| s.join('') } end + end module BookKeeping