From e90b94f75be07d4020bc103318a5f24808795630 Mon Sep 17 00:00:00 2001 From: Victor Goff Date: Wed, 22 Jun 2016 13:15:15 -0400 Subject: [PATCH] Generated Custom Set The custom-set exercise is generated using data from x-common repository. fixes #365 fixes #348 references exercism/x-common#257 --- bin/generate-custom-set | 7 + exercises/custom-set/.version | 1 + exercises/custom-set/custom_set_test.rb | 321 +++++++++++++++++++----- exercises/custom-set/example.rb | 14 +- exercises/custom-set/example.tt | 19 ++ lib/custom_set_cases.rb | 86 +++++++ 6 files changed, 377 insertions(+), 71 deletions(-) create mode 100755 bin/generate-custom-set create mode 100644 exercises/custom-set/.version create mode 100644 exercises/custom-set/example.tt create mode 100644 lib/custom_set_cases.rb diff --git a/bin/generate-custom-set b/bin/generate-custom-set new file mode 100755 index 0000000000..885e39fb4d --- /dev/null +++ b/bin/generate-custom-set @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby + +require_relative '../lib/helper' +require 'generator' +require 'custom_set_cases' + +Generator.new('custom-set', CustomSetCases).generate diff --git a/exercises/custom-set/.version b/exercises/custom-set/.version new file mode 100644 index 0000000000..56a6051ca2 --- /dev/null +++ b/exercises/custom-set/.version @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/exercises/custom-set/custom_set_test.rb b/exercises/custom-set/custom_set_test.rb index e5f5b27e1e..ba89640a1b 100755 --- a/exercises/custom-set/custom_set_test.rb +++ b/exercises/custom-set/custom_set_test.rb @@ -3,114 +3,299 @@ require 'minitest/autorun' require_relative 'custom_set' +# Test data version: +# cdfb4a2 class CustomSetTest < Minitest::Test - def test_equal - assert_equal CustomSet.new([1, 3]), CustomSet.new([3, 1]) - refute_equal CustomSet.new([1, 3]), CustomSet.new([3, 1, 5]) - refute_equal CustomSet.new([1, 3, 5]), CustomSet.new([3, 1]) - refute_equal CustomSet.new([1, 3]), CustomSet.new([2, 1]) + def test_sets_with_no_elements_are_empty + # skip + set = CustomSet.new [] + assert_empty set end - def test_no_duplicates - assert_equal CustomSet.new([1, 1]), CustomSet.new([1]) + def test_sets_with_elements_are_not_empty + skip + set = CustomSet.new [1] + refute_empty set + end + + def test_nothing_is_contained_in_an_empty_set + skip + set = CustomSet.new [] + element = 1 + refute set.member? element + end + + def test_when_the_element_is_in_the_set + skip + set = CustomSet.new [1, 2, 3] + element = 1 + assert set.member? element end - def test_delete + def test_when_the_element_is_not_in_the_set skip - assert_equal CustomSet.new([1, 3]), CustomSet.new([3, 2, 1]).delete(2) - assert_equal CustomSet.new([1, 2, 3]), CustomSet.new([3, 2, 1]).delete(4) - assert_equal CustomSet.new([1, 2, 3]), CustomSet.new([3, 2, 1]).delete(2.0) - assert_equal CustomSet.new([1, 3]), CustomSet.new([3, 2.0, 1]).delete(2.0) + set = CustomSet.new [1, 2, 3] + element = 4 + refute set.member? element end - def test_difference + def test_empty_set_is_a_subset_of_another_empty_set skip - assert_equal CustomSet.new([1, 3]), - CustomSet.new([1, 2, 3]).difference(CustomSet.new([2, 4])) + set1 = CustomSet.new [] + set2 = CustomSet.new [] + assert set1.subset? set2 + end - assert_equal CustomSet.new([1, 2.0, 3]), - CustomSet.new([1, 2.0, 3]).difference(CustomSet.new([2, 4])) + def test_empty_set_is_a_subset_of_non_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [1] + assert set1.subset? set2 end - def test_disjoint? + def test_non_empty_set_is_not_a_subset_of_empty_set skip - assert CustomSet.new([1, 2]).disjoint?(CustomSet.new([3, 4])) - refute CustomSet.new([1, 2]).disjoint?(CustomSet.new([2, 3])) - assert CustomSet.new([1.0, 2.0]).disjoint?(CustomSet.new([2, 3])) - assert CustomSet.new.disjoint?(CustomSet.new) + set1 = CustomSet.new [1] + set2 = CustomSet.new [] + refute set1.subset? set2 end - def test_empty + def test_set_is_a_subset_of_set_with_exact_same_elements skip - assert_equal CustomSet.new, CustomSet.new([1, 2]).empty - assert_equal CustomSet.new, CustomSet.new.empty + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [1, 2, 3] + assert set1.subset? set2 + end + + def test_set_is_a_subset_of_larger_set_with_same_elements + skip + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [4, 1, 2, 3] + assert set1.subset? set2 + end + + def test_set_is_not_a_subset_of_set_that_does_not_contain_its_elements + skip + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [4, 1, 3] + refute set1.subset? set2 + end + + def test_the_empty_set_is_disjoint_with_itself + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [] + assert set1.disjoint? set2 + end + + def test_empty_set_is_disjoint_with_non_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [1] + assert set1.disjoint? set2 + end + + def test_non_empty_set_is_disjoint_with_empty_set + skip + set1 = CustomSet.new [1] + set2 = CustomSet.new [] + assert set1.disjoint? set2 + end + + def test_sets_are_not_disjoint_if_they_share_an_element + skip + set1 = CustomSet.new [1, 2] + set2 = CustomSet.new [2, 3] + refute set1.disjoint? set2 + end + + def test_sets_are_disjoint_if_they_share_no_elements + skip + set1 = CustomSet.new [1, 2] + set2 = CustomSet.new [3, 4] + assert set1.disjoint? set2 + end + + def test_empty_sets_are_equal + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [] + assert_equal set1, set2 + end + + def test_empty_set_is_not_equal_to_non_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [1, 2, 3] + refute_equal set1, set2 + end + + def test_non_empty_set_is_not_equal_to_empty_set + skip + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [] + refute_equal set1, set2 + end + + def test_sets_with_the_same_elements_are_equal + skip + set1 = CustomSet.new [1, 2] + set2 = CustomSet.new [2, 1] + assert_equal set1, set2 + end + + def test_sets_with_different_elements_are_not_equal + skip + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [1, 2, 4] + refute_equal set1, set2 + end + + def test_add_to_empty_set + skip + set = CustomSet.new [] + expected = CustomSet.new [3] + assert_equal expected, set.add(3) + end + + def test_add_to_non_empty_set + skip + set = CustomSet.new [1, 2, 4] + expected = CustomSet.new [1, 2, 3, 4] + assert_equal expected, set.add(3) + end + + def test_adding_an_existing_element_does_not_change_the_set + skip + set = CustomSet.new [1, 2, 3] + expected = CustomSet.new [1, 2, 3] + assert_equal expected, set.add(3) + end + + def test_intersection_of_two_empty_sets_is_an_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [] + expected = CustomSet.new [] + assert_equal expected, set2.intersection(set1) + end + + def test_intersection_of_an_empty_set_and_non_empty_set_is_an_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [3, 2, 5] + expected = CustomSet.new [] + assert_equal expected, set2.intersection(set1) + end + + def test_intersection_of_a_non_empty_set_and_an_empty_set_is_an_empty_set + skip + set1 = CustomSet.new [1, 2, 3, 4] + set2 = CustomSet.new [] + expected = CustomSet.new [] + assert_equal expected, set2.intersection(set1) + end + + def test_intersection_of_two_sets_with_no_shared_elements_is_an_empty_set + skip + set1 = CustomSet.new [1, 2, 3] + set2 = CustomSet.new [4, 5, 6] + expected = CustomSet.new [] + assert_equal expected, set2.intersection(set1) end # rubocop:disable Metrics/LineLength - def test_intersection + def test_intersection_of_two_sets_with_shared_elements_is_a_set_of_the_shared_elements skip - assert_equal CustomSet.new([:a, :c]), - CustomSet.new([:a, :b, :c]).intersection(CustomSet.new([:a, :c, :d])) + set1 = CustomSet.new [1, 2, 3, 4] + set2 = CustomSet.new [3, 2, 5] + expected = CustomSet.new [2, 3] + assert_equal expected, set2.intersection(set1) + end - assert_equal CustomSet.new([3]), - CustomSet.new([1, 2, 3]).intersection(CustomSet.new([1.0, 2.0, 3])) + def test_difference_of_two_empty_sets_is_an_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [] + expected = CustomSet.new [] + assert_equal expected, set1.difference(set2) end - def test_member? + def test_difference_of_empty_set_and_non_empty_set_is_an_empty_set skip - assert CustomSet.new([1, 2, 3]).member?(2) - assert CustomSet.new(1..3).member?(2) - refute CustomSet.new(1..3).member?(2.0) - refute CustomSet.new(1..3).member?(4) + set1 = CustomSet.new [] + set2 = CustomSet.new [3, 2, 5] + expected = CustomSet.new [] + assert_equal expected, set1.difference(set2) end - def test_put + def test_difference_of_a_non_empty_set_and_an_empty_set_is_the_non_empty_set skip - assert_equal CustomSet.new([1, 2, 3, 4]), - CustomSet.new([1, 2, 4]).put(3) + set1 = CustomSet.new [1, 2, 3, 4] + set2 = CustomSet.new [] + expected = CustomSet.new [1, 2, 3, 4] + assert_equal expected, set1.difference(set2) + end - assert_equal CustomSet.new([1, 2, 3]), - CustomSet.new([1, 2, 3]).put(3) + def test_difference_of_two_non_empty_sets_is_a_set_of_elements_that_are_only_in_the_first_set + skip + set1 = CustomSet.new [3, 2, 1] + set2 = CustomSet.new [2, 4] + expected = CustomSet.new [1, 3] + assert_equal expected, set1.difference(set2) + end - assert_equal CustomSet.new([1, 2, 3, 3.0]), - CustomSet.new([1, 2, 3]).put(3.0) + def test_union_of_empty_sets_is_an_empty_set + skip + set1 = CustomSet.new [] + set2 = CustomSet.new [] + expected = CustomSet.new [] + assert_equal expected, set1.union(set2) end - def test_size + def test_union_of_an_empty_set_and_non_empty_set_is_the_non_empty_set skip - assert_equal 0, CustomSet.new.size - assert_equal 3, CustomSet.new([1, 2, 3]).size - assert_equal 3, CustomSet.new([1, 2, 3, 2]).size + set1 = CustomSet.new [] + set2 = CustomSet.new [2] + expected = CustomSet.new [2] + assert_equal expected, set1.union(set2) end - def test_subset? + def test_union_of_a_non_empty_set_and_empty_set_is_the_non_empty_set skip - assert CustomSet.new([1, 2, 3]).subset?(CustomSet.new([1, 2, 3])) - assert CustomSet.new([4, 1, 2, 3]).subset?(CustomSet.new([1, 2, 3])) - refute CustomSet.new([4, 1, 3]).subset?(CustomSet.new([1, 2, 3])) - refute CustomSet.new([1, 2, 3, 4]).subset?(CustomSet.new([1, 2, 3.0])) - assert CustomSet.new([4, 1, 3]).subset?(CustomSet.new) - assert CustomSet.new.subset?(CustomSet.new) + set1 = CustomSet.new [1, 3] + set2 = CustomSet.new [] + expected = CustomSet.new [1, 3] + assert_equal expected, set1.union(set2) end - def test_to_a + def test_union_of_non_empty_sets_contains_all_unique_elements skip - assert_equal [], CustomSet.new.to_a.sort - assert_equal [1, 2, 3], CustomSet.new([3, 1, 2]).to_a.sort - assert_equal [1, 2, 3], CustomSet.new([3, 1, 2, 1]).to_a.sort + set1 = CustomSet.new [1, 3] + set2 = CustomSet.new [2, 3] + expected = CustomSet.new [3, 2, 1] + assert_equal expected, set1.union(set2) end - def test_union # rubocop:disable Metrics/MethodLength + # 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 CustomSet.new([3, 2, 1]), - CustomSet.new([1, 3]).union(CustomSet.new([2])) - assert_equal CustomSet.new([3.0, 3, 2, 1]), - CustomSet.new([1, 3]).union(CustomSet.new([2, 3.0])) - assert_equal CustomSet.new([3, 1]), - CustomSet.new([1, 3]).union(CustomSet.new) - assert_equal CustomSet.new([2]), - CustomSet.new([2]).union(CustomSet.new) - assert_equal CustomSet.new([]), - CustomSet.new.union(CustomSet.new) + assert_equal 1, BookKeeping::VERSION end end diff --git a/exercises/custom-set/example.rb b/exercises/custom-set/example.rb index f6d5e23b37..45fd794097 100644 --- a/exercises/custom-set/example.rb +++ b/exercises/custom-set/example.rb @@ -26,6 +26,10 @@ def empty CustomSet.new end + def empty? + size == 0 + end + def intersection(other) intersection = nodes.select do |node| other.nodes.any? { |other_node| other_node.eql?(node) } @@ -36,8 +40,9 @@ def intersection(other) def member?(datum) data.any? { |node| node.datum.eql?(datum) } end + alias include? member? - def put(datum) + def add(datum) unless data.any? { |node| node.datum.eql?(datum) } add_datum(datum) end @@ -49,8 +54,7 @@ def size end def subset?(other) - return true if other.data.empty? - other.nodes.all? { |other_node| nodes.any? { |node| node.eql?(other_node) } } + nodes.all? { |other_node| other.nodes.any? { |node| node.eql?(other_node) } } end def to_a @@ -90,3 +94,7 @@ def initialize(input_datum) @datum = input_datum end end + +module BookKeeping + VERSION = 1 +end diff --git a/exercises/custom-set/example.tt b/exercises/custom-set/example.tt new file mode 100644 index 0000000000..2c2e3e6065 --- /dev/null +++ b/exercises/custom-set/example.tt @@ -0,0 +1,19 @@ +#!/usr/bin/env ruby +gem 'minitest', '>= 5.0.0' +require 'minitest/autorun' +require_relative 'custom_set' + +# Test data version: +# <%= sha1 %> +class CustomSetTest < Minitest::Test<% test_cases.each do |test_case| %> + def <%= test_case.name %> + <%= test_case.skipped %> + <%= test_case.test_body %> + end +<% end %> +<%= IO.read(XRUBY_LIB + '/bookkeeping.md') %> + def test_bookkeeping + skip + assert_equal <%= version.next %>, BookKeeping::VERSION + end +end diff --git a/lib/custom_set_cases.rb b/lib/custom_set_cases.rb new file mode 100644 index 0000000000..3bd47c9688 --- /dev/null +++ b/lib/custom_set_cases.rb @@ -0,0 +1,86 @@ +class CustomSetCase < OpenStruct + def name + 'test_%s' % description.gsub(/ |-/, '_') + end + + def test_body + send section + end + + def union + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + expected = CustomSet.new #{expected} + #{assert_or_refute}_equal expected, set1.union(set2)" + end + + def difference + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + expected = CustomSet.new #{expected} + #{assert_or_refute}_equal expected, set1.difference(set2)" + end + + def intersection + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + expected = CustomSet.new #{expected} + #{assert_or_refute}_equal expected, set2.intersection(set1)" + end + + def add + "set = CustomSet.new #{set} + expected = CustomSet.new #{expected} + #{assert_or_refute}_equal expected, set.add(#{element})" + end + + def equal + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + #{assert_or_refute}_equal set1, set2" + end + + def disjoint + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + #{assert_or_refute} set1.disjoint? set2" + end + + def subset + "set1 = CustomSet.new #{set1} + set2 = CustomSet.new #{set2} + #{assert_or_refute} set1.subset? set2" + end + + def empty + "set = CustomSet.new #{set} + #{assert_or_refute}_empty set" + end + + def contains + "set = CustomSet.new #{set} + element = #{element} + #{assert_or_refute} set.member? element" + end + + def assert_or_refute + expected ? 'assert' : 'refute' + end + + def skipped + index.zero? ? '# skip' : 'skip' + end +end + +CustomSetCases = proc do |data| + json = JSON.parse(data) + cases = [] + i = 0 + (json.keys - ['#']).each do |section| + json[section]['cases'].each do |row| + cases << CustomSetCase.new(row.merge('index' => i, 'section' => section)) + i += 1 + end + end + cases +end