2016-08-03 4 views
4

Я написал эту программу, которая сообщит вам два кратных факторов вашего входа. Ex. если бы я должен был ввести 35 (полупервичный), программа напечатала 5 и 7, которые являются двумя простыми числами, умноженными на 35.Лучший способ выполнить вычисления в списке/кортеже в Python 3x

Но мне интересно, есть ли более краткий или питонический способ перебора этот кортеж, поэтому мне не пришлось бы кодировать все эти утверждения «elif», которые вы видите ниже.

Также было бы здорово, если бы мне не пришлось полагаться на какие-либо внешние библиотеки.

# multiples of semiprimes 4 - 49 
tuple1 = (2, 3, 5, 7) 

# tuple 1 calculations 
while True: 

     try: 
       semiprime = int(input('Enter Semiprime: ')) 

     except ValueError: 
       print('INPUT MUST BE AN INTEGER') 
       continue 

     # index 0 - 3 
     if (tuple1[0]) * (tuple1[0]) == semiprime: 
       print((tuple1[0]), (tuple1[0])) 

     elif (tuple1[0]) * (tuple1[1]) == semiprime: 
       print((tuple1[0]), (tuple1[1])) 

     elif (tuple1[0]) * (tuple1[2]) == semiprime: 
       print((tuple1[0]), (tuple1[2])) 

     elif (tuple1[0]) * (tuple1[3]) == semiprime: 
       print((tuple1[0]), (tuple1[3])) 

     # index 1 - 3 
     elif (tuple1[1]) * (tuple1[0]) == semiprime: 
       print((tuple1[1]), (tuple1[0])) 

     elif (tuple1[1]) * (tuple1[1]) == semiprime: 
       print((tuple1[1]), (tuple1[1])) 

     elif (tuple1[1]) * (tuple1[2]) == semiprime: 
       print((tuple1[1]), (tuple1[2])) 

     elif (tuple1[1]) * (tuple1[3]) == semiprime: 
       print((tuple1[1]), (tuple1[3])) 

     # index 2 - 3 
     elif (tuple1[2]) * (tuple1[0]) == semiprime: 
       print((tuple1[2]), (tuple1[0])) 

     elif (tuple1[2]) * (tuple1[1]) == semiprime: 
       print((tuple1[2]), (tuple1[1])) 

     elif (tuple1[2]) * (tuple1[2]) == semiprime: 
       print((tuple1[2]), (tuple1[2])) 

     elif (tuple1[2]) * (tuple1[3]) == semiprime: 
       print((tuple1[2]), (tuple1[3])) 

     #index 3 - 3 
     elif (tuple1[3]) * (tuple1[0]) == semiprime: 
       print((tuple1[3]), (tuple1[0])) 

     elif (tuple1[3]) * (tuple1[1]) == semiprime: 
       print((tuple1[3]), (tuple1[1])) 

     elif (tuple1[3]) * (tuple1[2]) == semiprime: 
       print((tuple1[3]), (tuple1[2])) 
+1

[ 'itertools.combinations (tuple1, 2)'] (https://docs.python.org/dev/library/ itertools.html # itertools.combinations) – jedwards

+0

Путь @jedwards - это мудрость! Вложенный цикл for тоже выглядит нормально. – heLomaN

+1

вместо того, чтобы ограничивать себя предварительным подсчетом простых чисел, вы можете рассчитать первичную факторизацию заданного числа, используя либо первичную контрольную функцию, либо просто генераторную, такую ​​как сито эратостенов – Copperfield

ответ

3

Я намекнул на это в своем комментарии, но понял, что ссылки на функцию docs могут быть недостаточными.

Вот как вы могли бы написать свой код, используя itertools.combinations_with_replacement:

from itertools import combinations_with_replacement 

# multiples of semiprimes 4 - 49 
tuple1 = (2, 3, 5, 7) 

# tuple 1 calculations 
while True: 

    try: 
     semiprime = int(input('Enter Semiprime: ')) 

    except ValueError: 
     print('INPUT MUST BE AN INTEGER') 
     continue 

    for (x,y) in combinations_with_replacement(tuple1, 2): 
     if x * y == semiprime: 
      print(x,y) 

Намного приятнее, IMO :)

Edit: Предыдущая версия используется itertools.combinations, который не поддавался (х, у) пары с одинаковым значением (например, (x,y) = (2,2) никогда не произойдет). combinations_with_replacement допускает дубликаты. Спасибо @Copperfield за это.

+2

. В этом случае я думаю, что 'combination_with_replacement' является правильным, потому что OP также проверяет элементы в том же положении – Copperfield

+0

@Copperfield, вы правы, они делают - редактируют его. – jedwards

+0

@jedwards гораздо приятнее, спасибо! Но в цикле for, что является аргументом «2» в аргументах функций? – user

1

В то время как jedwards демонстрирует самый подход Pythonic - используя библиотеку itertools, которую вы узнаете и любите - вот более «классический» подход, использующий for-loops для шаблона, который вы хотите. Я приношу его, потому что, как новичок программирования, важно знать эту основные, императивные идиомы:

>>> tuple1 = (2,3,5,7) 
>>> for i in range(len(tuple1)): 
... for j in range(i+1, len(tuple1)): 
...  print(tuple1[i], tuple1[j]) 
... 
2 3 
2 5 
2 7 
3 5 
3 7 
5 7 
>>> 

Таким образом, ваш код будет сокращен до:

for i in range(len(tuple1)): 
    for j in range(i+1, len(tuple1)): 
     if tuple1[i] * tuple1[j] == semiprime 
      print(tuple1[i], tuple1[j]) 
+1

Я не ненавижу вложенный цикл, но я думаю, что итерация по кортежу (например, 'для e1 в tuple1: для e2 в tuple1: ...') может быть лучше – jedwards

+0

@jedwards Но тогда вы получите продукт, а не каждая уникальная комбинация. Вы могли бы избежать этого, используя кусочек (или, еще лучше, 'islice') и итерацию по кортежу, но я не хотел это поднимать, так как в любом случае это имеет значение. –

0

Даже если @jedwards решение отличное, (, а также краткое/pythonic); один из возможных решений:

def prime_multiples(l,t): 
    for i in l: # Iterate over our list. 
     for j in t: # Iterate over the tuple of prime factors. 
      # We check to see that we can divide without a remainder with our factor, 
      # then check to see if that factor exists in our tuple. 
      if i%j == 0 and i/j in t: 
       print "Prime factors: {} * {} = {}".format(j, i/j, i) 
       break # We could go not break to print out more options. 

Пример вывода:

l = [4, 6, 9, 10, 14, 15, 21, 22, 25, 26, 33, 34, 35, 38, 39, 46, 49] 
t = (2, 3, 5, 7) 
prime_multiples(l, t) 
>>> Prime factors: 2 * 2 = 4 
... Prime factors: 2 * 3 = 6 
... Prime factors: 3 * 3 = 9 
... Prime factors: 2 * 5 = 10 
... Prime factors: 2 * 7 = 14 
... Prime factors: 3 * 5 = 15 
... Prime factors: 3 * 7 = 21 
... Prime factors: 5 * 5 = 25 
... Prime factors: 5 * 7 = 35 
... Prime factors: 7 * 7 = 49