Wstęp do programowania/Wstęp do algorytmów/Ćwiczenia: Różnice pomiędzy wersjami
Poczatki prostokatow |
Zadanie o prostokątach |
||
| Linia 1: | Linia 1: | ||
== Zadanie 1 == | |||
Podaj algorytm wyliczający część wspólną dwu zadanych prostokątów o | Podaj algorytm wyliczający część wspólną dwu zadanych prostokątów o bokach równoległych do osi układu współrzędnych. | ||
bokach równoległych do osi układu współrzędnych. | ===Analiza specyfikacji=== | ||
* Czy specyfikacja podana w zadaniu jest wystarczająca do zapisania algorytmu ? | |||
==Analiza specyfikacji== | |||
* Czy specyfikacja podana w zadaniu jest wystarczająca do zapisania | |||
algorytmu ? | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"> | ||
'''Odpowiedź''' | '''Odpowiedź''' | ||
| Linia 20: | Linia 17: | ||
</div> | </div> | ||
</div> | </div> | ||
* Jaka może być postać danych | * Jaka może być postać danych ? | ||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | <div class="mw-collapsible mw-made=collapsible mw-collapsed"> | ||
'''Odpowiedź''' | '''Odpowiedź''' | ||
| Linia 45: | Linia 36: | ||
Reprezentacje 3,4,5 są poprawne, w zależności od tego co chcemy robić z wynikiem naszych obliczeń mogą się okazać warte wybrania. | Reprezentacje 3,4,5 są poprawne, w zależności od tego co chcemy robić z wynikiem naszych obliczeń mogą się okazać warte wybrania. | ||
Reprezentacje 2 i 1 wydają się równoważne, dopiero przy wyborze reprezentacji wyniku okaże się, że różnica między nimi w tym akurat zadaniu jest bardzo istotna.</div> | Reprezentacje 2 i 1 wydają się równoważne, dopiero przy wyborze reprezentacji wyniku okaże się, że różnica między nimi w tym akurat zadaniu jest bardzo istotna.</div> | ||
</div> | |||
* Jaka może być postać wyniku ? | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
'''Odpowiedź''' | |||
<div class="mw-collapsible-content" style="display:none"> | |||
Skoro możemy traktować każdy możliwy wynik jako (być może zdegenerowany) prostokąt o bokach równoległych do osi układu, to byłoby dobrze użyć tu tej samej reprezentacji co dla danych (nam jako piszącym będzie łatwiej, a przede wszystkim jest to lepsze dla użytkownika, który będzie mógł zastosować nasz algorytm do wyników przez ten algorytm policzonych). I tu okazuje się wyższość reprezentacji 2, która pozwala reprezentować także pusty prostokąt, w przeciwieństwie do reprezentacji 1. (Reprezetacje 3-6 też są dobre, moglibyśmy także np. rysować wynik na ekranie.) | |||
</div> | |||
</div> | </div> | ||
=== Znajdowanie algorytmu === | |||
Gdy zaczniemy analizować możliwe wzajemne położenia prostokątów okaże się, że przypadków jest co najmniej kilkanaście. | |||
Zamiast tego spróbujmy się zastanowić jaka może być współrzędna x-owa lewego-górnego rogu wynikowego prostokąta. | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
'''Rozwiązanie''' | |||
<div class="mw-collapsible-content" style="display:none"> | |||
Załóżmy, że mamy operacje min i max. Przyjmijmy oznaczenia: | |||
A, B, W - prostokąty dane i wynikowy (odpowiednio) | |||
x1,x2,y1,y2 - współrzędne lewego-górnego, i prawego-dolnego wierzchołka (odpowiednio) | |||
P.x1 - notacja kropkowa do odwoływania się do współrzędnych | |||
Cały algorytm to cztery linijki: | |||
W.x1 = max(A.x1, B,x1) | |||
W.y1 = min(A.y1, B.y1) | |||
W.x2 = min(A.x2, B.x2) | |||
W.y2 = max(A.y2, B.y2) | |||
(współrzędne y-owe rosną w górę, tak jak w matematyce, a nie w dól jak na ekranie komputera). | |||
</div> | |||
</div> | |||
=== Testowanie === | |||
Mając algorytm/program powinniśmy go przetestować, czyli sprawdzić | |||
jakie daje wyniki dla przykładowych danych. Warto testować z jednej strony przypadki typowe, z drugiej zaś szczególne przypadki graniczne (np. prostokąty dotykające się jednym rogiem lub jeden prostokąt zawarty w drugim). Testowanie jest ważne i trzeba je robić, mimo że, w przypadku gdy nie wykryje błędów, nic nie daje (nawet nie mamy pewności, że dla przetestowanych danych zawsze dostaniemy poprawny wynik, bo np. mamy niezainicjalizowane zmienne). | |||
=== Dowód poprawności === | |||
Skoro testowanie nie daje pewności, że mamy dobry program to potrzebujemy innego narzędzia, które pozwoli nam spać spokojnie - możemy (przynajmniej teoretycznie) dowieść formalnie poprawność programu. | |||
Powinniśmy ustalić co jest formalną specyfikacją naszego zadania (W = A ∩ B) i zrobić formalny dowód, że dla każdego punktu p zdanie p ε A ∩ B jest równoważne temu, że p ε W. Teraz już możemy spać spokojnie - nasz algorytm '''jest''' poprawny (o ile nie pomylilismy się w dowodzie)! | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
'''Dowód''' | |||
<div class="mw-collapsible-content" style="display:none"> | |||
Najpierw pokażemy, że jeśli p ε A ∩ B to p ε W. Ponieważ p ε A to | |||
A.x1 ≤ p.x ≤ A.x2 | |||
A.y1 ≥ p.y ≥ A.y2 | |||
Podobnie dla B, czyli B.x1 ≤ p.x ≤ B.x2 i B.y1 ≥ p.y ≥ B.y2. A więc | |||
max(A.x1,B.x1) ≤ p.x ≤ min(A.x2,B.x2) | |||
min(A.y1,B.y1) ≥ p.y ≥ max(A.y2,B.y2). | |||
Stąd W.x1 ≤ p.x ≤ W.x2 i W.y1 ≥ p.y ≥ W.y2, czyli p ε W. | |||
W drugą stronę dowód przebiega podobnie. Ponieważ p ε W to max(A.x1,B.x1) ≤ p.x ≤ min(A.x2,B.x2) i min(A.y1,B.y1) ≥ p.y ≥ max(A.y2,B.y2). Stąd A.x1 ≤ p.x ≤ A.x2 i A.y1 ≥ p.y ≥ A.y2, a więc p ε A. I tak samo dla B. A więc p ε A ∩ B. | |||
</div> | |||
</div> | |||
Najważniejszy morał z tego zadania, to pochwała myślenia - trzeba wykonać dużo pracy (myślowej) zanim zacznie się pisać pierwszy wiersz programu/algorytmu. | |||
trzeba wykonać dużo pracy | |||
(myślowej) zanim zacznie się pisać pierwszy wiersz programu/algorytmu. | |||
Wersja z 13:41, 12 lip 2006
Zadanie 1
Podaj algorytm wyliczający część wspólną dwu zadanych prostokątów o bokach równoległych do osi układu współrzędnych.
Analiza specyfikacji
- Czy specyfikacja podana w zadaniu jest wystarczająca do zapisania algorytmu ?
Odpowiedź
- Co może być częścią wspólną ?
Odpowiedź
- Jaka może być postać danych ?
Odpowiedź
- Jaka może być postać wyniku ?
Odpowiedź
Znajdowanie algorytmu
Gdy zaczniemy analizować możliwe wzajemne położenia prostokątów okaże się, że przypadków jest co najmniej kilkanaście. Zamiast tego spróbujmy się zastanowić jaka może być współrzędna x-owa lewego-górnego rogu wynikowego prostokąta.
Rozwiązanie
Testowanie
Mając algorytm/program powinniśmy go przetestować, czyli sprawdzić jakie daje wyniki dla przykładowych danych. Warto testować z jednej strony przypadki typowe, z drugiej zaś szczególne przypadki graniczne (np. prostokąty dotykające się jednym rogiem lub jeden prostokąt zawarty w drugim). Testowanie jest ważne i trzeba je robić, mimo że, w przypadku gdy nie wykryje błędów, nic nie daje (nawet nie mamy pewności, że dla przetestowanych danych zawsze dostaniemy poprawny wynik, bo np. mamy niezainicjalizowane zmienne).
Dowód poprawności
Skoro testowanie nie daje pewności, że mamy dobry program to potrzebujemy innego narzędzia, które pozwoli nam spać spokojnie - możemy (przynajmniej teoretycznie) dowieść formalnie poprawność programu. Powinniśmy ustalić co jest formalną specyfikacją naszego zadania (W = A ∩ B) i zrobić formalny dowód, że dla każdego punktu p zdanie p ε A ∩ B jest równoważne temu, że p ε W. Teraz już możemy spać spokojnie - nasz algorytm jest poprawny (o ile nie pomylilismy się w dowodzie)!
Dowód
Najważniejszy morał z tego zadania, to pochwała myślenia - trzeba wykonać dużo pracy (myślowej) zanim zacznie się pisać pierwszy wiersz programu/algorytmu.