Ten samouczek nauczy Cię, jak wydrukować trójkąt Pascala w Pythonie dla określonej liczby wierszy.
Zaczniesz od nauki budowy trójkąta Pascala. Następnie przejdziesz do napisania funkcji Pythona i nauczysz się ją dalej optymalizować.
▶️ Zacznijmy!
Spis treści:
Co to jest trójkąt Pascala i jak go skonstruować?
Popularnym pytaniem podczas rozmowy kwalifikacyjnej jest wydrukowanie trójkąta Pascala dla określonej liczby wierszy.
W trójkącie Pascala z n wierszami, wiersz numer i ma i elementów.
Tak więc pierwszy wiersz ma jeden element i to 1. Każdy element w kolejnych wierszach to suma dwóch liczb bezpośrednio nad nim.
Poniższy rysunek wyjaśnia, jak skonstruować trójkąt Pascala z pięcioma rzędami.
Trójkąt Pascala dla numRows = 5 (zdjęcie autora)
Zwróć uwagę, jak możesz uzupełnić zera, gdy masz tylko jedną liczbę powyżej pewnej liczby.
📝Jako szybkie ćwiczenie, wykonaj powyższą procedurę, aby skonstruować trójkąt Pascala dla n = 6 i n = 7.
Następnie przejdźmy do napisania kodu. Możesz uruchomić fragmenty kodu w środowisku IDE Pythona newsblog.pl bezpośrednio z przeglądarki — podczas przechodzenia przez samouczek.
Funkcja Pythona do drukowania trójkąta Pascala
W tej sekcji napiszemy funkcję Pythona wyświetlającą trójkąt Pascala dla dowolnej liczby wierszy.
Należy rozważyć dwa kluczowe pytania:
- Jak wyrazić wpisy w trójkącie Pascala?
- Jak wydrukować trójkąt Pascala z odpowiednimi odstępami i formatowaniem?
Odpowiedzmy na nie teraz.
#1. Jakie jest wyrażenie dla każdego wpisu w trójkącie Pascala?
Tak się składa, że wpisy w trójkącie Pascala można otrzymać ze wzoru na nCr. Jeśli przypomnisz sobie ze szkolnej matematyki, nCr oznacza liczbę sposobów, w jakie możesz wybrać r elementów ze zbioru n elementów.
Wzór na nCr podano poniżej:
formuła nCr (zdjęcie autora)
Przejdźmy teraz do wyrażenia wpisów w trójkącie Pascala za pomocą wzoru nCr.
Wpisy trójkąta Pascala za pomocą nCr (zdjęcie autora)
Znaleźliśmy teraz sposób na wyrażenie wpisów w macierzy.
#2. Jak dostosować odstępy podczas drukowania wzoru?
W trójkącie Pascala z numRows wiersz #1 ma jeden wpis, wiersz #2 ma dwa wpisy i tak dalej. Aby wydrukować wzór jako trójkąt, potrzebujesz numRows – i spacji w wierszu #i. Aby to zrobić, możesz użyć funkcji zakresu Pythona w połączeniu z pętlą for.
Ponieważ funkcja zakresu domyślnie wyklucza punkt końcowy, należy dodać + 1, aby uzyskać wymaganą liczbę spacji wiodących.
Teraz, gdy nauczyłeś się, jak reprezentować wpisy, a także dostosowywać odstępy podczas drukowania trójkąta Pascala, przejdźmy dalej i zdefiniujmy funkcję pascal_tri.
Analiza definicji funkcji
Więc co chcesz, aby funkcja pascal_tri zrobiła?
- Funkcja pascal_tri powinna przyjąć jako argument liczbę wierszy (numRows).
- Powinien wydrukować trójkąt Pascala z numRows.
Aby obliczyć silnię, użyjmy funkcji silni z wbudowanego modułu matematycznego Pythona.
▶️ Uruchom następującą komórkę kodu, aby zaimportować silnię i użyć jej w bieżącym module.
from math import factorial
Poniższy fragment kodu zawiera definicję funkcji.
def pascal_tri(numRows): '''Print Pascal's triangle with numRows.''' for i in range(numRows): # loop to get leading spaces for j in range(numRows-i+1): print(end=" ") # loop to get elements of row i for j in range(i+1): # nCr = n!/((n-r)!*r!) print(factorial(i)//(factorial(j)*factorial(i-j)), end=" ") # print each row in a new line print("n")
Funkcja działa w następujący sposób:
- Funkcja pascal_tri ma jeden wymagany parametr numRows: liczbę wierszy.
- W sumie są wiersze numRows. Dla każdego i wiersza dodajemy numRows – i wiodące spacje przed pierwszym wpisem w wierszu.
- Następnie używamy formuły nCr do obliczenia poszczególnych wpisów. W wierszu i wpisy to iCj, gdzie j = {0,1,2,…,i}.
- Zauważ, że używamy //, który wykonuje dzielenie liczb całkowitych, ponieważ chcielibyśmy, aby wpisy były liczbami całkowitymi.
- Po obliczeniu wszystkich wpisów w wierszu, wypisz następny wiersz w nowej linii.
🔗 Jak dodaliśmy dokumentacja, możesz użyć wbudowanej funkcji pomocy Pythona lub atrybutu __doc__, aby uzyskać dostęp do ciągu dokumentacyjnego funkcji. Poniższy fragment kodu pokazuje, jak to zrobić.
help(pascal_tri) # Output Help on function pascal_tri in module __main__: pascal_tri(numRows) Print Pascal's triangle with numRows. pascal_tri.__doc__ # Output Print Pascal's triangle with numRows.
Teraz przejdźmy dalej i wywołajmy funkcję z liczbą wierszy jako argumentem.
pascal_tri(3) # Output 1 1 1 1 2 1
Zgodnie z oczekiwaniami drukowane są pierwsze 3 rzędy trójkąta Pascala.
Wydrukuj trójkąt Pascala za pomocą rekurencji
W poprzedniej sekcji zidentyfikowaliśmy matematyczne wyrażenie każdego wpisu w trójkącie Pascala. Nie wykorzystaliśmy jednak relacji między wpisami w dwóch kolejnych wierszach.
W rzeczywistości użyliśmy poprzedniego wiersza do obliczenia wpisów w kolejnym wierszu. Czy nie możemy tego użyć i wymyślić rekurencyjną implementację funkcji pascal_tri?
Tak, zróbmy to!
W implementacji rekurencyjnej funkcja wielokrotnie wywołuje samą siebie, dopóki nie zostanie spełniony przypadek podstawowy. W konstrukcji trójkąta Pascala zaczynamy od pierwszego rzędu z jednym wpisem 1, a następnie budujemy kolejne rzędy.
Tak więc wywołanie funkcji pascal_tri(numRows) z kolei wywołuje pascal_tri(numRows-1) i tak dalej, aż do osiągnięcia bazowego przypadku pascal_tri(1).
Rozważ przykład, w którym musisz wydrukować pierwsze 3 rzędy trójkąta Pascala. Poniższy obraz wyjaśnia, w jaki sposób wywołania cykliczne są wypychane na stos. I jak rekurencyjne wywołania funkcji zwracają wiersze trójkąta Pascala.
Stos wywołań podczas wywołań rekurencyjnych (zdjęcie autora)
▶️ Uruchom poniższy fragment kodu, aby rekurencyjnie wygenerować wiersze trójkąta Pascala.
def pascal_tri(numRows): '''Print Pascal's triangle with numRows.''' if numRows == 1: return [[1]] # base case is reached! else: res_arr = pascal_tri(numRows-1) # recursive call to pascal_tri # use previous row to calculate current row cur_row = [1] # every row starts with 1 prev_row = res_arr[-1] for i in range(len(prev_row)-1): # sum of 2 entries directly above cur_row.append(prev_row[i] + prev_row[i+1]) cur_row += [1] # every row ends with 1 res_arr.append(cur_row) return res_arr
Oto kilka punktów, na które warto zwrócić uwagę:
- Użyliśmy listy zagnieżdżonej jako struktury danych, gdzie każdy wiersz w trójkącie Pascala jest listą samą w sobie, tak jak poniżej: [[row 1], [row 2],…,[row n]].
- Wywołanie funkcji pascal_tri(numRows) wyzwala serię rekurencyjnych wywołań z argumentami numRows – 1, numRows – 2 aż do 1. Te wywołania są umieszczane na stosie.
- Gdy numRows == 1, dotarliśmy do przypadku podstawowego i funkcja zwraca [[1]].
- Teraz zwrócona lista jest używana przez kolejne funkcje na stosie wywołań — do obliczenia następnego wiersza.
- Jeśli cur_row jest bieżącym wierszem, cur_row[i] = poprzedni_wiersz[i] + poprzedni_wiersz[i+1]—suma 2 elementów bezpośrednio nad bieżącym indeksem.
Ponieważ zwrócona tablica jest listą zagnieżdżoną (listą list), musimy dostosować odstępy i wydrukować wpisy, jak pokazano w komórce kodu poniżej.
tri_array = pascal_tri(5) for i,row in enumerate(tri_array): for j in range(len(tri_array) - i + 1): print(end=" ") # leading spaces for j in row: print(j, end=" ") # print entries print("n") # print new line
Wynik jest prawidłowy, jak widać poniżej!
# Output 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1
Funkcja Pythona do drukowania trójkąta Pascala dla numRows ≤ 5
Obie metody, których się nauczyłeś, będą działać przy wyświetlaniu trójkąta Pascala dla dowolnej liczby wierszy numRows.
Jednak są chwile, kiedy trzeba wydrukować trójkąt Pascala dla mniejszej liczby wierszy. A gdy liczba wierszy, które musisz wydrukować, wynosi najwyżej 5 – możesz użyć prostej techniki.
Przejdź przez poniższy rysunek. I obserwuj, jak potęgi 11 są identyczne z wpisami w trójkącie Pascala. Zauważ też, że działa to tylko do czwartej potęgi liczby 11. To znaczy, że 11 podniesione do potęg {0, 1, 2, 3, 4} daje wpisy w rzędach od 1 do 5 trójkąta Pascala.
Przepiszmy definicję funkcji, jak pokazano poniżej:
def pascal_tri(numRows): '''Print Pascal's triangle with numRows.''' for i in range(numRows): print(' '*(numRows-i), end='') # compute power of 11 print(' '.join(str(11**i)))
Oto jak działa funkcja pascal_tri:
- Podobnie jak w poprzednich przykładach, dostosowujemy odstępy.
- Następnie używamy operatora potęgowania Pythona (**), aby obliczyć potęgi liczby 11.
- Ponieważ potęgi 11 są domyślnie liczbami całkowitymi, przekonwertuj je na łańcuch za pomocą str(). Masz teraz moc 11 jako ciągi.
- Łańcuchy w Pythonie są iterowalne — możesz więc przechodzić przez nie i uzyskiwać dostęp do jednego znaku na raz.
- Następnie możesz użyć metody join() ze składnią:
.join( ), aby połączyć elementy w używając jako separatora. - Tutaj potrzebujesz pojedynczej spacji między znakami, więc
będzie ’ ’, to ciąg znaków: potęga 11.
Sprawdźmy, czy funkcja działa zgodnie z przeznaczeniem.
pascal_tri(5) # Output 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1
Jako inny przykład, wywołaj funkcję pascal_tri z 4 jako argumentem.
pascal_tri(4) # Output 1 1 1 1 2 1 1 3 3 1
Mam nadzieję, że wiesz, jak łatwo wydrukować trójkąt Pascala dla numRows w zakresie od 1 do 5.
Wniosek
Oto, czego się nauczyliśmy:
- Jak skonstruować trójkąt Pascala z podaną liczbą rzędów. Każda liczba w każdym rzędzie jest sumą dwóch liczb bezpośrednio nad nią.
- Napisz funkcję Pythona używając formuły nCr = n!/(nr)!.r! aby obliczyć wpisy trójkąta Pascala.
- Następnie nauczyłeś się rekurencyjnej implementacji funkcji.
- Wreszcie poznałeś najbardziej optymalną metodę konstruowania trójkąta Pascala dla numRows do 5 — przy użyciu potęgi 11.
Jeśli chcesz podnieść poziom umiejętności Pythona, naucz się mnożyć macierze, sprawdzać, czy liczba jest liczbą pierwszą i rozwiązywać problemy związane z operacjami na ciągach. Udanego kodowania!