diff --git a/exercises/all-your-base/.meta/.version b/exercises/all-your-base/.meta/.version new file mode 100644 index 0000000000..d8263ee986 --- /dev/null +++ b/exercises/all-your-base/.meta/.version @@ -0,0 +1 @@ +2 \ No newline at end of file diff --git a/exercises/all-your-base/all_your_base_test.rb b/exercises/all-your-base/all_your_base_test.rb index 9f9b78ed2c..f88bc77bee 100755 --- a/exercises/all-your-base/all_your_base_test.rb +++ b/exercises/all-your-base/all_your_base_test.rb @@ -1,9 +1,10 @@ -gem 'minitest', '>= 5.0.0' require 'minitest/autorun' require_relative 'all_your_base' +# Test data version: aa12f2e class AllYourBaseTest < Minitest::Test - def test_single_bit_to_one_decimal + def test_single_bit_one_to_decimal + # skip digits = [1] input_base = 2 output_base = 10 @@ -131,7 +132,7 @@ def test_empty_list def test_single_zero skip digits = [0] - input_base = 10 + input_base = 10 output_base = 2 expected = [0] @@ -142,10 +143,10 @@ def test_single_zero "Expected #{expected} but got #{converted}." end - def test_multiple_zeroes + def test_multiple_zeros skip digits = [0, 0, 0] - input_base = 10 + input_base = 10 output_base = 2 expected = [0] @@ -175,13 +176,10 @@ def test_negative_digit digits = [1, -1, 1, 0, 1, 0] input_base = 2 output_base = 10 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_invalid_positive_digit @@ -189,13 +187,10 @@ def test_invalid_positive_digit digits = [1, 2, 1, 0, 1, 0] input_base = 2 output_base = 10 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_first_base_is_one @@ -203,13 +198,10 @@ def test_first_base_is_one digits = [] input_base = 1 output_base = 10 - expected = nil - converted = BaseConverter.convert(input_base, digits, output_base) - - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_second_base_is_one @@ -217,13 +209,10 @@ def test_second_base_is_one digits = [1, 0, 1, 0, 1, 0] input_base = 2 output_base = 1 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_first_base_is_zero @@ -231,13 +220,10 @@ def test_first_base_is_zero digits = [] input_base = 0 output_base = 10 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_second_base_is_zero @@ -245,13 +231,10 @@ def test_second_base_is_zero digits = [7] input_base = 10 output_base = 0 - expected = nil - converted = BaseConverter.convert(input_base, digits, output_base) - - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_first_base_is_negative @@ -259,13 +242,10 @@ def test_first_base_is_negative digits = [1] input_base = -2 output_base = 10 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_second_base_is_negative @@ -273,13 +253,10 @@ def test_second_base_is_negative digits = [1] input_base = 2 output_base = -7 - expected = nil - - converted = BaseConverter.convert(input_base, digits, output_base) - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + end end def test_both_bases_are_negative @@ -287,17 +264,30 @@ def test_both_bases_are_negative digits = [1] input_base = -2 output_base = -7 - expected = nil - converted = BaseConverter.convert(input_base, digits, output_base) - - assert_equal expected, converted, - "Input base: #{input_base}, output base #{output_base}. " \ - "Expected #{expected} but got #{converted}." + assert_raises ArgumentError do + BaseConverter.convert(input_base, digits, output_base) + 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 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 - assert_equal 1, BookKeeping::VERSION + assert_equal 2, BookKeeping::VERSION end end diff --git a/exercises/all-your-base/example.rb b/exercises/all-your-base/example.rb index ccfd660e4e..2a035e0c1b 100644 --- a/exercises/all-your-base/example.rb +++ b/exercises/all-your-base/example.rb @@ -1,21 +1,26 @@ module BookKeeping - VERSION = 1 + VERSION = 2 end class BaseConverter def self.convert(base_from, number_array, base_to) - return if number_array.any?{|number| number < 0 || number >= base_from} - return if base_from <= 1 || base_to <= 1 + fail ArgumentError if invalid_inputs?(base_from, number_array, base_to) return [] unless number_array.any? number_in_canonical_base = convert_to_canonical_base(number_array, base_from) convert_from_canonical_base(number_in_canonical_base, base_to) end - private + private_class_method + + def self.invalid_inputs?(base_from, number_array, base_to) + number_array.any? { |number| number < 0 || number >= base_from } || + base_from <= 1 || base_to <= 1 + end + def self.convert_to_canonical_base(number_array, base) total = 0 number_array.reverse.each_with_index do |number, index| - total += number * base ** index + total += number * base**index end total end @@ -23,9 +28,9 @@ def self.convert_to_canonical_base(number_array, base) def self.convert_from_canonical_base(number, base_to) result = [] current_number = number - while current_number >= base_to do - result << current_number % base_to - current_number = current_number / base_to + while current_number >= base_to + result << current_number % base_to + current_number /= base_to end result << current_number % base_to result.reverse diff --git a/exercises/all-your-base/example.tt b/exercises/all-your-base/example.tt new file mode 100644 index 0000000000..064b38a372 --- /dev/null +++ b/exercises/all-your-base/example.tt @@ -0,0 +1,17 @@ +require 'minitest/autorun' +require_relative 'all_your_base' + +# Test data version: <%= sha1 %> +class AllYourBaseTest < Minitest::Test<% test_cases.each do |test_case| %> + def <%= test_case.test_name %> + <%= test_case.skipped %> +<%= test_case.workload %> + end +<% end %> + +<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping + skip + assert_equal <%= version.next %>, BookKeeping::VERSION + end +end diff --git a/lib/all_your_base_cases.rb b/lib/all_your_base_cases.rb new file mode 100644 index 0000000000..1d564510e9 --- /dev/null +++ b/lib/all_your_base_cases.rb @@ -0,0 +1,109 @@ +class AllYourBaseCase < OpenStruct + def test_name + 'test_%s' % description.downcase.tr(' -', '_') + end + + def workload + indent(4, (assignments + assertion).join("\n")) + "\n" + end + + def skipped + index.zero? ? '# skip' : 'skip' + end + + private + + def indent(size, text) + text.lines.each_with_object('') do |line, obj| + obj << (line == "\n" ? line : ' ' * size + line) + end + end + + def assignments + [ + "digits = #{input_digits}", + "input_base = #{input_base}", + "output_base = #{output_base}", + ] + end + + def assertion + return error_assertion unless expected + + [ + "expected = #{expected}", + "", + "converted = BaseConverter.convert(input_base, digits, output_base)", + "", + "assert_equal expected, converted,", + indent(13, error_message), + ] + end + + def error_assertion + [ + "", + "assert_raises ArgumentError do", + " BaseConverter.convert(input_base, digits, output_base)", + "end", + ] + end + + def error_message + %q("Input base: #{input_base}, output base #{output_base}. " \\) \ + "\n" + %q("Expected #{expected} but got #{converted}.") + end +end + +class AllYourBaseCase::PreProcessor + class << self + attr_reader :row + + def call(row) + @row = row + + row.merge('expected' => expected_value) + end + + private :row + private + + def expected_value + return row['expected'] if row['expected'] + + if invalid_input_digits? || invalid_bases? + nil + elsif row['input_digits'].empty? + [] + elsif input_of_zero? + [0] + else + handle_special_cases + end + end + + def invalid_input_digits? + row['input_digits'].any? { |x| x < 0 || x >= row['input_base'] } + end + + def invalid_bases? + row['input_base'] <= 1 || row['output_base'] <= 1 + end + + def input_of_zero? + row['input_digits'].all? { |x| x == 0 } + end + + def handle_special_cases + [4,2] if row['input_digits'] == [0, 6, 0] + end + end +end + +AllYourBaseCases = proc do |data| + JSON.parse(data)['cases'].map.with_index do |row, i| + AllYourBaseCase.new( + AllYourBaseCase::PreProcessor.call(row).merge(index: i), + ) + end +end