PDA

View Full Version : Simba Vectors



Echo_
01-31-2013, 02:01 AM
This is an implementation of a vector type. A vector is a container of elements like an array, but it can grow and shrink as you add and delete elements. Vectors are meant for adding elements to the end, as opposed to lists which are meant for adding elements to the front. Since I overloaded some functions, this will only be compatible with Lape. I also added a Map function just because I'm a big fan of functional programming :p

type
TVector = record
Size: Cardinal;
Elements: TVariantArray;
end;

{************************************************* ******************************
function Vector(Size: Cardinal): TVector;
by: Echo_
Description: Creates a new TVector with the given size.
************************************************** *****************************}
function Vector(Size: Cardinal): TVector; overload;
begin
Result.Size := Size;
SetLength(Result.Elements, Result.Size);
end;

{************************************************* ******************************
function Vector: TVector;
by: Echo_
Description: Creates a new TVector with a size of 0.
************************************************** *****************************}
function Vector: TVector; overload;
begin
Result := Vector(0);
end;

{************************************************* ******************************
function Vector(Elements: TVariantArray): TVector;
by: Echo_
Description: Creates a new TVector containing the given elements.
************************************************** *****************************}
function Vector(Elements: TVariantArray): TVector; overload;
var
I: Integer;
begin
Result := Vector(Length(Elements));
for I := 0 to High(Elements) do
Result.Elements[I] := Elements[I];
end;

{************************************************* ******************************
function TVector.IsEmpty: Boolean;
by: Echo_
Description: Returns true i the size is 0, false otherwise.
************************************************** *****************************}
function TVector.IsEmpty: Boolean;
begin
Result := Size = 0;
end;

{************************************************* ******************************
function TVector.IndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the first index of X, -1 otherwise.
************************************************** *****************************}
function TVector.IndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := 0 to Size - 1 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;

{************************************************* ******************************
function TVector.LastIndexOf(X: Variant): Integer;
by: Echo_
Description: Returns the last index of X, -1 otherwise.
************************************************** *****************************}
function TVector.LastIndexOf(X: Variant): Integer;
var
I: Integer;
begin
Result := -1;
for I := Size - 1 downto 0 do
if Elements[I] = X then begin
Result := I;
Break;
end;
end;

{************************************************* ******************************
function TVector.ContainsElement(X: Variant): Boolean;
by: Echo_
Description: True X is in the TVector, false otherwise.
************************************************** *****************************}
function TVector.ContainsElement(X: Variant): Boolean;
begin
Result := IndexOf(X) >= 0;
end;

{************************************************* ******************************
function TVector.GetElement(Index: Cardinal): Variant;
by: Echo_
Description: Returns the value at elements[index].
************************************************** *****************************}
function TVector.GetElement(Index: Cardinal): Variant;
begin
Result := Elements[Index];
end;

{************************************************* ******************************
procedure TVector.SetElement(Index: Cardinal; X: Variant);
by: Echo_
Description: Sets the value at elements[index] to x.
************************************************** *****************************}
procedure TVector.SetElement(Index: Cardinal; X: Variant);
begin
Elements[Index] := X;
end;

{************************************************* ******************************
procedure TVector.AddElement(X: Variant);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant); overload;
begin
Inc(Size);
SetLength(Elements, Size);
Elements[Size - 1] := X;
end;

{************************************************* ******************************
procedure TVector.AddElement(X: Variant; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElement(X: Variant; Index: Cardinal); overload;
var
I: Integer;
A: TVariantArray;
begin
Inc(Size);
SetLength(Elements, Size);
for I := Size - 1 downto Index + 1 do
Elements[I] := Elements[I - 1];

Elements[Index] := X;
end;

{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray);
by: Echo_
Description: Adds X to the end of the TVector.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray); overload;
var
S, I: Integer;
begin
S := Size;
Size := Size + Length(X);
SetLength(Elements, Size);
for I := S to Size - 1 do
Elements[I] := X[I - S];
end;

{************************************************* ******************************
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal);
by: Echo_
Description: Adds X at elements[index], shifting the remaining values right.
************************************************** *****************************}
procedure TVector.AddElements(X: TVariantArray; Index: Cardinal); overload;
var
I: Integer;
begin
Size := Size + Length(X);
SetLength(Elements, Size);
for I := Index + High(X) downto Index do
Elements[I + Length(X)] := Elements[I];

for I := 0 to High(X) do
Elements[I + Index] := X[I];
end;

{************************************************* ******************************
procedure TVector.DeleteElement(Index: Cardinal);
by: Echo_
Description: Deletes elements[index], shifting the remaining values left.
************************************************** *****************************}
procedure TVector.DeleteElement(Index: Cardinal);
var
I: Integer;
begin
for I := Index + 1 to Size - 1 do
Elements[I - 1] := Elements[I];

Dec(Size);
SetLength(Elements, Size);
end;

{************************************************* ******************************
procedure TVector.DeleteElements(Start, Finish: Cardinal);
by: Echo_
Description: Deletes elements between start (inclusive) and finish (exclusive).
************************************************** *****************************}
procedure TVector.DeleteElements(Start, Finish: Cardinal);
var
Offset, I: Integer;
begin
Offset := Finish - Start;
for I := Finish to Size - 1 do
Elements[I - Offset] := Elements[I];

Size := Size - Offset;
SetLength(Elements, Size);
end;

{************************************************* ******************************
procedure TVector.DeleteOccurrence(X: Variant);
by: Echo_
Description: Deletes the first element equal to X.
************************************************** *****************************}
procedure TVector.DeleteOccurrence(X: Variant);
var
Index: Integer;
begin
Index := IndexOf(X);
if Index = -1 then
Exit;

DeleteElement(Index);
end;

{************************************************* ******************************
procedure TVector.DeleteLastOccurrence(X: Variant);
by: Echo_
Description: Deletes the last element equal to X.
************************************************** *****************************}
procedure TVector.DeleteLastOccurrence(X: Variant);
var
Index: Integer;
begin
Index := LastIndexOf(X);
if Index = -1 then
Exit;

DeleteElement(Index);
end;

{************************************************* ******************************
procedure TVector.Clear;
by: Echo_
Description: Sets size to 0 and deletes all elements.
************************************************** *****************************}
procedure TVector.Clear;
begin
Size := 0;
SetLength(Elements, Size);
end;

{************************************************* ******************************
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
by: Echo_
Description: Applies function F to each element in V, returning a new TVector
containing the results.
************************************************** *****************************}
function Map(F: function(X: Variant): Variant; const V: TVector): TVector;
var
I: Integer;
begin
Result := Vector(V.Size);
for I := 0 to High(V.Elements) do
Result.SetElement(I, F(V.GetElement(I)));
end;

An example of how to use Map:
function Add2(A: Variant): Variant;
begin
Result := VarAsType(A, varInteger) + 2;
end;

var
A: TVariantArray;
X, Y: TVector;
begin
ClearDebug;
A := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
X := Vector(A);
Y := Map(@Add2, X);
WriteLn(X);
WriteLn(Y);
end.

This code will print:

{SIZE = 10, ELEMENTS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
{SIZE = 10, ELEMENTS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12]}

Enjoy :)

Le Jingle
01-31-2013, 02:19 AM
Pretty snazzy, maybe the lape compatible SRL 6 Devs ( Zyt3x; Coh3n; etc :]) might wana lookie?

~Lj

Echo_
01-31-2013, 03:45 AM
Ty
EDIT: added DeleteElements for deleting multiple values at a time.

x[Warrior]x3500
01-31-2013, 04:58 AM
oh vectors, definitely my favorite data struct from c++. great job on this! hopefully it can be added into lape as well.

Echo_
01-31-2013, 05:11 AM
It's not meant to be added into the Lape interpreter, if I had written it for that purpose then it would be object oriented :p What I meant by "only compatible with Lape" was that the overload keyword is not recognized by the PascalScript interpreter.

I mostly wrote this so that I could include it in scripts and have a dynamic collection type at my disposal. That's why it's in the snippets section.

Zyt3x
01-31-2013, 11:32 AM
I think this is a good addition, though
Will make AI programming like Neural Network programming easier. I'm at school now, but will look further into this later :)

Thanks for the mention, Lj

Dgby714
01-31-2013, 02:09 PM
You should take advantage of Lape's type methods.

Also, Lape now has some generics for Delete, Insert and Copy. You can use them on the internal array.

You could prob make this more efficient.

You really don't need to keep record of the element type, just the size.

Echo_
01-31-2013, 05:29 PM
You should take advantage of Lape's type methods.

Also, Lape now has some generics for Delete, Insert and Copy. You can use them on the internal array.

You could prob make this more efficient.

You really don't need to keep record of the element type, just the size.

Thanks for the advice, I changed it to use type methods, and removed unnecessary code. It's a lot cleaner now.
I haven't been able to get Delete, Insert, or Copy to work with anything other than AnsiString.

Zyt3x
01-31-2013, 06:08 PM
Using Simba 1000?

Echo_
01-31-2013, 06:32 PM
Using Simba 1000?

No, I've been using 992 :p I'll go download 1000 now

Edit: Still didn't work, maybe I'm doing it wrong?:

program new;

var
A, B: array of Variant;
begin
A := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
B := Copy(A, 4, 3);
WriteLn(A);
WriteLn(B);
end.


Exception in Script: Expected variable of type "AnsiString", got "array of Variant" at line 7, column 12

Dgby714
01-31-2013, 09:16 PM
No, I've been using 992 :p I'll go download 1000 now

Edit: Still didn't work, maybe I'm doing it wrong?:

program new;

var
A, B: array of Variant;
begin
A := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
B := Copy(A, 4, 3);
WriteLn(A);
WriteLn(B);
end.


Exception in Script: Expected variable of type "AnsiString", got "array of Variant" at line 7, column 12

Hmm weird, it should work, I'll look into it, we may need to update the Lape we are using.

Dgby714
02-02-2013, 02:06 AM
Yeah, we just need to update Simba's Lape. It's currently set right before the Copy and stuff was added.