How to return a list where the size is set according to a number typed in the python input?

Asked

Viewed 195 times

1

I would like the code I wrote to return a number of tuples according to the value entered in the input, for example, if the input is 3, the return will have to be 3 pairs of tuples. The following image will make it clearer. inserir a descrição da imagem aqui

Here is my code:

"""Números primos gêmeos são pares de números primos (p1, p2) tais que p2=p1+2.

Implemente uma função chamada primos_gemeos que recebe um número inteiro n e 
retorna os n primeiros pares de números primos gêmeos, conforme formatação indicada abaixo."""
def primos_gemeos(num):
  valor = False
  for n in range(2, num):
     if num % n == 0:
        break
  else:
     valor = True
  return valor

entrada = int(input())
i = 0
lista = []
while i < entrada:
  for j in range(3, entrada + 1, 2):
     if primos_gemeos(j) and primos_gemeos(j + 2):
        lista.append((j, j + 2))
        i += 1
print(lista)
    
primos_gemeos(entrada)

In my code what I tried to do was a while that repeats while i < input and increments 1 after append, but the return is repeating the pairs, for example, when the input is 3, the output would have to be like this: [(3, 5), (5, 7), (11, 13)] But when I exit my code it’s like this: [(3, 5), (3, 5), (3, 5)] Where I went wrong?

2 answers

2

One of the problems with code (and perhaps the only one without having tested) is that you are not changing (increasing) the value of j, so you always end up with the same values.

What are Twin Prime Numbers?

An implementation can be done like this:

def e_primo(num): # verificar se e primo
    return all(num%i!=0 for i in range(2,num)) 

qtd_tuples = 10 # input
results = [] # armazenar resultados
curr_prime = 1
while len(results) < qtd_tuples: # enquanto a quantidade de tuplas for inferior ao nosso input
    curr_prime += 2
    if(e_primo(curr_prime) and e_primo(curr_prime+2)):
        results.append((curr_prime, curr_prime+2))

print(results)

Output:

[(3, 5), (5, 7), (11, 13), (17, 19), (29, 31), (41, 43), (59, 61), (71, 73), (101, 103), (107, 109)]

DEMONSTRATION

1

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 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

  • Of course, of course... my distraction

  • @Miguel Anyway, I edited the reply, making this point clearer. Thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.