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