Wstęp do programowania/Wstęp do algorytmów/Ćwiczenia: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Daria (dyskusja | edycje)
Poczatki prostokatow
 
Daria (dyskusja | edycje)
Zadanie o prostokątach
Linia 1: Linia 1:
=== Zadanie 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">
'''Odpowiedź''' 
<div class="mw-collapsible-content" style="display:none">
 
</div>
</div>
<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 &cap; B) i zrobić formalny dowód, że dla każdego punktu p zdanie p &epsilon; A &cap; B jest równoważne temu, że p &epsilon; 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 &epsilon; A &cap; B to p &epsilon; W. Ponieważ p &epsilon; A to
A.x1 &le; p.x &le; A.x2
A.y1 &ge; p.y &ge; A.y2
Podobnie dla B, czyli B.x1 &le; p.x &le; B.x2  i  B.y1 &ge; p.y &ge; B.y2. A więc
max(A.x1,B.x1) &le; p.x &le; min(A.x2,B.x2)
min(A.y1,B.y1) &ge; p.y &ge; max(A.y2,B.y2).
Stąd  W.x1 &le; p.x &le; W.x2  i  W.y1  &ge; p.y &ge; W.y2, czyli p &epsilon; W.


 
W drugą stronę dowód przebiega podobnie. Ponieważ  p &epsilon; W to max(A.x1,B.x1) &le; p.x &le; min(A.x2,B.x2) min(A.y1,B.y1) &ge; p.y &ge; max(A.y2,B.y2). Stąd A.x1 &le; p.x &le; A.x2  i A.y1 &ge; p.y &ge; A.y2, a więc p &epsilon; A. I tak samo dla B. A więc p &epsilon; A &cap; B.
 
</div>
 
</div>
    Postać wyniku
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.
      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.)
 
b) Znajdowanie algorytmu
      Dla utrudnienia narysujmy kilka możliwych wzajemnych położeń
prosokątów na tablicy. Zapewne
      pojawi się pomysł na badanie różnych przypadków wzajemnego
położenia tych prostokątów, jeśli
      tak, to pozwólmy chwilę nad tym rozwiązaniem popracować
studentom, tak by wszyscy zobaczyli jak
      bardzo nieprzyjemne jest to rozwiazanie (klikanaście bądź więcej
przypadków), skomentujmy
      dlaczego należy unikać tego typu rozwiazań.
      O ile studenci sami nie wpadną na dobre rozwiązanie lekko je im
zasugerujmy (jaka może być
      współrzędna x-owa lewego-górnego rogu wynikowego prostokąta).
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 (nie używam jeszcze symbolu
przypisania)
        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).
 
c) Testowanie
  Mając algorytm/program powinniśmy go przetestować, czyli sprawdzić
ajkie daje wyniki dla
  przykładowych danych. Jakie dane warto testować (typowe oraz
szczególnie przypadki graniczne).
  Koniecznie podkreślmy, że testowanie jest ważne i że trzeba je robić,
ale że (o ile 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).
  Przeliczmy wyniki  dla paru zestawów danych (np. prostokąt a zawarty
w B i przypadek gdy część
  wspólna jest pusta).
 
  d)  Dowód poprawności
          Skoro testowanie nie daje pewności, że mamy dobry program
potrzebujemy inego narzędzia, które
    pozwoli nam spać spokojnie - możemy (przynajmniej teoretycznie)
dowieść formalnie poprawność
    programu.
    Co jest formalną specyfikacja naszego zadania (W = A \cap B).
    Zróbmy formalny dowód (tzn. bieżemy punkt p i pokazujemy że p \in A
\cap B jest równoważne
    temu, że p \in W).. Teraz już możemy spać spokojnie - nasz algorytm
_jest_ poprawny (o ile nie
    pomylilismy się także w  dowodzie)!
 
Sądzę, że 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.

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.