unit TVectors;

interface

type
  TIntArray = array of Integer;

  TIntVector = class
    private
      //Arreglo contiene elementos desde 0 hasta tope
      tope: Integer;
      arreglo: array of Integer;
      fillValue: Integer;
    public
      Constructor Create(tamanioIni: Integer); overload;
      Constructor Create(tamanioIni: Integer; fillValue: Integer); overload;
      procedure Free;
      //arreglo[i]:= x
      procedure setArreglo(indice, x: Integer);
      //result:= arreglo[indice]
      function getArreglo(indice: Integer): Integer;

      //agrega un elemento al final
      function add(x: Integer): Integer;
      //mueve todos los elementos desde i un lugar hacia adelante arreglo[i + 1]:= arreglo[i]
      //y hace arreglo[i]:= x
      procedure insert(indice, x: Integer);
      procedure remove(indice: Integer);
      procedure Clear;
      function size(): Integer;

      //Si nuevoTamanio < tope se queda con el arreglo hasta nuevoTamanio
      //Si nuevoTamanio > tope agranda el arreglo llenando los nuevos lugares con fill
//      procedure resize(nuevoTamanio: Integer; fill: Integer);
      function capacity(): Integer;
      procedure setCapacity(newCapacity: Integer);

      function toArray(): TIntArray;

      property e[indice: Integer]: Integer read getArreglo write setArreglo; default;
      property a: TIntArray read toArray;
  end;
  TDAOfTIntVector = array of TIntVector;

procedure test();

implementation

Constructor TIntVector.Create(tamanioIni: Integer);
begin
  Create(tamanioIni, 0);
end;

Constructor TIntVector.Create(tamanioIni: Integer; fillValue: Integer);
begin
  inherited Create;
  SetLength(self.arreglo, trunc(tamanioIni * 1.1));
  self.fillValue:= fillValue;
  self.tope:= -1;
end;

procedure TIntVector.Free;
begin
  SetLength(arreglo, 0);
  inherited Free;
end;

procedure TIntVector.setArreglo(indice, x: Integer);
var
  i: Integer;
begin
  if indice > high(arreglo) then
    SetLength(arreglo, indice * 2);
  if indice = tope + 1 then
    tope:= indice
  else if indice > tope + 1 then
  begin
    for i:= tope + 1 to indice - 1 do
      arreglo[i]:= fillValue;
    tope:= indice;
  end;
  arreglo[indice]:= x;
end;

function TIntVector.getArreglo(indice: Integer): Integer;
begin
  result:= arreglo[indice];
end;

function TIntVector.add(x: Integer): Integer;
begin
  tope:= tope + 1;
  if tope > high(arreglo) then
    SetLength(arreglo, length(arreglo) * 2); //duplicamos el tamaño
  arreglo[tope]:= x;
  result:= tope;
end;

procedure TIntVector.insert(indice, x: Integer);
var
  i: Integer;
begin
  if indice > high(arreglo) then
    SetLength(arreglo, length(arreglo) * 2);
  if tope < indice then
  begin
    for i:= tope + 1 to indice - 1 do
      arreglo[i]:= fillValue;
    arreglo[indice]:= x;
    tope:= indice;
  end
  else
  begin
    for i:= tope downto indice do
      arreglo[i + 1]:= arreglo[i];
    arreglo[indice]:= x;
    tope:= tope + 1;
  end;
end;

procedure TIntVector.remove(indice: Integer);
var
  i: Integer;
begin
  if (indice <= tope) then
  begin
    for i:= indice to tope - 1 do
      arreglo[i]:= arreglo[i + 1];
    tope:= tope - 1;
  end;
end;

procedure TIntVector.Clear;
begin
  tope:= -1;
end;

function TIntVector.size(): Integer;
begin
  result:= tope + 1;
end;

{procedure TIntVector.resize(nuevoTamanio: Integer; fill: Integer);
var
  i, oldLength: Integer;
begin
  if nuevoTamanio - 1 < tope then
  begin
    for i:= nuevoTamanio to tope do
      arreglo[i]:= 0;
    tope:= nuevoTamanio - 1;
  end
  else if nuevoTamanio - 1 > tope then
  begin
    if nuevoTamanio - 1 > length(arreglo) then
    begin
      oldLength:= Length(arreglo);
      SetLength(arreglo, nuevoTamanio * 2);
      for i:= oldLength to high(arreglo) do
        arreglo[i]:= fill;
      tope:= nuevoTamanio - 1;
    end
    else
    begin

    end;
  end;
end;}

function TIntVector.capacity(): Integer;
begin
  result:= Length(arreglo);
end;

procedure TIntVector.setCapacity(newCapacity: Integer);
begin
  if tope >= newCapacity then
    tope:= newCapacity - 1;
  SetLength(arreglo, newCapacity);
end;

function TIntVector.toArray(): TIntArray;
begin
  result:= TIntArray(copy(arreglo, 0, tope + 1));
end;

procedure test();
var
  tam: Integer;
  vect: TIntVector;

  arr: TIntArray;
  i: Integer;
begin
  vect:= TIntVector.Create(10, 0);
  vect.add(0);
  vect.add(1);
  vect.add(2);
  vect.add(3);
  arr:= vect.a;  
  vect.Clear;

  vect[0]:= 0;
  vect[5]:= 5;
  vect[15]:= 15;
  arr:= vect.a;  
  vect.Clear;  

  for i:= 0 to 5 do
    vect[i]:= i;

  for i:= 0 to 5 do
    vect.remove(0);
  arr:= vect.a;
  vect.Clear;

  for i:= 0 to 5 do
    vect[i]:= i;

  for i:= 0 to 5 do
    vect.insert(2 * i, 1000);
  arr:= vect.a;
  vect.Clear;

  vect.remove(14);
  vect.add(50);
  vect.remove(5);
  vect.add(51);
  vect.add(52);
  vect.remove(0);  
  vect.insert(0, 1);
  vect.insert(vect.capacity + 1, 1);
  vect.insert(5, 1000);

  vect[100]:= 1;
  arr:= vect.a;

  tam:= vect.size;
  vect.setCapacity(round(0.5 * tam));
  vect.setCapacity(2 * tam);

  vect.Free;
end;

end.
