From f58de129fac3ce7da9e89a5bdd127f8362ec2438 Mon Sep 17 00:00:00 2001 From: Dimitar Apostolovski Date: Tue, 1 Oct 2024 10:42:18 +0200 Subject: [PATCH 1/4] [palindrome-products] Add missing tests --- .../palindrome-products/.meta/tests.toml | 24 ++++++ .../palindrome_products_test.rb | 74 +++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/exercises/practice/palindrome-products/.meta/tests.toml b/exercises/practice/palindrome-products/.meta/tests.toml index 2f02f4394f..a3bc41750a 100644 --- a/exercises/practice/palindrome-products/.meta/tests.toml +++ b/exercises/practice/palindrome-products/.meta/tests.toml @@ -9,6 +9,9 @@ # As user-added comments (using the # character) will be removed when this file # is regenerated, comments can be added via a `comment` key. +[5cff78fe-cf02-459d-85c2-ce584679f887] +description = "find the smallest palindrome from single digit factors" + [0853f82c-5fc4-44ae-be38-fadb2cced92d] description = "find the largest palindrome from single digit factors" @@ -23,3 +26,24 @@ description = "find the smallest palindrome from triple digit factors" [edab43e1-c35f-4ea3-8c55-2f31dddd92e5] description = "find the largest palindrome from triple digit factors" + +[4f802b5a-9d74-4026-a70f-b53ff9234e4e] +description = "find the smallest palindrome from four digit factors" + +[787525e0-a5f9-40f3-8cb2-23b52cf5d0be] +description = "find the largest palindrome from four digit factors" + +[58fb1d63-fddb-4409-ab84-a7a8e58d9ea0] +description = "empty result for smallest if no palindrome in the range" + +[9de9e9da-f1d9-49a5-8bfc-3d322efbdd02] +description = "empty result for largest if no palindrome in the range" + +[12e73aac-d7ee-4877-b8aa-2aa3dcdb9f8a] +description = "error result for smallest if min is more than max" + +[eeeb5bff-3f47-4b1e-892f-05829277bd74] +description = "error result for largest if min is more than max" + +[16481711-26c4-42e0-9180-e2e4e8b29c23] +description = "smallest product does not use the smallest factor" diff --git a/exercises/practice/palindrome-products/palindrome_products_test.rb b/exercises/practice/palindrome-products/palindrome_products_test.rb index fad80fcf26..c99ac6fadc 100644 --- a/exercises/practice/palindrome-products/palindrome_products_test.rb +++ b/exercises/practice/palindrome-products/palindrome_products_test.rb @@ -2,7 +2,16 @@ require_relative 'palindrome_products' class PalindromesTest < Minitest::Test + def test_smallest_palindrome_from_single_digit_factors + palindromes = Palindromes.new(max_factor: 9) + palindromes.generate + smallest = palindromes.smallest + assert_equal 1, smallest.value + assert_equal [[1, 1]], smallest.factors + end + def test_largest_palindrome_from_single_digit_factors + skip palindromes = Palindromes.new(max_factor: 9) palindromes.generate largest = palindromes.largest @@ -45,4 +54,69 @@ def test_smallest_palindrome_from_triple_digit_factors assert_equal 10_201, smallest.value assert_equal [[101, 101]], smallest.factors end + + def test_smallest_palindrome_from_four_digit_factors + skip + palindromes = Palindromes.new(min_factor: 1000, max_factor: 9999) + palindromes.generate + smallest = palindromes.smallest + assert_equal 1_002_001, smallest.value + assert_equal [[1001, 1001]], smallest.factors + end + + def test_largest_palindrome_from_four_digit_factors + skip + palindromes = Palindromes.new(min_factor: 1000, max_factor: 9999) + palindromes.generate + largest = palindromes.largest + assert_equal 99_000_099, largest.value + assert_equal [[9901, 9999]], largest.factors + end + + def test_empty_for_smallest_if_no_palindrome_in_range + skip + palindromes = Palindromes.new(min_factor: 1002, max_factor: 1003) + palindromes.generate + smallest = palindromes.smallest + assert_nil smallest.value + assert_empty smallest.factors + end + + def test_empty_for_largest_if_no_palindrome_in_range + skip + palindromes = Palindromes.new(min_factor: 15, max_factor: 15) + palindromes.generate + largest = palindromes.largest + assert_nil largest.value + assert_empty largest.factors + end + + def test_error_for_smallest_if_min_more_than_max + skip + error = assert_raises(ArgumentError) do + palindromes = Palindromes.new(min_factor: 10_000, max_factor: 1) + palindromes.generate + palindromes.smallest + end + assert_equal "min must be <= max", error.message + end + + def test_error_for_largest_if_min_more_than_max + skip + error = assert_raises(ArgumentError) do + palindromes = Palindromes.new(min_factor: 2, max_factor: 1) + palindromes.generate + palindromes.smallest + end + assert_equal "min must be <= max", error.message + end + + def test_smallest_palindrome_does_not_use_smallest_factors + skip + palindromes = Palindromes.new(min_factor: 3215, max_factor: 4000) + palindromes.generate + smallest = palindromes.smallest + assert_equal 10_988_901, smallest.value + assert_equal [[3297, 3333]], smallest.factors + end end From 92729776adf9526fba12a2c6e9653c3b985dcb20 Mon Sep 17 00:00:00 2001 From: Dimitar Apostolovski Date: Tue, 1 Oct 2024 15:07:26 +0200 Subject: [PATCH 2/4] [palindrome-products] Update example solution --- .../palindrome-products/.meta/example.rb | 49 +++++++++---------- .../palindrome-products/.meta/example_2.rb | 47 ------------------ 2 files changed, 23 insertions(+), 73 deletions(-) delete mode 100644 exercises/practice/palindrome-products/.meta/example_2.rb diff --git a/exercises/practice/palindrome-products/.meta/example.rb b/exercises/practice/palindrome-products/.meta/example.rb index 2e761d28aa..f4f58b5081 100644 --- a/exercises/practice/palindrome-products/.meta/example.rb +++ b/exercises/practice/palindrome-products/.meta/example.rb @@ -1,43 +1,40 @@ Palindrome = Struct.new(:value, :factors) class Palindromes - attr_reader :range - def initialize(options) - max = options.fetch(:max_factor) - min = options.fetch(:min_factor) { 1 } - @range = (min..max) - end + private + attr_reader :min, :max - def generate - @palindromes = {} - range.each do |i| - range.each do |j| - product = i * j - if palindrome?(product) - palindrome = @palindromes[product] || Palindrome.new(product, []) - palindrome.factors << [i, j].sort - palindrome.factors.uniq! - @palindromes[product] = palindrome - end - end - end + def initialize(max_factor:, min_factor: 1) + raise ArgumentError, "min must be <= max" unless min_factor <= max_factor + + @min = min_factor + @max = max_factor end def palindrome?(number) number.to_s == number.to_s.reverse end - def sort - @palindromes.sort_by do |key, _palindrome| - key + def factors(palindrome) + (min..Math.sqrt(palindrome)).each_with_object([]) do |number, factors| + div, mod = palindrome.divmod(number) + factors << [number, div] if div.between?(min, max) && mod.zero? end end - def largest - sort.last[1] + def find_palindrome(enum) + enum.lazy. + filter { |number| palindrome? number }. + map { |number| Palindrome.new number, factors(number) }. + find { |palindrome| !palindrome.factors.empty? } end - def smallest - sort.first[1] + public + attr_reader :smallest, :largest + + def generate + @smallest = find_palindrome(min**2..max**2) || Palindrome.new(nil, []) + + @largest = find_palindrome((max**2..min**2).step(-1)) || Palindrome.new(nil, []) end end diff --git a/exercises/practice/palindrome-products/.meta/example_2.rb b/exercises/practice/palindrome-products/.meta/example_2.rb deleted file mode 100644 index ce989be8d8..0000000000 --- a/exercises/practice/palindrome-products/.meta/example_2.rb +++ /dev/null @@ -1,47 +0,0 @@ -Palindrome = Struct.new(:value, :factors) - -class Palindromes - - private - - attr_reader :range, :candidates - - def initialize(min_factor: 1, max_factor: 9) - @range = (min_factor..max_factor) - end - - def factors(palindrome) - range.each_with_object([]) do |number, factors| - div, mod = palindrome.divmod(number) - if div <= number && range.include?(div) && mod.zero? - factors << [div, number] - end - end - end - - def palindrome_and_factors(palindrome) - Palindrome.new palindrome, factors(palindrome) - end - - public - - def generate - @candidates ||= range.each_with_object([]) do |r1, candidates| - (r1..range.last).each do |r2| - candidate = r1 * r2 - if candidate == candidate.to_s.reverse.to_i - candidates << candidate - end - end - end - end - - def largest - @largest ||= palindrome_and_factors(candidates.max) - end - - def smallest - @smallest ||= palindrome_and_factors(candidates.min) - end - -end From f52235b03096ecc65b0770605c8deda770619867 Mon Sep 17 00:00:00 2001 From: Dimitar Apostolovski Date: Thu, 3 Oct 2024 10:29:17 +0200 Subject: [PATCH 3/4] [palindrome-products] Update config.json --- exercises/practice/palindrome-products/.meta/config.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/exercises/practice/palindrome-products/.meta/config.json b/exercises/practice/palindrome-products/.meta/config.json index 3c4443e141..c5554bd6a7 100644 --- a/exercises/practice/palindrome-products/.meta/config.json +++ b/exercises/practice/palindrome-products/.meta/config.json @@ -12,7 +12,8 @@ "Insti", "kotp", "markijbema", - "tryantwit" + "tryantwit", + "themetar" ], "files": { "solution": [ From 552375e54fc861c669bfc98588da0559f781fb98 Mon Sep 17 00:00:00 2001 From: Dimitar Apostolovski Date: Wed, 9 Oct 2024 10:03:25 +0200 Subject: [PATCH 4/4] [palindrome-products] Fix formatting (example.rb) --- exercises/practice/palindrome-products/.meta/example.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/practice/palindrome-products/.meta/example.rb b/exercises/practice/palindrome-products/.meta/example.rb index f4f58b5081..ef98d0410d 100644 --- a/exercises/practice/palindrome-products/.meta/example.rb +++ b/exercises/practice/palindrome-products/.meta/example.rb @@ -2,6 +2,7 @@ class Palindromes private + attr_reader :min, :max def initialize(max_factor:, min_factor: 1) @@ -30,6 +31,7 @@ def find_palindrome(enum) end public + attr_reader :smallest, :largest def generate