Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync palindrome products exercise with problem specification #1722

Merged
merged 4 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion exercises/practice/palindrome-products/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"Insti",
"kotp",
"markijbema",
"tryantwit"
"tryantwit",
"themetar"
],
"files": {
"solution": [
Expand Down
51 changes: 25 additions & 26 deletions exercises/practice/palindrome-products/.meta/example.rb
Original file line number Diff line number Diff line change
@@ -1,43 +1,42 @@
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

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
attr_reader :min, :max

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
47 changes: 0 additions & 47 deletions exercises/practice/palindrome-products/.meta/example_2.rb

This file was deleted.

24 changes: 24 additions & 0 deletions exercises/practice/palindrome-products/.meta/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"
74 changes: 74 additions & 0 deletions exercises/practice/palindrome-products/palindrome_products_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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