From e63e484462c29c8d2398e5a11bb17e57032bbb7e Mon Sep 17 00:00:00 2001 From: Cohen Carlisle Date: Mon, 11 Apr 2016 00:15:36 -0400 Subject: [PATCH 1/3] generate run-length-encoding --- bin/generate-run-length-encoding | 6 ++ config.json | 1 + exercises/run-length-encoding/.version | 1 + exercises/run-length-encoding/example.rb | 30 ++++++++ exercises/run-length-encoding/example.tt | 29 ++++++++ .../run_length_encoding_test.rb | 71 +++++++++++++++++++ lib/run_length_encoding_cases.rb | 30 ++++++++ 7 files changed, 168 insertions(+) create mode 100755 bin/generate-run-length-encoding create mode 100644 exercises/run-length-encoding/.version create mode 100644 exercises/run-length-encoding/example.rb create mode 100644 exercises/run-length-encoding/example.tt create mode 100755 exercises/run-length-encoding/run_length_encoding_test.rb create mode 100644 lib/run_length_encoding_cases.rb diff --git a/bin/generate-run-length-encoding b/bin/generate-run-length-encoding new file mode 100755 index 0000000000..56dcca121c --- /dev/null +++ b/bin/generate-run-length-encoding @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby + +require_relative '../lib/generator' +require_relative '../lib/run_length_encoding_cases' + +Generator.new('run-length-encoding', RunLengthEncodingCases).generate diff --git a/config.json b/config.json index b5d7cc2ad4..e0f9bc0348 100644 --- a/config.json +++ b/config.json @@ -19,6 +19,7 @@ "word-count", "bob", "food-chain", + "run-length-encoding", "sieve", "binary", "accumulate", diff --git a/exercises/run-length-encoding/.version b/exercises/run-length-encoding/.version new file mode 100644 index 0000000000..56a6051ca2 --- /dev/null +++ b/exercises/run-length-encoding/.version @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/exercises/run-length-encoding/example.rb b/exercises/run-length-encoding/example.rb new file mode 100644 index 0000000000..e5511befa1 --- /dev/null +++ b/exercises/run-length-encoding/example.rb @@ -0,0 +1,30 @@ +class RunLength + VERSION = 1 + + def self.encode(str) + str.chars.chunk { |char| char }.each_with_object('') do |chunk, out| + out << encoded(chunk) + end + end + + def self.decode(str) + str.scan(/(\d+)?(\D)/).each_with_object('') do |captures, out| + out << decoded(captures) + end + end + + def self.encoded(chunk) + char = chunk.first + times = chunk.last.count + return char if times == 1 + "#{times}#{char}" + end + private_class_method :encoded + + def self.decoded(captures) + times = (captures.first || 1).to_i + char = captures.last + char * times + end + private_class_method :decoded +end diff --git a/exercises/run-length-encoding/example.tt b/exercises/run-length-encoding/example.tt new file mode 100644 index 0000000000..8b2d3857e8 --- /dev/null +++ b/exercises/run-length-encoding/example.tt @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# encoding: utf-8 +gem 'minitest', '>= 5.0.0' +require 'minitest/autorun' +require_relative 'run_length' + +# Test data version: +# <%= sha1 %> +class RunLengthEncodingTest < Minitest::Test<% test_cases.each do |test_case| %> + def <%= test_case.name %><% if test_case.skipped? %> + skip<% end %> + input = '<%= test_case.input %>' + output = '<%= test_case.expected %>' + assert_equal <%= test_case.do %>, output + end +<% 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 RunLength. + # 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 + assert_equal <%= version+1 %>, RunLength::VERSION + end +end diff --git a/exercises/run-length-encoding/run_length_encoding_test.rb b/exercises/run-length-encoding/run_length_encoding_test.rb new file mode 100755 index 0000000000..1713437467 --- /dev/null +++ b/exercises/run-length-encoding/run_length_encoding_test.rb @@ -0,0 +1,71 @@ +#!/usr/bin/env ruby +# encoding: utf-8 +gem 'minitest', '>= 5.0.0' +require 'minitest/autorun' +require_relative 'run_length' + +# Test data version: +# eb8d142 Merge pull request #220 from IanWhitney/sieve_ordering + +class RunLengthEncodingTest < Minitest::Test + def test_encode_simple + input = 'AABBBCCCC' + output = '2A3B4C' + assert_equal RunLength.encode(input), output + end + + def test_decode_simple + skip + input = '2A3B4C' + output = 'AABBBCCCC' + assert_equal RunLength.decode(input), output + end + + def test_encode_with_single_values + skip + input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' + output = '12WB12W3B24WB' + assert_equal RunLength.encode(input), output + end + + def test_decode_with_single_values + skip + input = '12WB12W3B24WB' + output = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' + assert_equal RunLength.decode(input), output + end + + def test_decode_encode_combination + skip + input = 'zzz ZZ zZ' + output = 'zzz ZZ zZ' + assert_equal RunLength.decode(RunLength.encode(input)), output + end + + def test_encode_unicode + skip + input = '⏰⚽⚽⚽⭐⭐⏰' + output = '⏰3⚽2⭐⏰' + assert_equal RunLength.encode(input), output + end + + def test_decode_unicode + skip + input = '⏰3⚽2⭐⏰' + output = '⏰⚽⚽⚽⭐⭐⏰' + assert_equal RunLength.decode(input), output + 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 RunLength. + # 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 + assert_equal 1, RunLength::VERSION + end +end diff --git a/lib/run_length_encoding_cases.rb b/lib/run_length_encoding_cases.rb new file mode 100644 index 0000000000..6505c4876f --- /dev/null +++ b/lib/run_length_encoding_cases.rb @@ -0,0 +1,30 @@ +class RunLengthEncodingCase < OpenStruct + def name + 'test_%s' % cleaned_description + end + + def cleaned_description + description.gsub(/\W+/, '_').squeeze('_') + end + + def do + case description + when /decode.+encode/ + 'RunLength.decode(RunLength.encode(input))' + when /encode/ + 'RunLength.encode(input)' + when /decode/ + 'RunLength.decode(input)' + end + end + + def skipped? + index > 0 + end +end + +RunLengthEncodingCases = proc do |data| + JSON.parse(data)['cases'].map.with_index do |row, i| + RunLengthEncodingCase.new(row.merge('index' => i)) + end +end From e415d31d572ac0a017ed52a2cbabd7340d056db5 Mon Sep 17 00:00:00 2001 From: Cohen Carlisle Date: Wed, 13 Apr 2016 20:25:31 -0400 Subject: [PATCH 2/3] update file/class name to pass in ci --- exercises/run-length-encoding/example.rb | 18 ++++++++--------- exercises/run-length-encoding/example.tt | 6 +++--- .../run_length_encoding_test.rb | 20 +++++++++---------- lib/run_length_encoding_cases.rb | 6 +++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/exercises/run-length-encoding/example.rb b/exercises/run-length-encoding/example.rb index e5511befa1..284e5d66a9 100644 --- a/exercises/run-length-encoding/example.rb +++ b/exercises/run-length-encoding/example.rb @@ -1,30 +1,30 @@ -class RunLength +class RunLengthEncoding VERSION = 1 - def self.encode(str) + def self.do(str) str.chars.chunk { |char| char }.each_with_object('') do |chunk, out| - out << encoded(chunk) + out << encode(chunk) end end - def self.decode(str) + def self.undo(str) str.scan(/(\d+)?(\D)/).each_with_object('') do |captures, out| - out << decoded(captures) + out << decode(captures) end end - def self.encoded(chunk) + def self.encode(chunk) char = chunk.first times = chunk.last.count return char if times == 1 "#{times}#{char}" end - private_class_method :encoded + private_class_method :encode - def self.decoded(captures) + def self.decode(captures) times = (captures.first || 1).to_i char = captures.last char * times end - private_class_method :decoded + private_class_method :decode end diff --git a/exercises/run-length-encoding/example.tt b/exercises/run-length-encoding/example.tt index 8b2d3857e8..8a0422f003 100644 --- a/exercises/run-length-encoding/example.tt +++ b/exercises/run-length-encoding/example.tt @@ -2,7 +2,7 @@ # encoding: utf-8 gem 'minitest', '>= 5.0.0' require 'minitest/autorun' -require_relative 'run_length' +require_relative 'run_length_encoding' # Test data version: # <%= sha1 %> @@ -19,11 +19,11 @@ class RunLengthEncodingTest < Minitest::Test<% test_cases.each do |test_case| %> # The version number refers to the version of the problem you solved, # not your solution. # - # Define a constant named VERSION inside of RunLength. + # Define a constant named VERSION inside of RunLengthEncoding. # 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 - assert_equal <%= version+1 %>, RunLength::VERSION + assert_equal <%= version+1 %>, RunLengthEncoding::VERSION end end diff --git a/exercises/run-length-encoding/run_length_encoding_test.rb b/exercises/run-length-encoding/run_length_encoding_test.rb index 1713437467..7a15888216 100755 --- a/exercises/run-length-encoding/run_length_encoding_test.rb +++ b/exercises/run-length-encoding/run_length_encoding_test.rb @@ -2,7 +2,7 @@ # encoding: utf-8 gem 'minitest', '>= 5.0.0' require 'minitest/autorun' -require_relative 'run_length' +require_relative 'run_length_encoding' # Test data version: # eb8d142 Merge pull request #220 from IanWhitney/sieve_ordering @@ -11,49 +11,49 @@ class RunLengthEncodingTest < Minitest::Test def test_encode_simple input = 'AABBBCCCC' output = '2A3B4C' - assert_equal RunLength.encode(input), output + assert_equal RunLengthEncoding.do(input), output end def test_decode_simple skip input = '2A3B4C' output = 'AABBBCCCC' - assert_equal RunLength.decode(input), output + assert_equal RunLengthEncoding.undo(input), output end def test_encode_with_single_values skip input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' output = '12WB12W3B24WB' - assert_equal RunLength.encode(input), output + assert_equal RunLengthEncoding.do(input), output end def test_decode_with_single_values skip input = '12WB12W3B24WB' output = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' - assert_equal RunLength.decode(input), output + assert_equal RunLengthEncoding.undo(input), output end def test_decode_encode_combination skip input = 'zzz ZZ zZ' output = 'zzz ZZ zZ' - assert_equal RunLength.decode(RunLength.encode(input)), output + assert_equal RunLengthEncoding.undo(RunLengthEncoding.do(input)), output end def test_encode_unicode skip input = '⏰⚽⚽⚽⭐⭐⏰' output = '⏰3⚽2⭐⏰' - assert_equal RunLength.encode(input), output + assert_equal RunLengthEncoding.do(input), output end def test_decode_unicode skip input = '⏰3⚽2⭐⏰' output = '⏰⚽⚽⚽⭐⭐⏰' - assert_equal RunLength.decode(input), output + assert_equal RunLengthEncoding.undo(input), output end # Problems in exercism evolve over time, @@ -61,11 +61,11 @@ def test_decode_unicode # The version number refers to the version of the problem you solved, # not your solution. # - # Define a constant named VERSION inside of RunLength. + # Define a constant named VERSION inside of RunLengthEncoding. # 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 - assert_equal 1, RunLength::VERSION + assert_equal 1, RunLengthEncoding::VERSION end end diff --git a/lib/run_length_encoding_cases.rb b/lib/run_length_encoding_cases.rb index 6505c4876f..2dd3946641 100644 --- a/lib/run_length_encoding_cases.rb +++ b/lib/run_length_encoding_cases.rb @@ -10,11 +10,11 @@ def cleaned_description def do case description when /decode.+encode/ - 'RunLength.decode(RunLength.encode(input))' + 'RunLengthEncoding.undo(RunLengthEncoding.do(input))' when /encode/ - 'RunLength.encode(input)' + 'RunLengthEncoding.do(input)' when /decode/ - 'RunLength.decode(input)' + 'RunLengthEncoding.undo(input)' end end From 83a0e3b8b70a1edabae82ae31c1c4a910a0c29c8 Mon Sep 17 00:00:00 2001 From: Cohen Carlisle Date: Thu, 14 Apr 2016 20:47:00 -0400 Subject: [PATCH 3/3] don't define #do and don't exceed 80 chars/line --- exercises/run-length-encoding/example.rb | 18 ++++++++------- exercises/run-length-encoding/example.tt | 6 ++--- .../run_length_encoding_test.rb | 15 ++++++------ lib/run_length_encoding_cases.rb | 23 ++++++++++++++----- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/exercises/run-length-encoding/example.rb b/exercises/run-length-encoding/example.rb index 284e5d66a9..bde2e01429 100644 --- a/exercises/run-length-encoding/example.rb +++ b/exercises/run-length-encoding/example.rb @@ -1,30 +1,32 @@ class RunLengthEncoding VERSION = 1 - def self.do(str) + def self.encode(str) str.chars.chunk { |char| char }.each_with_object('') do |chunk, out| - out << encode(chunk) + out << encoded(chunk) end end - def self.undo(str) + def self.decode(str) str.scan(/(\d+)?(\D)/).each_with_object('') do |captures, out| - out << decode(captures) + out << decoded(captures) end end - def self.encode(chunk) + # private + + def self.encoded(chunk) char = chunk.first times = chunk.last.count return char if times == 1 "#{times}#{char}" end - private_class_method :encode + private_class_method :encoded - def self.decode(captures) + def self.decoded(captures) times = (captures.first || 1).to_i char = captures.last char * times end - private_class_method :decode + private_class_method :decoded end diff --git a/exercises/run-length-encoding/example.tt b/exercises/run-length-encoding/example.tt index 8a0422f003..62efd5e157 100644 --- a/exercises/run-length-encoding/example.tt +++ b/exercises/run-length-encoding/example.tt @@ -9,9 +9,9 @@ require_relative 'run_length_encoding' class RunLengthEncodingTest < Minitest::Test<% test_cases.each do |test_case| %> def <%= test_case.name %><% if test_case.skipped? %> skip<% end %> - input = '<%= test_case.input %>' - output = '<%= test_case.expected %>' - assert_equal <%= test_case.do %>, output + <%= test_case.assign_input %> + <%= test_case.assign_output %> + <%= test_case.assertion %> end <% end %> # Problems in exercism evolve over time, diff --git a/exercises/run-length-encoding/run_length_encoding_test.rb b/exercises/run-length-encoding/run_length_encoding_test.rb index 7a15888216..d798dd4e24 100755 --- a/exercises/run-length-encoding/run_length_encoding_test.rb +++ b/exercises/run-length-encoding/run_length_encoding_test.rb @@ -11,49 +11,50 @@ class RunLengthEncodingTest < Minitest::Test def test_encode_simple input = 'AABBBCCCC' output = '2A3B4C' - assert_equal RunLengthEncoding.do(input), output + assert_equal output, RunLengthEncoding.encode(input) end def test_decode_simple skip input = '2A3B4C' output = 'AABBBCCCC' - assert_equal RunLengthEncoding.undo(input), output + assert_equal output, RunLengthEncoding.decode(input) end def test_encode_with_single_values skip input = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' output = '12WB12W3B24WB' - assert_equal RunLengthEncoding.do(input), output + assert_equal output, RunLengthEncoding.encode(input) end def test_decode_with_single_values skip input = '12WB12W3B24WB' output = 'WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB' - assert_equal RunLengthEncoding.undo(input), output + assert_equal output, RunLengthEncoding.decode(input) end def test_decode_encode_combination skip input = 'zzz ZZ zZ' output = 'zzz ZZ zZ' - assert_equal RunLengthEncoding.undo(RunLengthEncoding.do(input)), output + assert_equal output, + RunLengthEncoding.decode(RunLengthEncoding.encode(input)) end def test_encode_unicode skip input = '⏰⚽⚽⚽⭐⭐⏰' output = '⏰3⚽2⭐⏰' - assert_equal RunLengthEncoding.do(input), output + assert_equal output, RunLengthEncoding.encode(input) end def test_decode_unicode skip input = '⏰3⚽2⭐⏰' output = '⏰⚽⚽⚽⭐⭐⏰' - assert_equal RunLengthEncoding.undo(input), output + assert_equal output, RunLengthEncoding.decode(input) end # Problems in exercism evolve over time, diff --git a/lib/run_length_encoding_cases.rb b/lib/run_length_encoding_cases.rb index 2dd3946641..32ce39d763 100644 --- a/lib/run_length_encoding_cases.rb +++ b/lib/run_length_encoding_cases.rb @@ -3,24 +3,35 @@ def name 'test_%s' % cleaned_description end - def cleaned_description - description.gsub(/\W+/, '_').squeeze('_') + def assign_input + "input = '#{input}'" end - def do + def assign_output + "output = '#{expected}'" + end + + def assertion case description when /decode.+encode/ - 'RunLengthEncoding.undo(RunLengthEncoding.do(input))' + 'assert_equal output, + RunLengthEncoding.decode(RunLengthEncoding.encode(input))' when /encode/ - 'RunLengthEncoding.do(input)' + 'assert_equal output, RunLengthEncoding.encode(input)' when /decode/ - 'RunLengthEncoding.undo(input)' + 'assert_equal output, RunLengthEncoding.decode(input)' end end def skipped? index > 0 end + + # internal + + def cleaned_description + description.gsub(/\W+/, '_').squeeze('_') + end end RunLengthEncodingCases = proc do |data|