Skip to content

Sync palindrome products exercise with problem specification #1722

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

Merged
merged 4 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
49 changes: 23 additions & 26 deletions exercises/practice/palindrome-products/.meta/example.rb
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private
attr_reader :min, :max
private
attr_reader :min, :max

Copy link
Contributor Author

@themetar themetar Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vscode kept triggering rubocop and auto-formatting my code. I assumed that that's exercism's style.

I think this is the rule that's being followed:

ruby/.rubocop.yml

Lines 37 to 38 in fa35ccc

Layout/EmptyLinesAroundAccessModifier:
EnforcedStyle: only_before

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is stating that it is only enforcing the empty line before. But, while we are not enforcing that there is a blank line after (because sometimes that really does make sense) we may have a blank line, and so should likely have a blank line after, since the communication value is there.


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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public
attr_reader :smallest, :largest
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