Wstęp do programowania / Ćwiczenia 6: Różnice pomiędzy wersjami
Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwaniam |
|||
Linia 35: | Linia 35: | ||
{{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | {{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
− | Główną trudnością jest wymyślenie odpowiedniego niezmiennika pętli while. Tu | + | Główną trudnością jest wymyślenie odpowiedniego niezmiennika pętli while. Tu będzie to zdanie: |
∀ i (1 ≤ i < m) ⇒ A[i] < 0 ∧ | ∀ i (1 ≤ i < m) ⇒ A[i] < 0 ∧ | ||
∀ j (m ≤ j < r) ⇒ A[j] = 0 ∧ | ∀ j (m ≤ j < r) ⇒ A[j] = 0 ∧ | ||
Linia 145: | Linia 145: | ||
{{cwiczenie||| | {{cwiczenie||| | ||
− | Tablica A typu array[1..N] of integer, N >0 | + | Tablica A typu array[1..N] of integer, N >0 zawiera tylko liczby dodatnie. Napisz program, który dla danego W typu integer takiego, że W > 0 sprawdza, czy w A istnieje segment o sumie W (czyli czy istnieją l, p takie, że W<math>=A[l]+...+A[p-1]</math>).}} |
'''Program''' | '''Program''' | ||
Linia 223: | Linia 223: | ||
1 ≤ l ≤ p+1 ≤ N+1 ∧ N,W > 0 ∧ suma+A[p]=A[l]+....A[p] ∧ | 1 ≤ l ≤ p+1 ≤ N+1 ∧ N,W > 0 ∧ suma+A[p]=A[l]+....A[p] ∧ | ||
A jest tablicą o wartościach dodatnich | A jest tablicą o wartościach dodatnich | ||
− | Jedyna część, która nie jest oczywista to | + | Jedyna część, która nie jest oczywista, to że A[l]+...A[p-1] < W, ale to wynika z (suma < W) i suma=A[l]+....A[p-1] |
'''5''' W drugiej gałęzi wiemy dodatkowo, że suma > W | '''5''' W drugiej gałęzi wiemy dodatkowo, że suma > W | ||
Linia 237: | Linia 237: | ||
Dla uzasadnienia drugiej linii wystarczy zauważyć, że gdy skracamy segment o wartości mniejszej niż W, to jego wartość spada, bo A jest tablica dodatnią. | Dla uzasadnienia drugiej linii wystarczy zauważyć, że gdy skracamy segment o wartości mniejszej niż W, to jego wartość spada, bo A jest tablica dodatnią. | ||
− | Pozostaje uzasadnienie l+1 ≤ p. Ponieważ suma > W to l < p, a więc | + | Pozostaje uzasadnienie l+1 ≤ p. Ponieważ suma > W to l < p, a więc też l+1 ≤ p. |
'''7''' Po pętli '''while''' wiemy, że zachodzi N(l,p,suma) i zaprzeczenie dozoru, czyli (suma=W ∨ p > N). Z niezmiennika wiemy, że p ≤ N+1, a więc musi być p=N+1. | '''7''' Po pętli '''while''' wiemy, że zachodzi N(l,p,suma) i zaprzeczenie dozoru, czyli (suma=W ∨ p > N). Z niezmiennika wiemy, że p ≤ N+1, a więc musi być p=N+1. | ||
Linia 361: | Linia 361: | ||
'''5''' Kolejny '''if'''; dowód znów się rozgałęzia. | '''5''' Kolejny '''if'''; dowód znów się rozgałęzia. | ||
− | '''6''' Korzystając z reguły na przypisanie, mamy do pokazania, że N(i,ile,kand) ∧ i ≤ N ∧ A[i]<> kand i ∧ ile > 0 implikuje N(i+1,ile-1,kand). | + | '''6''' Korzystając z reguły na przypisanie, mamy do pokazania, że N(i,ile,kand) ∧ i ≤ N ∧ A[i]<> kand i ∧ ile > 0 implikuje N(i+1,ile-1,kand). Jeśli P to permutacja z N(i,ile,kand), to |
szukana permutacja to P rozszerzona o identyczność na i. W nowym ogonie mamy dodatkowo A[i] i kand. Z tego wynika, że gdyby A[i] był liderem w nowym ogonie, to A[i] byłby liderem w starym ogonie, co jest niemożliwe. Oczywiście i+1 ≤ N+1; oraz ile > 0. | szukana permutacja to P rozszerzona o identyczność na i. W nowym ogonie mamy dodatkowo A[i] i kand. Z tego wynika, że gdyby A[i] był liderem w nowym ogonie, to A[i] byłby liderem w starym ogonie, co jest niemożliwe. Oczywiście i+1 ≤ N+1; oraz ile > 0. | ||
'''7''' Wpierw zauważmy, że ile ≤ 0 oraz ile ≥ 0 implikują ile=0. Korzystając z reguły na przypisanie, mamy do pokazania, że | '''7''' Wpierw zauważmy, że ile ≤ 0 oraz ile ≥ 0 implikują ile=0. Korzystając z reguły na przypisanie, mamy do pokazania, że | ||
N(i,ile,kand) ∧ i ≤ N ∧ A[i] <> kand ∧ ile =0 | N(i,ile,kand) ∧ i ≤ N ∧ A[i] <> kand ∧ ile =0 | ||
− | implikuje N(i+1,1,A[i]). Ponieważ ile=0 to w tablicy A[1..i-1] nie ma lidera. Szukaną permutacją jest więc na przykład A[i]@A[1..i-1]. | + | implikuje N(i+1,1,A[i]). Ponieważ ile=0, to w tablicy A[1..i-1] nie ma lidera. Szukaną permutacją jest więc na przykład A[i]@A[1..i-1]. |
Oczywiście i+1 ≤ N+1; oraz ile > 0. | Oczywiście i+1 ≤ N+1; oraz ile > 0. | ||
'''8''' Po wyjściu z pętli mamy N(i,ile,kand) i zaprzeczenie dozoru, czyli i > N. To oznacza, że i=N+1. Czy możliwe jest, by liderem była | '''8''' Po wyjściu z pętli mamy N(i,ile,kand) i zaprzeczenie dozoru, czyli i > N. To oznacza, że i=N+1. Czy możliwe jest, by liderem była | ||
− | wartośc w <> kand | + | wartośc w <> kand? Jeśli tak przypuścimy, to niezależnie od ile, w musiałaby być liderem w ogonie, co jest sprzeczne z niezmiennikiem. Jedynym kandydatem na lidera jest więc rzeczywiście kand. |
</div> | </div> |
Wersja z 22:18, 15 lis 2006
<<< Powrót do modułu Dowodzenie poprawności programów
To są zadania na logikę Hoare'a.
Oglądaj wskazówki i rozwiązania __SHOWALL__
Ukryj wskazówki i rozwiązania __HIDEALL__
Zadanie 1 (Flaga trójkolorowa)
Udowodnij częściową poprawność podanego poniżej rozwiązania zadania o fladze trójkolorowej.
Ćwiczenie
Dana jest tablica A typu array[1..N] of integer (N > 0). Należy tak poprzestawiać w niej elementy, żeby najpierw były elementy ujemne, potem równe zero, a na końcu dodatnie.
Program
program FlagaTrójkolorowa(N:integer; A:array[1..N] of integer); var m,r,w,pom : integer; begin m:=1; r:=1; w:=N; while r <= w do if A[r]=0 then r:=r+1 //przedłużamy segment liczb dodatnich else if A[r]<0 then begin pom:=A[r]; A[r]:=A[m]; A[m]:=pom; //zamieniamy wartości w A[r] i A[m], po zamianie A[r]=0 i A[m] < 0 m:=m+1; //więc zwiększamy oba indeksy r i m r:=r+1; end else begin pom:=A[r]; A[r]:=A[w]; A[w]:=pom; //zamieniamy wartości w A[r] i A[w] w:=w-1; //po zamianie A[w]>0, ale o A[r] nic nie wiemy end; end.
Rozwiązanie
{{{3}}}
Całkowita poprawność
Zadanie 2 (Segment o danej sumie)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Ćwiczenie
Tablica A typu array[1..N] of integer, N >0 zawiera tylko liczby dodatnie. Napisz program, który dla danego W typu integer takiego, że W > 0 sprawdza, czy w A istnieje segment o sumie W (czyli czy istnieją l, p takie, że W
).Program
program SegmentODanejSumie2(N,W:integer; A:array[1..N] of integer); //Tablica A zawiera tylko liczby dodatnie var l,p,suma: integer; znalezione: boolean; begin l:=1; p:=1; suma:=0; while (suma <> W) and (p <= N) do if suma < W then begin //jeśli suma jest za mała, to przesuwamy prawy koniec segmentu suma:=suma+A[p]; p:=p+1; end else begin //jeśli za duża, to przesuwamy lewy koniec segmentu suma:= suma-A[l]; l:=l-1; end; while (suma > W) do begin suma:= suma-A[l]; l:=l-1; end; znalezione:=(suma=W); end.
Rozwiązanie
{{{3}}}
Całkowita poprawność
Zadanie 3 (Głosowanie większościowe)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Ćwiczenie
Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź, czy jest w niej element wystepujący więcej niż N/2 razy i jeśli tak, wskaż go.
Program
program Głosowanie2(N,W:integer; A:array[1..N] of integer); var ile,i,kand,lider: integer; begin kand:=A[1]; //szukamy kandydata na lidera ile := 1; i:=2; while i <= N do begin if A[i]=kand then begin ile:=ile+1; i:=i+1; end else if ile > 0 then begin ile:=ile-1; i:=i+1; end else begin kand:=A[i]; ile:=1; i:=i+1; end; end; ile:=0; //sprawdzamy, czy kandydat jest liderem for i:=1 to do if A[i]=kand then ile:=ile+1; if (ile >= (N div 2 + 1) then begin lider:=kand; write('Liderem jest: ', kand); end else lider:=0; end.
Rozwiązanie
{{{3}}}
Zadanie 4 (BinPower)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Ćwiczenie
Dla zadanych x,n > 0 wyznacz xn (oczywiscie bez exp i ln).
Program
function BinPower(x,n:integer):integer; // Dla x,n > 0 wyznaczamy x do potęgi n var z,y,i: integer; begin z:=1; y:=x; i:=n; while i > 0 do begin if (i mod 2 = 1) then z:=z*y; y:=y*y; i:=i div 2; end; BinPower:=z; end;
Rozwiązanie
{{{3}}}