Rozumienie zestawu w Pythonie

81

Więc mam te dwa problemy do zadania domowego i utknąłem na drugim.

  1. Użyj Python Set Compression (Pythonowy odpowiednik notacji Set Builder), aby wygenerować zbiór wszystkich liczb pierwszych, które są mniejsze niż 100. Przypomnij sobie, że liczba pierwsza to liczba całkowita większa niż 1 i niepodzielna przez żadną liczbę całkowitą inną niż i 1. Przechowuj swój zestaw liczb pierwszych w zmiennej (będziesz jej potrzebował do dodatkowych części). Wyprowadź swój zestaw liczb pierwszych (np. Za pomocą funkcji drukowania).

  2. Użyj funkcji Zrozumienie zbioru Pythona, aby wygenerować zestaw uporządkowanych par (krotek o długości 2) składających się ze wszystkich par pierwszych składających się z liczb pierwszych mniejszych niż 100. Para pierwsza to para kolejnych liczb nieparzystych, które są liczbami pierwszymi. Przechowuj swój zestaw pierwszych par w zmiennej. Twój zestaw numer 1 będzie bardzo pomocny. Wyprowadź zestaw pierwszych par.

W przypadku pierwszego działa to idealnie:

r= {x for x in range(2, 101) 
if not any(x % y == 0 for y in range(2, x))} 

Jednak jestem dość zaskoczony drugim. Myślę, że być może będę musiał wziąć z czymś iloczyn kartezjański zbioru r, ale po prostu nie jestem pewien.

To mnie trochę zbliża, ale chcę tylko kolejnych par.

cart = { (x, y) for x in r for y in r
     if x < y }
user3308790
źródło

Odpowiedzi:

69
primes = {x for x in range(2, 101) if all(x%y for y in range(2, min(x, 11)))}

Trochę uprościłem test - if all(x%yzamiastif not any(not x%y

Ograniczyłem też zasięg y; nie ma sensu testowanie dzielników> sqrt (x). Zatem max (x) == 100 implikuje max (y) == 10. Dla x <= 10, y także musi wynosić <x.

pairs = {(x, x+2) for x in primes if x+2 in primes}

Zamiast generować pary liczb pierwszych i testować je, uzyskaj jeden i zobacz, czy istnieje odpowiadająca mu wyższa liczba pierwsza.

Hugh Bothwell
źródło
14

Możesz uzyskać czyste i jasne rozwiązania, budując odpowiednie predykaty jako funkcje pomocnicze. Innymi słowy, użyj notacji Pythona set-builder w ten sam sposób, w jaki zapisałbyś odpowiedź za pomocą zwykłej notacji matematycznej.

Cała idea wyrażeń zbiorowych polega na tym, abyśmy mogli pisać i rozumować w kodzie w taki sam sposób, jak robimy matematykę ręcznie.

Mając w ręku odpowiedni predykat, problem 1 upraszcza się do:

 low_primes = {x for x in range(1, 100) if is_prime(x)}

Problem 2 upraszcza się do:

 low_prime_pairs = {(x, x+2) for x in range(1,100,2) if is_prime(x) and is_prime(x+2)}

Zwróć uwagę, że ten kod jest bezpośrednim tłumaczeniem specyfikacji problemu: „Para pierwsza to para kolejnych liczb nieparzystych, które są liczbami pierwszymi”.

PS Próbuję podać poprawną technikę rozwiązywania problemów, nie ujawniając odpowiedzi na zadanie domowe.

Raymond Hettinger
źródło
2
Chociaż problem 2 można uprościć, aby po prostu prześledzić wynik w ramach problemu 1, jak wskazano w instrukcji.
tripleee
5

Możesz generować pary w ten sposób:

{(x, x + 2) for x in r if x + 2 in r}

Następnie pozostaje tylko uzyskać warunek, który uczyni je pierwszymi, co już zrobiłeś w pierwszym przykładzie.

Inny sposób na zrobienie tego: (Chociaż wolniej w przypadku dużych zestawów liczb pierwszych)

{(x, y) for x in r for y in r if x + 2 == y}
icedtrees
źródło
3
Nie jestem pewien, dlaczego twój lepszy sposób jest lepszy. OP ma już liczby pierwsze mniejsze niż 100 cali r, więc {(x, x + 2) for x in r if x + 2 in r}wystarczy.
DSM
2
and x % 2 == 1to nie jest konieczne.
thefourtheye
2
naprawiono, dziękuję, z jakiegoś powodu myślałem, że liczby pierwsze mogą być równe
icedtrees
2
Z jakiegoś powodu nie widzę, których brakuje. Mam ustawione ([(29, 31), (59, 61), (5, 7), (71, 73), (41, 43), (3, 5), (17, 19), (11, 13)]). Których par brakuje? Już zastosowałeś warunek (bycia liczbą pierwszą) do r, więc kod powinien być w porządku.
icedtrees
Nie, masz absolutną rację. Byłem pod wrażeniem (7,11) i (13,17) itd.… Zostały uwzględnione w pierwszych parach, ponieważ były one technicznie „kolejnymi” na liście liczb pierwszych. Ale teraz rozumiem.
user3308790