SRL Archive - General

string.reverse();


footballjds

2014-01-09 13:46:42

I couldn't find it so i wrote it:

program new;
var
str: string := '123456789';
str2: string := 'abcdefghijklmnopqrstuvxyz';

procedure string.reverse();
var
temp_str: string;
i, l, l2: integer;
begin
temp_str := self;
l := length(self);
l2 := l;
for i := 1 to l do
begin
self[i] := temp_str[l2];
l2 := l2-1;
end;
end;

begin
writeln('string 1: '+str);
str.reverse();
writeln('string 1(reversed): '+str);
writeln('string 1: '+str2);
str2.reverse();
writeln('string 1(reversed): '+str2);
end.

Compiled successfully in 265 ms.
string 1: 123456789
string 1(reversed): 987654321
string 1: abcdefghijklmnopqrstuvxyz
string 1(reversed): zyxvutsrqponmlkjihgfedcba
Successfully executed.

Janilabo

2014-01-09 14:02:28

Nice one, fbjds!

Here is version I wrote a while ago - taken from String Handling Commands topic:

var
str: string := '123456789';
str2: string := 'abcdefghijklmnopqrstuvxyz';

function Reverse(str: string): string;
var
i, l: Integer;
begin
l := Length(str);
SetLength(Result, l);
for i := l downto 1 do
Result[i] := str[((l - i) + 1)];
end;

begin
ClearDebug;
WriteLn('string 1: '+str);
str := Reverse(str);
WriteLn('string 1(reversed): ' + str);
WriteLn('string 1: ' + str2);
str2 := Reverse(str2);
WriteLn('string 1(reversed): ' + str2);
end.

Any other ways to do the job? :)

masterBB

2014-01-09 14:13:12

From: Janilabo

Any other ways to do the job? :)


Swapping?

var
str: string := '123456789';
str2: string := 'abcdefghijklmnopqrstuvxyz';

function Reverse2(str: string): string;
var
i, l, half: Integer;
begin
l := Length(str) + 1;
SetLength(Result, l - 1);
half := Floor(l / 2);
for i := 1 to half do
begin
Result[i] := str[l - i];
Result[l - i] := str[i];
end;
end;

begin
ClearDebug;
WriteLn('string 1: '+str);
str := Reverse(str);
WriteLn('string 1(reversed): ' + str);
WriteLn('string 1: ' + str2);
str2 := Reverse(str2);
WriteLn('string 1(reversed): ' + str2);
end.

not tested, just wrote it in browser.

footballjds

2014-01-09 14:20:31

masterBB, looks less resource intensive :p

Janilabo

2014-01-09 14:26:32

From: masterBB
Swapping?

var
str: string := '123456789';
str2: string := 'abcdefghijklmnopqrstuvxyz';

function Reverse2(str: string): string;
var
i, l, half: Integer;
begin
l := Length(str) + 1;
SetLength(Result, l - 1);
half := Floor(l / 2);
for i := 1 to half do
begin
Result[i] := str[l - i];
Result[l - i] := str[i];
end;
end;

begin
ClearDebug;
WriteLn('string 1: '+str);
str := Reverse(str);
WriteLn('string 1(reversed): ' + str);
WriteLn('string 1: ' + str2);
str2 := Reverse(str2);
WriteLn('string 1(reversed): ' + str2);
end.

not tested, just wrote it in browser.
Yeah that's definitely the best way to go!
It works, you just need to replace the Reverse's in mainloop to Reverse2 instead. :p

Nice job!

Edit: I would probably even get rid of that Floor-call, like this:

var
str: string := '123456789';
str2: string := '0123456789';

function Reverse2(str: string): string;
var
h, i, l: Integer;
begin
l := (Length(str) + 1);
SetLength(Result, (l - 1));
h := (l div 2);
for i := 1 to h do
begin
Result[i] := str[((l - i))];
Result[((l - i))] := str[i];
end;
end;

begin
ClearDebug;
WriteLn('string 1: '+str);
str := Reverse2(str);
WriteLn('string 1(reversed): ' + str);
WriteLn('string 1: ' + str2);
str2 := Reverse2(str2);
WriteLn('string 1(reversed): ' + str2);
end.

Not that it really makes it that much cheaper…

masterBB

2014-01-09 15:53:39

It is not better. You just asked for another way :p

Janilabo

2014-01-09 16:00:44

From: masterBB
It is not better. You just asked for another way :p
Better or not, I am just glad you brought it up mate!

masterBB

2014-01-09 16:06:33

From: Janilabo
Better or not, I am just glad you brought it up mate!


Then I hope you are happy with another way:

procedure string.reverse();
var
i, l, half: Integer;
begin
l := Length(Self);
half := l div 2;
Inc(l);
for i := 1 to half do
begin
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[l - i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
end;
end;

Janilabo

2014-01-09 16:11:27

From: masterBB
Then I hope you are happy with another way:

procedure string.reverse();
var
i, l, half: Integer;
begin
l := Length(Self);
half := l div 2;
Inc(l);
for i := 1 to half do
begin
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[l - i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
end;
end;
Yes sir, I am!

Now that is an interesting way to do it - I like it man.

masterBB

2014-01-09 16:13:31

From: Janilabo
Yes sir, I am!

Now that is an interesting way to do it - I like it man.


If only we had a string to bytearray cast this could actually be useful. I wouldn't be suprised if footballjds his function is still the fastest.

E: This feels like the good old days :p

Janilabo

2014-01-09 16:33:29

From: masterBB
If only we had a string to bytearray cast this could actually be useful. I wouldn't be suprised if footballjds his function is still the fastest.

E: This feels like the good old days :p
Heh yeah, couldn't agree more! It's fun to work around simple challenges like these every now and then. :)

I guess we can always do some basic/simple timing between the ways:

procedure string.reverse();
var
temp_str: string;
i, l, l2: integer;
begin
temp_str := self;
l := length(self);
l2 := l;
for i := 1 to l do
begin
self[i] := temp_str[l2];
l2 := l2-1;
end;
end;

procedure string.reverse2();
var
i, l, half: Integer;
begin
l := Length(Self);
half := l div 2;
Inc(l);
for i := 1 to half do
begin
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[l - i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
end;
end;

function Reverse(str: string): string;
var
i, l: Integer;
begin
l := Length(str);
SetLength(Result, l);
for i := l downto 1 do
Result[i] := str[((l - i) + 1)];
end;


function Reverse2(str: string): string;
var
i, l, half: Integer;
begin
l := Length(str) + 1;
SetLength(Result, l - 1);
half := Floor(l / 2);
for i := 1 to half do
begin
Result[i] := str[l - i];
Result[l - i] := str[i];
end;
end;

function Reverse3(str: string): string;
var
h, i, l: Integer;
begin
l := (Length(str) + 1);
SetLength(Result, (l - 1));
h := (l div 2);
for i := 1 to h do
begin
Result[i] := str[((l - i))];
Result[((l - i))] := str[i];
end;
end;

var
str, tmp, m: string;
t, i: Integer;

begin
ClearDebug;
str := (StringOfChar('A', 5000000) + StringOfChar('B', 5000000) + StringOfChar('C', 5000000));
t := GetTimeRunning;
tmp := Reverse(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse: ' + IntToStr(t) + ' ms. [' + m + ']');
t := GetTimeRunning;
tmp := Reverse2(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse2: ' + IntToStr(t) + ' ms. [' + m + ']');
t := GetTimeRunning;
tmp := Reverse3(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse3: ' + IntToStr(t) + ' ms. [' + m + ']');
tmp := str;
t := GetTimeRunning;
tmp.reverse;
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('string.reverse: ' + IntToStr(t) + ' ms. [' + m + ']');
tmp := str;
t := GetTimeRunning;
tmp.reverse2;
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('string.reverse2: ' + IntToStr(t) + ' ms. [' + m + ']');
end.

Brandon

2014-01-09 17:08:53


Function Reverse(S: String): String;
var
Ptr: ^Char;
I, L: Integer;
Begin
L := Length(S);
SetLength(Result, L);
Ptr := @S[L + 1];

For I := 1 To L Do
Result[I] := (Ptr := Ptr - 1)^;
End;

Kasi

2014-01-09 17:13:42

@Brandon;

Was gonna attempt a Pointer reverse before you posted -.-

Janilabo

2014-01-09 17:17:41

From: Brandon

Function Reverse(S: String): String;
var
Ptr: ^Char;
I, L: Integer;
Begin
L := Length(S);
SetLength(Result, L);
Ptr := @S[L + 1];

For I := 1 To L Do
Result[I] := (Ptr := Ptr - 1)^;
End;
Dang, I was kinda waiting for Brandon to popup here…
..and so he did.

That is a fast and clever solution man, woah!
Included to the timing script:

procedure string.reverse();
var
temp_str: string;
i, l, l2: integer;
begin
temp_str := self;
l := length(self);
l2 := l;
for i := 1 to l do
begin
self[i] := temp_str[l2];
l2 := l2-1;
end;
end;

procedure string.reverse2();
var
i, l, half: Integer;
begin
l := Length(Self);
half := l div 2;
Inc(l);
for i := 1 to half do
begin
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[l - i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
Self[i] := Char(Byte(Self[i]) xor Byte(Self[l - i]));
end;
end;

function Reverse(str: string): string;
var
i, l: Integer;
begin
l := Length(str);
SetLength(Result, l);
for i := l downto 1 do
Result[i] := str[((l - i) + 1)];
end;


function Reverse2(str: string): string;
var
i, l, half: Integer;
begin
l := Length(str) + 1;
SetLength(Result, l - 1);
half := Floor(l / 2);
for i := 1 to half do
begin
Result[i] := str[l - i];
Result[l - i] := str[i];
end;
end;

function Reverse3(str: string): string;
var
h, i, l: Integer;
begin
l := (Length(str) + 1);
SetLength(Result, (l - 1));
h := (l div 2);
for i := 1 to h do
begin
Result[i] := str[((l - i))];
Result[((l - i))] := str[i];
end;
end;

Function Reverse4(S: String): String;
var
Ptr: ^Char;
I, L: Integer;
Begin
L := Length(S);
SetLength(Result, L);
Ptr := @S[L + 1];

For I := 1 To L Do
Result[I] := (Ptr := Ptr - 1)^;
End;

var
str, tmp, m: string;
t, i: Integer;

begin
ClearDebug;
str := (StringOfChar('A', 5000000) + StringOfChar('B', 5000000) + StringOfChar('C', 5000000));
t := GetTimeRunning;
tmp := Reverse(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse: ' + IntToStr(t) + ' ms. [' + m + ']');
t := GetTimeRunning;
tmp := Reverse2(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse2: ' + IntToStr(t) + ' ms. [' + m + ']');
t := GetTimeRunning;
tmp := Reverse3(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse3: ' + IntToStr(t) + ' ms. [' + m + ']');
t := GetTimeRunning;
tmp := Reverse4(str);
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('Reverse4: ' + IntToStr(t) + ' ms. [' + m + ']');
tmp := str;
t := GetTimeRunning;
tmp.reverse;
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('string.reverse: ' + IntToStr(t) + ' ms. [' + m + ']');
tmp := str;
t := GetTimeRunning;
tmp.reverse2;
t := (GetTimeRunning - t);
m := MD5(tmp);
WriteLn('string.reverse2: ' + IntToStr(t) + ' ms. [' + m + ']');
end.

Results for me turned out like this:

Reverse: 1857 ms. [47A75DD9F3E0DFA21C401ADAD158B815]
Reverse2: 1950 ms. [47A75DD9F3E0DFA21C401ADAD158B815]
Reverse3: 1950 ms. [47A75DD9F3E0DFA21C401ADAD158B815]
Reverse4: 1638 ms. [47A75DD9F3E0DFA21C401ADAD158B815]
string.reverse: 2044 ms. [47A75DD9F3E0DFA21C401ADAD158B815]
string.reverse2: 4618 ms. [47A75DD9F3E0DFA21C401ADAD158B815]

Looks like it wins easily, sweet.

Brandon

2014-01-09 17:54:55

From: Janilabo
Dang, I was kinda waiting for Brandon to popup here…
..and so he did.

That is a fast and clever solution man, woah!


Ahaha :D Thank you, thank you. The most optimized version of that is:


Function Reverse(S: String): String;
var
Ptr: ^Char;
I, L: Integer;
Begin
L := Length(S);
SetLength(Result, L);
Ptr := @S[L + 1];

For I := L DownTo 1 Do
Result[I] := (Ptr - I)^;
End;

The reason is because it gets rid of the subtraction by one and the assignment to Ptr and replaces it with just a subtraction with the help of a down-to loop. No assignment is done. That's probably the most I could optimise it (assuming that Simba behaves like a compiler would). I doubt replacing Result indexing with a pointer would help. But yeah, all nice solutions though. I like master-bb's. Never thought I'd live to see an XOR solution.

footballjds

2014-01-09 20:16:43

From: Brandon
Ahaha :D Thank you, thank you. The most optimized version of that is:


Function Reverse(S: String): String;
var
Ptr: ^Char;
I, L: Integer;
Begin
L := Length(S);
SetLength(Result, L);
Ptr := @S[L + 1];

For I := L DownTo 1 Do
Result[I] := (Ptr - I)^;
End;

The reason is because it gets rid of the subtraction by one and the assignment to Ptr and replaces it with just a subtraction with the help of a down-to loop. No assignment is done. That's probably the most I could optimise it (assuming that Simba behaves like a compiler would). I doubt replacing Result indexing with a pointer would help. But yeah, all nice solutions though. I like master-bb's. Never thought I'd live to see an XOR solution.


thanks for this! using it

bg5

2014-01-12 09:45:24

Not optimized but in one line;)
Function Reverse( S :string) : String;
var i:integer;
begin
for i := 1 to length(s) do Result := Result + s[length(s)-i+1];
end;

Janilabo

2014-01-12 14:14:01

From: bg5
Not optimized but in one line;)
Function Reverse( S :string) : String;
var i:integer;
begin
for i := 1 to length(s) do Result := Result + s[length(s)-i+1];
end;
Mate, waaat… 1 line?! I must be going either nuts or blind, because that function clearly looks like 5 lines to me - maybe even 7! :p
..just a bit sarcasm involved.
Looking good though, bg. Heck, it is tiny at least!

masterBB

2014-01-12 14:21:05

From: Janilabo
Mate, waaat… 1 line?! I must be going either nuts or blind, because that function clearly looks like 5 lines to me - maybe even 7! :p
..just a bit sarcasm involved.
Looking good though, bg. Heck, it is tiny at least!


Function Reverse(S :string) :String; var i:integer; begin for i := 1 to length(s) do Result := Result + s[length(s)-i+1]; end;

or

Function Reverse(S :string) :String; 
var
i:integer;
begin
for i := 1 to length(s) do
Result := Result + s[length(s) - i + 1];
end;

slacky

2014-05-13 10:32:13

Hum.. This should be quite a fast way to reverse it :P

function String.Reversed():string;
var
lo:PtrUInt;
p,r:PChar;
begin
SetLength(Result,length(self));
p := @Self[length(self)];
r := @Result[1];

lo := PtrUInt(@Self[1]);
while (lo<=PtrUInt(p)) do
begin
r^ := p^;
dec(p);
inc(r);
end;
end;

We could also do it without any aux mem, which is even faster.

procedure String.Reverse();
var
tmp:Char;
lo,hi:PChar;
begin
lo := @Self[1];
hi := @Self[length(self)];
while (PtrUInt(lo)<PtrUInt(hi)) do
begin
tmp := hi^;
hi^ := lo^;
lo^ := tmp;
dec(hi);
inc(lo);
end;
end;

[spoiler="Array example"]

function TExtendedArray.Reversed(): TExtendedArray;
var
lo:PtrUInt;
p,r:^Extended;
begin
SetLength(Result,length(self));
p := @Self[high(self)];
r := @Result[0];

lo := PtrUInt(@Self[0]);
while (lo<=PtrUInt(p)) do
begin
r^ := p^;
dec(p);
inc(r);
end;
end;

procedure TExtendedArray.Reverse();
var
tmp:Extended;
lo,hi:^Extended;
begin
lo := @Self[0];
hi := @Self[High(self)];
while (PtrUInt(lo)<PtrUInt(hi)) do
begin
tmp := hi^;
hi^ := lo^;
lo^ := tmp;
dec(hi);
inc(lo);
end;
end;
[/spoiler]


string.reverse : 912 ms. [648E181DC8C46BE035942EB110E9F5C3] //slacky
string.reversed: 998 ms. [648E181DC8C46BE035942EB110E9F5C3] //slacky
string.Reverse : 1279 ms. [648E181DC8C46BE035942EB110E9F5C3] //Brandon
Reverse : 1435 ms. [648E181DC8C46BE035942EB110E9F5C3] //masterBB
string.Reverse : 1528 ms. [648E181DC8C46BE035942EB110E9F5C3] //footballjds
Reverse : 1560 ms. [648E181DC8C46BE035942EB110E9F5C3] //Janilabo
string.Reverse : 2870 ms. [648E181DC8C46BE035942EB110E9F5C3] //MasterBB (xor fun)

SKy Scripter

2014-06-28 21:34:20

For C# Users lol

  public string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}