Wstęp do programowania / Ćwiczenia 6: Różnice pomiędzy wersjami
3 zadania |
Zadanie 4 |
||
Linia 266: | Linia 266: | ||
'''Zadanie''' | '''Zadanie''' | ||
Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź | Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź czyjest w niej element wystepujący więcej niż N/2 razy i jeśli tak wskażgo. | ||
'''Program''' | '''Program''' | ||
Linia 365: | Linia 365: | ||
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. a więc jedynym kandydatem an lidera jest rzeczywiście 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. a więc jedynym kandydatem an lidera jest rzeczywiście kand. | ||
</div> | |||
</div> | |||
== Zadanie 4 (BinPower)== | |||
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania. | |||
'''Zadanie''' | |||
Dla zadanych x,n > 0 wyznacz x<sup>n</sup> (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'''; | |||
<div class="mw-collapsible mw-made=collapsible mw-collapsed"> | |||
'''Rozwiązanie''' | |||
<div class="mw-collapsible-content" style="display:none"> | |||
Zacznijmy od niezmiennika pętli oznaczanego przez N(z,y,i): | |||
x<sup>n</sup>=z*y<sup>i</sup> ∧ i≥ 0 | |||
Poniżej znajduje się program wraz z anotacjami i dowody, że anotacje wraz z kodem który otaczają są poprawnymi trójkami Hoare'a. | |||
// x,n > 0 | |||
1: z:=1; y:=x; i:=n; | |||
// N(z,y,i) | |||
2: '''while''' i > 0 '''do''' '''begin''' | |||
// N(z,y,i) ∧ i > 0 | |||
3: '''if''' (i mod 2 = 1) '''then''' z:=z*y; | |||
// N(z,y*y,i div 2) | |||
4: y:=y*y; | |||
i:=i div 2; | |||
// N(z,y,i) | |||
5: '''end'''; | |||
// z= x<sup>n</sup> | |||
'''1''' Korzystając z reguły na przypisanie. Mamy pokazać, że N(1,x,n). Ponieważ n>0 to n≥ 0 | |||
'''2''' Będziemy pokazywać, że N(z,y,i) jest niezmiennikiem pętli. | |||
'''3''' Choć mamy instrukcję '''if''' bez '''else''' musimy pokazać dwie implikacje | |||
N(z,y,i) ∧ i>0 ∧ i mod 2 = 1 ⇒ N(z*y, y*y, i div 2) | |||
N(z,y,i) ∧ i>0 ∧ i mod 2 = 0 ⇒ N(z, y*y, i div 2) | |||
Dla pierwszej z nich zauważmy, ze jeśli i mod 2 = 1 to i=2*(i div 2) +1. Wtedy z*y<sup>i</sup>= (z*y) * (y*y)<sup>(i div 2)</sup>. Oczywiście jeśli i > 0 to i div 2 ≥ 0. | |||
Dla drugiej, mamy i=2*(i div 2). Wtedy z*y<sup>i</sup>= z * (y*y)<sup>(i div 2)</sup>. Podobnie jeśli i > 0 to i div 2 ≥ 0. | |||
'''4''' Jest to dwa razy użyta reguła na przypisanie. | |||
'''5''' Po wyjściu z pętli mamy N(z,y,i) ∧ i ≤ 0. Ponieważ i ≥ 0 z niezmiennika, to i=0. A więc x<sup>n</sup>=z. | |||
</div> | </div> | ||
</div> | </div> |
Wersja z 16:58, 24 lip 2006
Zadanie 1 (Flaga trójkolorowa)
Udowodnij częściową poprawność podanego poniżej rozwiązania zadania o fladze trójkolorowej.
Zadanie 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
Całkowita poprawność
Zadanie 2 (Segment o danej sumie)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Zadanie 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
Całkowita poprawność
Zadanie 3 (Głosowanie większościowe)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Zadanie Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź czyjest 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
Zadanie 4 (BinPower)
Udowodnij częściową poprawność dla podanego poniżej zadania i jego rozwiązania.
Zadanie 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