admin 0Comment

Tym tematem zaczynam serię wpisów, opisujących proces rozwiązywania praktycznych zadań umieszczonych w kolejnych rozdziałach internetowego i książkowego kursu Automate the Boring Stuff with Python. O samym kursie pisałem tutaj. W swoich wpisach chcę opisać sam proces dochodzenia do rozwiązania każdego z zadań praktycznych, napotykane po drodze problemy czy błędy.  Wpisy nie mają wyłącznie zaserwować gotowe rozwiązanie w postaci przykładowego kodu – sam autor tutoriala nie udostępniał ich na stronie swojego kursu, co było bardzo dobrym posunięciem. Jednocześnie namawiam cię do tego byś spróbował napisać własne rozwiązanie dla danego zadania a dopiero potem przeczytał jak ja do niego podszedłem.

Zadania zaczerpnięte są z tutoriala AtBSwP, jednak nic nie stoi na przeszkodzie żeby potraktować je jako samodzielne ćwiczenia dla osób uczących się Pythona z innych źródeł. Warto wtedy jednak chociaż zajrzeć do spisu treści kursu i zorientować się na jakim etapie zaawansowania jest dane zadanie oraz za pomocą jakich poznanych już metod powinno się być w stanie je rozwiązać.

Pamiętajcie też, że podane przeze mnie przykłady rozwiązań są, no właśnie – wyłącznie przykładami. Nie są to jedyne sposoby ukończenia ćwiczeń, najczęściej nie są one też najbardziej optymalnymi – najczęściej zatrzymuję się na rozwiązaniu działającym, ale nie wykraczającym poza zakres wiedzy dostępny na danym poziomie kursu, a jeśli jest inaczej – jasno to zaznaczam.

Przechodzimy do pierwszego otwartego zadania praktycznego, pojawiającego się w tutorialu w rozdziale trzecim (tutaj widnieje spis treści dla kursu oraz linki do kolejnych rozdziałów).

Na czym polega zadanie z rozdziału trzeciego:

Etap pierwszy:

The Collatz Sequence

Write a function named collatz() that has one parameter named number. If number is even, then collatz() should print number // 2 and return this value. If number is odd, then collatz() should print and return 3 * number + 1.

Etap drugi:

Then write a program that lets the user type in an integer and that keeps calling collatz() on that number until the function returns the value 1. (Amazingly enough, this sequence actually works for any integer—sooner or later, using this sequence, you’ll arrive at 1! Even mathematicians aren’t sure why. Your program is exploring what’s called the Collatz sequence, sometimes called “the simplest impossible math problem.”)

Remember to convert the return value from input() to an integer with the int() function; otherwise, it will be a string value.

Hint: An integer number is even if number % 2 == 0, and it’s odd if number % 2 == 1.

The output of this program could look something like this:

Enter number:
3
10
5
16
8
4
2
1

Etap trzeci:

Add try and except statements to the previous project to detect whether the user types in a noninteger string. Normally, the int() function will raise a ValueError error if it is passed a noninteger string, as in int(‚puppy’). In the except clause, print a message to the user saying they must enter an integer.

 

Opis rozwiązania dla etapu pierwszego:

Stosunkowo prosta część zadania, sam jej opis jest w zasadzie podaniem kolejnych kroków.

def collatz(number):
    if number % 2 == 0:
         return number // 2
    else:
        return 3 * number + 1

 
Wiemy jak definiuje się funkcję,  pamiętamy o właściwej indentacji (czyli, po prostu, o odpowiednich wcięciach), i to w zasadzie tyle. Schody zaczynają się za chwilę.

Pewną trudnością (i dobrym ćwiczeniem) byłoby samodzielne dojście do tego jak umożliwić programowi rozróżnienie parzystej od nieparzystej liczby. Autor wyjaśnia to jednak w zamieszczonej wskazówce. Szkoda, że nie zostało to ukryte i nie zaproponował samodzielnej próby dojścia do rozwiązania.

Kod jest na tyle nieskomplikowany, że możemy w całości zdefiniować go w oknie IDLE (jeśli nie wiesz o czym piszę, powinieneś jednak zatrzeć do początkowych rozdziałów AtBSwP) a potem wywołać funkcję za pomocą, przykładowo:

>>>collatz(5)

Lub też możemy kod zapisać jako osobny program w nowym oknie, wtedy jednak warto dodać do niego fragment, który, po uruchomieniu programu, poprosi nas o wpisanie liczby i wywoła funkcję z wybraną liczbą jako jej argumentem:

(...)
print('Input number ')
n = input()
n = int(n)
print(collatz(n))

Cały program wyglądałby więc tak:

def collatz(number):
    if number % 2 == 0:
        return number // 2
    else:
        return 3 * number + 1

print('Input number ')
n = input()
n = int(n)
print(collatz(n))

Opis rozwiązania dla etapu drugiego:

Tutaj mamy za zadanie stworzenie formuły przedstawiającej działanie tzw. Problemu Collatza, opisanego w tekście ćwiczenia. Podstawowym elementem naszego programu będzie oczywiście, zdefiniowana powyżej, funkcja.

def collatz(number):
    if number % 2 == 0:
        return number // 2
    else:
        return 3 * number + 1

Także dalszy fragment wcześniejszego programu przyda nam się w tym momencie:

(...)
print('Input number')
n = input()
n = int(n)

Dalej jednak nie możemy podać wyniku dla pojedynczego wywołania funkcji na podanej przez nas liczbie, ale musimy kontynuować wywoływanie funkcji na jej wyniku aż do momentu gdy ta zwróci nam wynik o wartości jeden. Po pierwszych rozdziałach kursu nie powinno być to problemem, musisz jedynie pogłówkować i przetłumaczyć opisane powyżej zadania na komendy języka.  I tak, wykonywanie danej czynności aż do momentu zwrotu wartości n o wyniku 1 możemy zapisujemy jako:

(...)
while n != 1:

Czyli tak długo jak zmienna n nie równa się 1, wykonuj poniższe. A co poniżej? Za każdym razem nasza zmienna n powinna wynosić tyle ile zwraca wywołana funkcja collatz, a także chcemy mieć wyświetlone kolejne wartości n:

(...)
while n != 1:
    n = collatz(n)
    print(n)

Cały program wygląda więc tak:

def collatz(number):
    if number % 2 == 0:
        return number // 2
    else:
        return 3 * number + 1
    
print('Input number')
n = input()
n = int(n)

while n != 1:
    n = collatz(n)
    print(n)

 

Opis rozwiązania dla etapu trzeciego:

Na początek musimy umieścić w try oraz except tę linię kodu, która mogłaby spowodować wystąpienie błędu programu w przypadku podania przez użytkownika innej zmiennej niż liczba:

(...)
try:
        n = int(n)
except:

Następnie musimy poinformować o konieczności podania liczby a także wymyślić sposób, jak powrócić do prawidłowego działania programu. Idealne będzie tutaj polecenie continue, a skoro tak, to należy część programu umieścić w pętli (aby continue mogło do niej się odnieść).

(...)    
while True:
    print('Input number')
    n = input()
    try:
        n = int(n)
    except:
        print('Please enter an integer')
        continue

Dalej w tej samej pętli while True umieścimy pozostałą część programu czyli znane już wywoływanie funkcji tak długo, aż nie zwróci ona wartości n równej jeden. Jeśli chcemy by funkcjonujący w pętli program zadziałał tylko raz, należy na jego końcu mieścić komendę break.  Moja wersja całego programu wygląda więc tak:

def collatz(number):
    if number % 2 == 0:
        return number // 2
    else:
        return 3 * number + 1
    
while True:
    print('Input number')
    n = input()
    try:
        n = int(n)
    except:
        print('Please enter an integer')
        continue
    while n != 1:
        n = collatz(n)
        print(n)
    break

I to by było na tyle. Nawet taki dość prosty program potrafi sprawić sporo trudności.

Finalne wersje przykładowych odpowiedzi do zadań będą pojawiały się na moim koncie GitHub.

Dodaj komentarz