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

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Pch (dyskusja | edycje)
 
(Nie pokazano 5 wersji utworzonych przez 2 użytkowników)
Linia 34: Linia 34:
  '''end'''.
  '''end'''.


{{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">  
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">  
Główną trudnością jest wymyślenie odpowiedniego niezmiennika pętli while. Tu będzie to zdanie:
Główną trudnością jest wymyślenie odpowiedniego niezmiennika pętli while. Tu będzie to zdanie:
  &forall; i  (1 &le; i < m) &rArr;  A[i] < 0 &and;   
  &forall; i  (1 &le; i < m) &rArr;  A[i] < 0 &and;   
Linia 132: Linia 134:
'''12''' Z reguły na '''while''' wiemy, że zachodzi N(m,r,w) i zaprzeczenie dozoru w '''while''' czyli r > w. Z niezmiennika wiemy, że r-1 &le; w, musi więc być r-1=w.
'''12''' Z reguły na '''while''' wiemy, że zachodzi N(m,r,w) i zaprzeczenie dozoru w '''while''' czyli r > w. Z niezmiennika wiemy, że r-1 &le; w, musi więc być r-1=w.
</div>
</div>
</div>}}
</div>


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Linia 162: Linia 164:
     '''else''' '''begin''' //jeśli za duża, to przesuwamy lewy koniec segmentu
     '''else''' '''begin''' //jeśli za duża, to przesuwamy lewy koniec segmentu
       suma:= suma-A[l];
       suma:= suma-A[l];
       l:=l-1;
       l:=l+1;
     '''end''';
     '''end''';
   '''while''' (suma > W) '''do''' '''begin'''   
   '''while''' (suma > W) '''do''' '''begin'''   
     suma:= suma-A[l];
     suma:= suma-A[l];
     l:=l-1;
     l:=l+1;
   '''end''';
   '''end''';
   znalezione:=(suma=W);
   znalezione:=(suma=W);
  '''end'''.
  '''end'''.
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
{{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">  
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">  
Zacznijmy od niezmiennika pierwszej pętli
Zacznijmy od niezmiennika pierwszej pętli
  &forall; k  &forall; m (k < l &and; l &le; m &le; N+1) &rArr;  A[k]+...+A[m-1] <> W &and;
  &forall; k  &forall; m (k < l &and; l &le; m &le; N+1) &rArr;  A[k]+...+A[m-1] <> W &and;
Linia 258: Linia 261:
Czyli nie isnieje segment o sumie równej W.
Czyli nie isnieje segment o sumie równej W.
</div>
</div>
</div>}}
</div>


<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
Linia 274: Linia 277:


{{cwiczenie|||
{{cwiczenie|||
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.}}
Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź, czy jest w niej element występujący więcej niż N/2 razy i jeśli tak, wskaż go.}}


'''Program'''
'''Program'''
Linia 310: Linia 313:
  '''end'''.
  '''end'''.


{{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">  
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">  
Sprawdzenie, czy kandydat jest liderem, jest proste. Skoncentrujemy się więc na pierwszej części i wykażemy, że jeśli w tablicy jest lider to pierwsza część go znajduje.
Sprawdzenie, czy kandydat jest liderem, jest proste. Skoncentrujemy się więc na pierwszej części i wykażemy, że jeśli w tablicy jest lider to pierwsza część go znajduje.


Linia 354: Linia 359:
'''2''' Będziemy pokazywać, że N(i,ile,kand) jest niezmiennikiem pętli.
'''2''' Będziemy pokazywać, że N(i,ile,kand) jest niezmiennikiem pętli.


'''3''' Trzeba osobno rozpatrzeć gałezie '''if'''.
'''3''' Trzeba osobno rozważyć gałęzie '''if'''.


'''4''' Korzystając z reguły na przypisanie, mamy do pokazania, że N(i,ile,kand) &and; i &le; N &and; A[i]=kand implikuje N(i+1,ile+1,kand). Jeśli P to permutacja z N(i,ile,kand), to
'''4''' Korzystając z reguły na przypisanie, mamy do pokazania, że N(i,ile,kand) &and; i &le; N &and; A[i]=kand implikuje N(i+1,ile+1,kand). Jeśli P to permutacja z N(i,ile,kand), to
Linia 370: Linia 375:


'''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? 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.
wartość 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>
</div>}}
</div>


== Zadanie 4 (BinPower)==
== Zadanie 4 (BinPower)==
Linia 396: Linia 401:
   BinPower:=z;
   BinPower:=z;
  '''end''';
  '''end''';
 
<div class="mw-collapsible mw-made=collapsible mw-collapsed">
{{rozwiazanie|||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none">  
<span class="mw-collapsible-toogle mw-collapsible-toogle-default style="font-variant:small-caps">Rozwiązanie</span>
<div class="mw-collapsible-content" style="display:none">  
Zacznijmy od niezmiennika pętli oznaczanego przez N(z,y,i):  
Zacznijmy od niezmiennika pętli oznaczanego przez N(z,y,i):  
  x<sup>n</sup>=z*y<sup>i</sup> &and; i&ge; 0
  x<sup>n</sup>=z*y<sup>i</sup> &and; i&ge; 0
Linia 431: Linia 437:
'''5''' Po wyjściu z pętli mamy  N(z,y,i) &and; i &le; 0. Ponieważ i &ge; 0  z niezmiennika, to i=0. A więc  x<sup>n</sup>=z.
'''5''' Po wyjściu z pętli mamy  N(z,y,i) &and; i &le; 0. Ponieważ i &ge; 0  z niezmiennika, to i=0. A więc  x<sup>n</sup>=z.
</div>
</div>
</div>}}
</div>

Aktualna wersja na dzień 16:00, 28 maj 2020

<<< 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

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=A[l]+...+A[p1]).

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.

Ćwiczenie

Dana jest tablica A typu array[1..N] of integer, N > 0. Sprawdź, czy jest w niej element występują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 n 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.

Ć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