algorytm.org

Implementacja w Delphi/Pascal



Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Generowanie podzbiorów za pomocą Kodu Grey'a. - Implementacja w Delphi/Pascal
Ocena użytkownikóww: *****  / 2
SłabyŚwietny
Nadesłany przez Krzysztof Kwiatkowski, 05 marca 2006 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.
Pobierz pełne rozwiązanie.

Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.

kod_graya_d.dpr:
// Generowanie podzbiorów zbioru n-elementowego za pomocą Kodu Grey’a.
// www.algorytm.org
// (c) 2006 Krzysztof Kwiatkowski

program kod_graya;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
    vector = array[1..10] of Integer;

  {
  ***************************************************************************
  *
  *    Prosta implementacja funkcji f(x)=a^x.
  *
  ***************************************************************************
  }
  function pow(pods: Integer; wyk: Integer): LongInt;
  var
    a: Integer;
  begin
  if ( pods = 0 ) then pods:=0
  else if ( pods = 1) then pods:=1
  else if ( wyk = 0) then pods:=1
  else begin
    if (wyk<0) then begin
      writeln('Wykladnik mniejszy od 0. Nie obsluguje');
      exit;
    end;
    a := pods;
    while ( wyk > 1 ) do begin
      dec(wyk);
      pods:=pods*a;
    end;
  end;
  pow:=pods;
  end;

  {
  ****************************************************
  *
  *  Funkcja przeksztalcajaca liczbe calkowita
  *  na zapis dwojkowy. Wynikiem jest wektor
  *
  *  Pierwsza liczba w zwracanym wektorze to ilosc elementow
  *  obliczonej liczby.
  *
  ****************************************************
  }

  function ZmianaPodstawy2Wektor(pods: Integer; liczba: Integer): vector;
  var
    v,w: vector;
    i,j: Integer;
  begin

    if (liczba<0) then begin
      writeln('Liczba mniejsza od 0. Nie obsluguje');
      exit;
    end;
    if (liczba=0) then begin
      v[1]:=1;
      v[2]:=0;
      ZmianaPodstawy2Wektor:=v;
    end;
    i:=1;
    while (liczba>0) do begin
      inc(i);
      v[i]:=liczba mod pods;
      liczba:=liczba div pods;
    end;
    for j:=2 to i do w[j]:=v[i-j+2];
    w[1]:=i-1;
    ZmianaPodstawy2Wektor:=w;
  end;

  {
  *****************************************************************************
  *
  *   Ta funkcja przeszktalca liczbe z systemu o podstawie pods zapisanej
  *   w wektorze, do liczby w systemie dziesietnym.
  *   Podana liczba w wektorze v, musi miec specyficzna postac, tzn.
  *   pierwszy element tablicy to liczba mowiaca ile cyfr ma liczba
  *   do przeksztalcenia.
  *
  *   np. v=[3,1,1,0]; (czyli w systemie dziesietnym jest to = 6)
  *
  *****************************************************************************
  }
  function ZmianaPodstwy2Liczba(pods: Integer; v: vector): Integer;
  var
    suma: Integer;
    i,j : Integer;
  begin
    suma:=0;
    j:=0;
    for i:=v[1]+1 downto 2 do begin
        suma:=suma+(v[i]*pow(pods,j));
        inc(j);
    end;
    ZmianaPodstwy2Liczba:=suma;
  end;


  {
  **********************************************************
  *
  *   Funkcja na podstawie indexu generuje slowo Grey'a
  *
  **********************************************************
  }

  function IndeksNaSlowoGreya(i: Integer; ile_m: Integer):vector;
  var
    g,h: vector;
    j,z: Integer;
  begin
    FillChar(h,sizeof(h),0);
    g:=ZmianaPodstawy2Wektor(2,i);
    if (ile_m<g[1]) then begin
      writeln('Za mala liczba miejsc na ktorych nalezy przedstawic liczbe.');
      writeln('Wychodze z funkcji.');
      exit;
    end;

    for i:=2 to g[1]+1 do h[ile_m-g[1]+i-1]:=g[i];
    for i:=1 to ile_m do begin
      z:=ile_m-i+1;
      g[ile_m-i+1]:=(h[z]+h[z-1]) mod 2;
    end;

    FillChar(h,sizeof(h),0);
    h[1]:=ile_m;
    for i:=2 to ile_m+1 do h[i]:=g[i-1];
    IndeksNaSlowoGreya:=h;
  end;

  { DORZUCIC GENEROWANIE G[n] ZA POMOCA ROZNICY SYMETRYCZNEJ }
  function IndeksNaSlowoGreyaXOR(i: Integer; ile_m: Integer):vector;
  var
    g,h: vector;
    j,z: Integer;
  begin
    FillChar(h,sizeof(h),0);
    g:=ZmianaPodstawy2Wektor(2,i);
    if (ile_m<g[1]) then begin
      writeln('Za mala liczba miejsc na ktorych nalezy przedstawic liczbe.');
      writeln('Wychodze z funkcji.');
      exit;
    end;

  end;

 {**************************************************************************
  *
  *   Ta funkcja zwraca numer indeksu dla pobranego slowa Graya.
  *
  *   Parametry
  *   v  [in] -  macierzy wyjsciowa zawierajaca w pierwszym elemencie
  *              warosc ile_m oraz w ile_m kolejnych elementow
  *              szukane slowo Grey'a
  *
  *   n [out] -  szukany indeks slowa Gray'a
  *
  **************************************************************************}
  function SlowoGrayaNaIndeks(v:vector):integer;
  var
    b   : vector;
    i,j : Integer;
    suma: Integer;
  begin
    b[1]:=v[1];
    for j:=v[1]+1 downto 2 do begin
      suma:=0;
      for i:=j downto 2 do
        suma:=suma+v[i];
      b[j]:=suma mod 2;
    end;
    SlowoGrayaNaIndeks:=ZmianaPodstwy2Liczba(2,b);
  end;

  {***************************************************************************
  *
  *   Funkcja ta generuje wektor przejsc korzystajac z tablic.
  *   Wektor przejsc zawiera numery bitow, ktore ulegaja zmianie w generowaniu
  *   kolejnych slow kodu Grey'a.
  *   Podawany argument n oraz dlugosc rozpatrywanych slow w kodzie Grey'a,
  *   maja taka sama wartosc.
  *
  *   n [in]     - dlugosc wektora wejsciowego
  *   Tout [out] - wygenerowany wektor przejsc
  *
  *   UWAGA:
  *   Pierwszy element w wektorze wyjsciowym zawiera dlugosc tego wygenerowanego
  *   wektora.
  ***************************************************************************}
  function GenerujWektorPrzejsc(n: Integer): vector;
  var
    i,k,Twsk,j: Integer;
    flag      : Boolean;
    v,Tout    : vector;
    warunekZak: Integer;
  begin
    // inicjowanie wartosci poczatkowych
    i:=1; Twsk:=2;
    flag:=True;
    warunekZak := pow(2,n)-1;

    for j:=1 to n do v[j]:=j;

    while flag do begin
      if v[i]>0 then begin
        Tout[Twsk]:=v[i];
        inc(Twsk);
        v[i]:=0;
        for k:=i-1 downto 1 do v[k]:=k;
        i:=1;
      end else
        inc(i);
      // obliczamy wartosci do polowy, poniewaz wartosci w ciagu sa takie same
      // jak wartosci w obliczonym ciagu ale od tylu.

      // TO DO: dla n= 2 ten program nie dziala. Powodem jest ten warunek ponizej.
      // Powoduje on wystepowanie petli nieskonczonej
      if Twsk=( (warunekZak+1) div 2 ) then flag:=False;
    end;
    // wartosc 2^(n-1) jest zawsze rowna n (jest to srodek ciagu, miejsce
    // w kodzie Grey'a gdzie pierwsza wartosc kodu zmienia sie z 0 na 1)
    Tout[Twsk+1]:=n;
    // TODO:  nie wiem czemu ale cos sie kopie na tym wskazniku wiec ustwie go na twrado
    Tout[Twsk]:=1;
    // reszta juz jest znana - wiec przepisujemy

    j:=0;
    for i:=Twsk+2 to warunekZak+1 do begin
      Tout[i]:=Tout[Twsk-j];
      inc(j);
    end;

    Tout[1]:=warunekZak;                     //w pierwszym elemencie jest liczba okreslajaca dlugosc wektora przejsc
    GenerujWektorPrzejsc:=Tout;
  end;


  // PONIZSZE PROCEDURY SA POTRZBNE DO GENEROWANIA PODZBIOROW I OGOLNIE DO
  // DZIALANIA PROGRAMU.
  // CALA TRUDNOSC ALGORYMU POLEGA NA WYZNACZENIU WEKTORA PRZEJSC.
  // OPIS ALGORYTMU:
  // 1. GENERUJEMY WEKTOR PRZEJSC
  // 2. WYKORZYSTUJEMY TEN WEKTOR DO GENEROWANIA SLOW KODU GREYA
  // 3. WYGENEROWANE SLOWO GREYA PODAJEMY DO PROCCEDURY PokazImiona(), KTORA
  //    WSTAWIA W MIEJSCE JEDYNEK ODPOWIEDNIE SLOWA (W TYM PRZYPADKU IMIONA)


var
  i,n: Integer;
  v,w: vector;
  imie: array[1..10] of String;

procedure PodajImiona(n: integer);
var
  i: Integer;
begin
  for i:=1 to n do begin
    write('Podaj imie ',i,': ');
    Readln(imie[i]);
  end;
end;

procedure PokazImiona(v: vector; n: Integer);
var
  j: Integer;
begin
  for j:=1 to n do
    if (v[j]=1) then
      write(imie[j],',');
  writeln;
end;

procedure GenerujPodzbiory;
begin
// nmax dla tablicy w typie vector jest ustawione na 1025
// wiec maxymalna liczba elementow w slowie Gray'a nie moze byc wieksza niz 10

  w:=GenerujWektorPrzejsc(n);
  for i:=1 to n do
    v[i]:=0;
  // wystarczy tak bo tylko jedna liczba sie zmienia w jednym przejsciu
  for i:=1 to w[1] do begin
    if (v[w[i+1]] = 0) then
      v[w[i+1]]:=1
    else
      v[w[i+1]]:=0;
    write(i:2,': ');
    PokazImiona(v,n);
end;
end;

begin
Write('Ilosc elementow (wartosc od 2 do 10): '); Readln(n);
PodajImiona(n);
GenerujPodzbiory;
readln;
end.
Dodaj komentarz