diff --git a/exercises/palindrome-products/example.py b/exercises/palindrome-products/example.py index 4330be1e13..2139feeaa0 100644 --- a/exercises/palindrome-products/example.py +++ b/exercises/palindrome-products/example.py @@ -3,12 +3,12 @@ from math import log10, floor, ceil -def largest_palindrome(max_factor, min_factor): +def largest(min_factor, max_factor): return get_extreme_palindrome_with_factors(max_factor, min_factor, "largest") -def smallest_palindrome(max_factor, min_factor): +def smallest(max_factor, min_factor): return get_extreme_palindrome_with_factors(max_factor, min_factor, "smallest") @@ -17,37 +17,36 @@ def get_extreme_palindrome_with_factors(max_factor, min_factor, extreme): palindromes_found = palindromes(max_factor, min_factor, reverse=(extreme == "largest")) factor_pairs = None - for palin in palindromes_found: - factor_pairs = ((fact, palin // fact) - for fact in range(min_factor, max_factor + 1) - if palin % fact == 0) + for palindrome in palindromes_found: + factor_pairs = ((factor, palindrome // factor) + for factor in range(min_factor, max_factor + 1) + if palindrome % factor == 0) factor_pairs = list(pair for pair in factor_pairs if min_factor <= pair[1] <= max_factor) if len(factor_pairs) > 0: break - if factor_pairs is None or len(factor_pairs) == 0: + if not factor_pairs: return (None, []) - return (palin, factor_pairs) + return (palindrome, factor_pairs) -def reverse_num(n): - rev = 0 - while n > 0: - rev *= 10 - rev += (n % 10) - n //= 10 - return rev +def reverse_num(number): + reversed = 0 + while number > 0: + reversed *= 10 + reversed += (number % 10) + number //= 10 + return reversed -def num_digits(n): - return int(floor(log10(n) + 1)) +def num_digits(number): + return int(floor(log10(number) + 1)) def palindromes(max_factor, min_factor, reverse=False): """Generates all palindromes between `min_factor`**2 and max_factor`**2 - If `reverse` is True, will produce the palindromes in decreasing order, from `max_factor`**2 down to `min_factor`**2. This is needed for `largest_palindrome`, since it won't have to iterate through a @@ -62,19 +61,18 @@ def palindromes(max_factor, min_factor, reverse=False): minimum = min_factor ** 2 maximum = max_factor ** 2 - def gen_palins_of_length(nd, reverse=reverse): + def gen_palindromes_of_length(num_digits, reverse=reverse): """Generates all palindromes with `nd` number of digits that are within the desired range. - Again, if `reverse` is True, the palindromes are generated in reverse order. """ - even_nd = (nd % 2 == 0) + even_nd = (num_digits % 2 == 0) - min_left_half = max(10 ** (int(ceil(nd / 2)) - 1), - minimum // (10 ** (nd // 2))) - max_left_half = min((10 ** int(ceil(nd / 2))) - 1, - maximum // (10 ** (nd // 2))) + min_left_half = max(10 ** (int(ceil(num_digits / 2)) - 1), + minimum // (10 ** (num_digits // 2))) + max_left_half = min((10 ** int(ceil(num_digits / 2))) - 1, + maximum // (10 ** (num_digits // 2))) current_left_half = min_left_half if not reverse else max_left_half @@ -82,14 +80,14 @@ def make_palindrome(left_half, even_nd=False): right_half = (reverse_num(left_half) if even_nd else reverse_num(left_half // 10)) - return (left_half * (10 ** (nd // 2))) + right_half + return (left_half * (10 ** (num_digits // 2))) + right_half if not reverse: while current_left_half <= max_left_half: - palin = make_palindrome(current_left_half, even_nd) - if minimum <= palin <= maximum: - yield palin - elif palin > maximum: + palindrome = make_palindrome(current_left_half, even_nd) + if minimum <= palindrome <= maximum: + yield palindrome + elif palindrome > maximum: # since palindromes are generated in increasing order, # we break out of the loop once we've exceeded the # maximum value @@ -97,20 +95,21 @@ def make_palindrome(left_half, even_nd=False): current_left_half += 1 else: while current_left_half >= min_left_half: - palin = make_palindrome(current_left_half, even_nd) - if minimum <= palin <= maximum: - yield palin - elif palin < minimum: + palindrome = make_palindrome(current_left_half, even_nd) + if minimum <= palindrome <= maximum: + yield palindrome + elif palindrome < minimum: # since palindromes are generated in decreasing order, # we break out of the loop once we've gone below the # minimum value break current_left_half -= 1 - min_nd, max_nd = num_digits(minimum), num_digits(maximum) + min_nd = num_digits(minimum) + max_nd = num_digits(maximum) lengths = (range(min_nd, max_nd + 1) if not reverse else range(max_nd, min_nd - 1, -1)) - return chain(*map(gen_palins_of_length, lengths)) + return chain(*map(gen_palindromes_of_length, lengths)) diff --git a/exercises/palindrome-products/palindrome_products.py b/exercises/palindrome-products/palindrome_products.py index 951888d4bc..7c138b801c 100644 --- a/exercises/palindrome-products/palindrome_products.py +++ b/exercises/palindrome-products/palindrome_products.py @@ -1,6 +1,6 @@ -def largest_palindrome(max_factor, min_factor): +def largest(min_factor, max_factor): pass -def smallest_palindrome(max_factor, min_factor): +def smallest(min_factor, max_factor): pass diff --git a/exercises/palindrome-products/palindrome_products_test.py b/exercises/palindrome-products/palindrome_products_test.py index 11ece4dc15..3735efb21c 100644 --- a/exercises/palindrome-products/palindrome_products_test.py +++ b/exercises/palindrome-products/palindrome_products_test.py @@ -1,6 +1,6 @@ """ -Notes regarding the implementation of smallest_palindrome and -largest_palindrome: +Notes regarding the implementation of smallest and +largest: Both functions must take two keyword arguments: max_factor -- int @@ -13,70 +13,69 @@ import unittest -from palindrome_products import smallest_palindrome, largest_palindrome +from palindrome_products import smallest, largest # Tests adapted from `problem-specifications//canonical-data.json` @ v1.2.0 class PalindromeProductsTest(unittest.TestCase): def test_smallest_palindrome_from_single_digit_factors(self): - value, factors = smallest_palindrome(min_factor=1, max_factor=9) + value, factors = smallest(min_factor=1, max_factor=9) self.assertEqual(value, 1) - self.assertFactorsEqual(factors, {(1, 1)}) + self.assertFactorsEqual(factors, [[1, 1]]) def test_largest_palindrome_from_single_digit_factors(self): - value, factors = largest_palindrome(min_factor=1, max_factor=9) + value, factors = largest(min_factor=1, max_factor=9) self.assertEqual(value, 9) - self.assertFactorsEqual(factors, {(1, 9), (3, 3)}) + self.assertFactorsEqual(factors, [[1, 9], [3, 3]]) def test_smallest_palindrome_from_double_digit_factors(self): - value, factors = smallest_palindrome(min_factor=10, max_factor=99) + value, factors = smallest(min_factor=10, max_factor=99) self.assertEqual(value, 121) - self.assertFactorsEqual(factors, {(11, 11)}) + self.assertFactorsEqual(factors, [[11, 11]]) def test_largest_palindrome_from_double_digit_factors(self): - value, factors = largest_palindrome(min_factor=10, max_factor=99) + value, factors = largest(min_factor=10, max_factor=99) self.assertEqual(value, 9009) - self.assertFactorsEqual(factors, {(91, 99)}) + self.assertFactorsEqual(factors, [[91, 99]]) def test_smallest_palindrome_from_triple_digit_factors(self): - value, factors = smallest_palindrome(min_factor=100, max_factor=999) + value, factors = smallest(min_factor=100, max_factor=999) self.assertEqual(value, 10201) - self.assertFactorsEqual(factors, {(101, 101)}) + self.assertFactorsEqual(factors, [[101, 101]]) def test_largest_palindrome_from_triple_digit_factors(self): - value, factors = largest_palindrome(min_factor=100, max_factor=999) + value, factors = largest(min_factor=100, max_factor=999) self.assertEqual(value, 906609) - self.assertFactorsEqual(factors, {(913, 993)}) + self.assertFactorsEqual(factors, [[913, 993]]) def test_smallest_palindrome_from_four_digit_factors(self): - value, factors = smallest_palindrome(min_factor=1000, max_factor=9999) + value, factors = smallest(min_factor=1000, max_factor=9999) self.assertEqual(value, 1002001) - self.assertFactorsEqual(factors, {(1001, 1001)}) + self.assertFactorsEqual(factors, [[1001, 1001]]) def test_largest_palindrome_from_four_digit_factors(self): - value, factors = largest_palindrome(min_factor=1000, max_factor=9999) + value, factors = largest(min_factor=1000, max_factor=9999) self.assertEqual(value, 99000099) - self.assertFactorsEqual(factors, {(9901, 9999)}) + self.assertFactorsEqual(factors, [[9901, 9999]]) def test_empty_for_smallest_palindrome_if_none_in_range(self): - value, factors = smallest_palindrome(min_factor=1002, max_factor=1003) + value, factors = smallest(min_factor=1002, max_factor=1003) self.assertIsNone(value) self.assertFactorsEqual(factors, []) def test_empty_for_largest_palindrome_if_none_in_range(self): - value, factors = largest_palindrome(min_factor=15, max_factor=15) + value, factors = largest(min_factor=15, max_factor=15) self.assertIsNone(value) self.assertFactorsEqual(factors, []) - def test_error_for_smallest_if_min_is_more_than_max(self): + def test_error_for_smallest_palindrome_if_min_is_more_than_max(self): with self.assertRaisesWithMessage(ValueError): - value, factors = smallest_palindrome(min_factor=10000, - max_factor=1) + value, factors = smallest(min_factor=10000, max_factor=1) - def test_error_for_largest_if_min_is_more_than_max(self): + def test_error_for_largest_palindrome_if_min_is_more_than_max(self): with self.assertRaisesWithMessage(ValueError): - value, factors = largest_palindrome(min_factor=2, max_factor=1) + value, factors = largest(min_factor=2, max_factor=1) # Utility functions def setUp(self):