Make a table test would already make you realize the mistake: entrada
is the amount of pairs that you must return to, but in for
you are using range(3, entrada + 1, 2)
, that is, that for
only checks the numbers until entrada
.
Therefore, when entrada
is 3
, the range
only goes up to 3, and inside the for
, as you test j
and j + 2
, in which case you will always be testing only 3 and 5.
So you should actually use entrada
only to control the amount of pairs already generated. Already the numbers to be tested should have no limit, because you do not know which number will be in the nth pair.
Other points to improve is that you can start at 3
(for I know (2, 3) that they are not twin cousins). And the algorithm gives to improve a little: as I already start excluding the 2, I do not need to test it, and also do not need to test even numbers. Also, from the 5, all prime numbers are of the form 6k - 1
or 6k + 1
(that is, they are predecessors or successors of a multiple of 6), so I can check only those values. And the loop can go to the square root of the number.
Then it would be:
from math import sqrt
# ATENÇÃO: **nesse caso específico**, como eu não testo o 2,
# estou deliberadamente ignorando ele e os demais números pares
def primo(n):
if n == 3:
return True
if n % 3 == 0:
return False
i = 5
limite = int(sqrt(n)) + 1
while i < limite:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
quantidade = int(input())
lista = []
# começo no 3, pois sei que (2, 3) não são gêmeos
n = 3
while True:
if primo(n) and primo(n + 2):
lista.append((n, n + 2))
if len(lista) == quantidade: # se já tenho a quantidade de pares, interrompe o while
break
n += 2
print(lista)
Heed: As I only call the function primo
passing odd numbers, so inside it I don’t check if the number is even. But if it was a general purpose function, to check if any number is prime, then you would have to check (it would be thus).
There is only one detail: see while
i test n
and n + 2
.
That means that in the first iteration I test if 3 and 5 are cousins. Then, in the second iteration, I test whether 5 and 7 are primes, then I test 7 and 9, then 9 and 11, etc. Note that there are several numbers being tested 2 times, no need. So you can optimize a little bit, causing them to be tested only once, and reuse this information in the next iteration:
lista = []
proxPrimo = None
# começo no 3, pois sei que (2, 3) não são gêmeos
n = 3
atualPrimo = primo(n)
while True:
proxPrimo = primo(n + 2)
if atualPrimo and proxPrimo:
lista.append((n, n + 2))
if len(lista) == quantidade:
break
atualPrimo = proxPrimo
n += 2
print(lista)
Very good. I assume we can also discard pairs soon? https://ideone.com/CheTnL
– Miguel
@Miguel In this specific case, as I am calling the function
primo
for odd numbers only, I ignored the pairs on purpose (see the comment in the code: "as I do not test the 2, I am deliberately ignoring it and the other even numbers". But for a general purpose function, then yes, it should test if the number is even and discard right away - the only exception is 2 itself, so it would have to be like this: https://ideone.com/zlnWdd– hkotsubo
Of course, of course... my distraction
– Miguel
@Miguel Anyway, I edited the reply, making this point clearer. Thank you!
– hkotsubo