1
\$\begingroup\$

Pentagonal numbers are generated by the formula, \$P_n=\frac{n(3n−1)}{2}\$. The first ten pentagonal numbers are:

1, 5, 12, 22, 35, 51, 70, 92, 117, 145

It can be seen that \$P_4 + P_7 = 22 + 70 = 92 = P_8\$. However, their difference, \$70 − 22 = 48\$, is not pentagonal.

Find the pair of pentagonal numbers, \$P_j\$ and \$P_k\$, for which their sum and difference are pentagonal and \$D = |P_k − P_j|\$ is minimised; what is the value of D?

Awaiting feedback.

from time import time


def generate_pentagons(n):
    """generates next n pentagons"""
    pentagons = (num * (3 * num - 1) // 2 for num in range(1, n))
    for i in range(n - 1):
        yield next(pentagons)


def get_pentagons(n):
    """Assumes n is a range > 0.
    generates pentagons that obey to the + - rules."""
    pentagons = set(generate_pentagons(n))
    for pentagon1 in pentagons:
        for pentagon2 in pentagons:
            if pentagon1 + pentagon2 in pentagons and abs(pentagon1 - pentagon2) in pentagons:
                return pentagon1, pentagon2


if __name__ == '__main__':
    start_time = time()
    pent1, pent2 = get_pentagons(10000)
    print(abs(pent1 - pent2))
    print(f'Time: {time() - start_time} seconds.')
\$\endgroup\$
  • 1
    \$\begingroup\$ Why do you ignore the repeated advice (1, 2) to tag Python questions correctly? \$\endgroup\$ – Martin R Jul 22 at 5:17
  • \$\begingroup\$ I'm sorry if I seem to be ignoring your advice but in fact, 'python-3.x' as well as 'programming-challenge' are already tagged. I don't know what's wrong here. \$\endgroup\$ – emadboctor Jul 22 at 5:24
  • \$\begingroup\$ check under the code block, you must see them I guess. \$\endgroup\$ – emadboctor Jul 22 at 5:25
  • 1
    \$\begingroup\$ From the first referenced comment: “Please tag all Python questions with [python], ...” \$\endgroup\$ – Martin R Jul 22 at 5:28
  • 7
    \$\begingroup\$ You're averaging 5 questions a day. Some of the downvotes might be from people who think you should take things a lot slower, waiting for answers to one question so that you can apply the same principles to your next program. \$\endgroup\$ – Peter Taylor Jul 22 at 7:18
2
\$\begingroup\$

This is an answer focused primarily about styling

  • Your parameter names can be renamed to be more specific, like generate_pentagons(n) can be rewritten to generate_pentagons(number_of_pentagons). This change can also be implemented in the get_pentagons method. While this may seem useless in this program, since n can be easily interpreted as the number of pentagons to generate, it's a good practice to follow when you start writing large programs that require more specific parameter names.
  • Parameter constants should be UPPERCASE.
  • You don't use i in your loop in generate_pentagons method. To avoid generating an unused variable, you can use an underscore. The _ immediately signals the reader that the value is not important.

Final Code

from time import time


def generate_pentagons(number_of_pentagons):
    """generates next n pentagons"""
    pentagons = (num * (3 * num - 1) // 2 for num in range(1, number_of_pentagons))
    for _ in range(number_of_pentagons - 1):
        yield next(pentagons)


def get_pentagons(number_of_pentagons):
    """Assumes n is a range > 0. Generates pentagons that obey to the + - rules."""
    pentagons = set(generate_pentagons(number_of_pentagons))
    for pentagon1 in pentagons:
        for pentagon2 in pentagons:
            if pentagon1 + pentagon2 in pentagons and abs(pentagon1 - pentagon2) in pentagons:
                return pentagon1, pentagon2

if __name__ == '__main__':
    START_TIME = time()
    PENTAGON_1, PENTAGON_2 = get_pentagons(10000)
    print(abs(PENTAGON_1 - PENTAGON_2))
    print(f"Time: {time() - START_TIME} seconds.")
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.