Author Topic: Sort the data  (Read 1267 times)

0 Members and 1 Guest are viewing this topic.

Offline Silnikos

  • Soldier
  • **
  • Posts: 129
Sort the data
« on: October 22, 2009, 02:08:21 pm »
I've got some info saved in .txt files like this:
Quote
blabla | times: 1
blablabla | times: 3
bladsala | times: 1
bladfd | times: 12
blafdsala | times: 14
blaasla | times: 5
I would like to load it as an array of string, get the numbers after 'tries: ', sort the lines by this criteria and save it back to the same file.

I tried to code it, but it somehow still doesn't work properly.

Code: [Select]
procedure sort();
begin
temp := ixsplit(ReadFile('w.txt'), chr(13)+chr(10));
for i:=0 to ArrayHigh(temp) do begin
cutlength := length(temp[i]) - (length(GetPiece(temp[i],' | times: ',1)));
_count[i] := strtoint(Copy(temp[i],cutlength,length(temp[i]))) + 1;
temp[i] := Copy(temp[i],1,cutlength) + inttostr(_count[i]);
end
if (_count[i] < _count[i+1]) and ((i+1) < ArrayHigh(temp)) then begin
_tempcount := temp[i];
temp[i] := temp[i+1];
temp[i+1] := temp[i];
writestring:=writestring+temp[i]+#13+#10;
end
WriteFile('w.txt',writestring);
writestring:='';
end;

Offline danmer

  • Camper
  • ***
  • Posts: 466
  • crabhead
Re: Sort the data
« Reply #1 on: October 22, 2009, 02:12:01 pm »
split each line too

Offline Silnikos

  • Soldier
  • **
  • Posts: 129
Re: Sort the data
« Reply #2 on: October 22, 2009, 02:24:26 pm »
What for? To get the amount of 'times'? I see now it would be easier to split them, but I got the same using GetPiece and it just doesn't work.

Offline Gizd

  • Flagrunner
  • ****
  • Posts: 586
  • (Re)tired
    • Eat-this! community site
Re: Sort the data
« Reply #3 on: October 22, 2009, 02:51:58 pm »
Save file using some unique char as a separator ie #3:
Code: [Select]
WriteLnFile('scorez.txt',IntToStr(IDToName(i)) + #3 + IntToStr(Tries[i]))
Then use GetPiece(Text,#3,1/0) to get the data.

Sorting code core:
Code: [Select]
var
  i, j, best: byte; // change to word if you want to sort more than 255 scores
  checked: array[1..<ammount of elements to sort>] of boolean;
  nomore: boolean;
  tries: array[1..<ammount of elements to sort>] of word;
begin
      for i:= 1 to <ammount of elements to sort> do tries[i]:= <assign score value>;
      j:= 1;
      for i:= 1 to <ammount of elements to sort> do checked[i]:= false;
      repeat
        best:= 0;
        for i:= 1 to <ammount of elements to sort> do if not checked[i] then if (best = 0) or (tries[i] < tries[best]) then best:= i;
        checked[best]:= true;
        // HERE YOU CAN DO STUFF WITH THE SORTED TRIES, "best" is current score ID(if you read them line-by-line it will be the line number), "j" is position on the 'list'
        j:= j + 1;
        nomore:= true;
        for i:= 1 to <ammount of elements to sort> do if not checked[i] then nomore:= false;
      until nomore;
end;
I cut it from one of my scripts and modified a bit so it may not work(ofc it won't work unless you turn it into a real script...), code is simple so you should be able to fix any mistakes/modify it.
« Last Edit: October 22, 2009, 02:56:44 pm by Gizd »

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: Sort the data
« Reply #4 on: October 23, 2009, 03:34:45 am »
Maybe MySSQL + QuickSort or SelectionSort ?!

Would require a slight modification on the sort algorithms though.
For QuickSort without MySSQL it should work as follows...

Code: [Select]
function ZeroFill(S: string; Peak: integer; IsEnabled: boolean): string;
var
  i, m: integer;
begin
  if (IsEnabled) then
  begin
    m:= Peak - length(S);
    for i:= 1 to m do
    begin
      S:= '0' + S;
    end;
  end;
  result:= S;
end;

procedure QuickSort(var AOS: array of string; Left, Right: integer; Ival: boolean; SortBy: integer);
var
  b, e, Pivot: string;
  i, l, m, r: integer;
begin
  if (Right > Left) then
  begin
    for i:= 0 to Right do
    begin
      e:= GetPiece(AOS[i], '|', SortBY);
      if (length(e) > m) then
      begin
        m:= length(e);
      end;
    end;
    l:= Left;
    r:= Right;
    Pivot:= ZeroFill(GetPiece(AOS[Random(Left, Right)], '|', SortBy), m, Ival);
    repeat
      while ((ZeroFill(GetPiece(AOS[l], '|', SortBy), m, IVal) > Pivot) and (l < Right)) do
      begin
        Inc(l, 1);
      end;
      while ((ZeroFill(GetPiece(AOS[r], '|', SortBy), m, IVal) < Pivot) and (r > Left)) do
      begin
        Dec(r, 1);
      end;
      if (l <= r) then
      begin
        b:= AOS[r];
        AOS[r]:= AOS[l];
        AOS[l]:= b;
        Inc(l, 1);
        Dec(r, 1);
      end;
    until (l >= r);
    if (Left < r) then
    begin
      QuickSort(AOS, Left, r, Ival, SortBy);
    end;
    if (Right > l) then
    begin
      QuickSort(AOS, l, Right, Ival, SortBy);
    end;
  end else
  begin
    exit;
  end;
end;

AOS: Array of string you want to sort
Left: Lowest array index
Right: Highest array index
Ival: Does every single string element represent a numeric value? (In your case I would set this to true)
SortBy: Determines which piece of the string is used for the sorting.

Btw, better delimit your segments with #9 instead of '|', unless you don't save for example player names into your file which may also contain '|'.

If you want to have a working sort algorithm which is suitable to MySSQL, let me know.
Soldat Global Account System: #soldat.sgas @ quakenet

Offline Silnikos

  • Soldier
  • **
  • Posts: 129
Re: Sort the data
« Reply #5 on: October 23, 2009, 06:24:16 am »
I tried QuickSort by CurryWurst - it change lines order, but not in the right way.

Code: [Select]
QuickSort(temp, 0, ArrayHigh(temp), true, 2);
for i:=0 to ArrayHigh(temp) do begin
writestring:=writestring+temp[i]+#13+#10;
end
WriteFile('whois_data/'+iprange+'.txt',writestring);
writestring:='';

in QuickSort in GetPiece I use "| times: " as a separator.
Code: [Select]
GetPiece(AOS[l], '| times: ', SortBy)(same for aos[r] and aos[random])

What's wrong?
« Last Edit: October 23, 2009, 06:27:52 am by Silnikos »

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: Sort the data
« Reply #6 on: October 23, 2009, 06:36:46 am »
Code: [Select]
blabla | times: 1
blablabla | times: 3
bladsala | times: 1
bladfd | times: 12
blafdsala | times: 14
blaasla | times: 5

The problem is you only delimit "blabbla" from "times: 14" which would require an additional split.
Why don't delimit all your segments by '|': "blabla|times|14" ?


Hmm, I do a test...

I tried QuickSort by CurryWurst - it change lines order, but not in the right way.

Code: [Select]
QuickSort(temp, 0, ArrayHigh(temp), true, 2);
for i:=0 to ArrayHigh(temp) do begin
writestring:=writestring+temp[i]+#13+#10;
end
WriteFile('whois_data/'+iprange+'.txt',writestring);
writestring:='';

in QuickSort in GetPiece I use "| times: " as a separator.
Code: [Select]
GetPiece(AOS[l], '| times: ', SortBy)(same for aos[r] and aos[random])

What's wrong?

Try this: QuickSort(temp, 0, ArrayHigh(temp), true, 1);
« Last Edit: October 23, 2009, 06:43:36 am by CurryWurst »
Soldat Global Account System: #soldat.sgas @ quakenet

Offline Silnikos

  • Soldier
  • **
  • Posts: 129
Re: Sort the data
« Reply #7 on: October 23, 2009, 07:07:38 am »

The problem is you only delimit "blabbla" from "times: 14" which would require an additional split.
Why don't delimit all your segments by '|': "blabla|times|14" ?

My only values are "blabla" and "14", "| times" is my delimit. I don't use "#9" or "|" because nicks can contain it. (theres a clan with tag "#two_random_numbers")

Try this: QuickSort(temp, 0, ArrayHigh(temp), true, 1);
Works, thanks.

Offline CurryWurst

  • Camper
  • ***
  • Posts: 265
    • Soldat Global Account System
Re: Sort the data
« Reply #8 on: October 23, 2009, 07:25:27 am »
Um
Try this: QuickSort(temp, 0, ArrayHigh(temp), true, 1);
Works, thanks.

Um, really? It doesn't for me lol :|


The problem is you only delimit "blabbla" from "times: 14" which would require an additional split.
Why don't delimit all your segments by '|': "blabla|times|14" ?

My only values are "blabla" and "14", "| times" is my delimit. I don't use "#9" or "|" because nicks can contain it. (theres a clan with tag "#two_random_numbers")

I have never been able to use a tabulator in my name, but thanks for the info.

Well, screw QuickSort. If you encounter more problems, better use this:

Code: [Select]
procedure ZeroFill(var S: string; const Count: word);
var
  i: word;
  b: string;
begin
  for i:= 1 to Count do
  begin
    b:= b + '0';
  end;
  S:= b + S;
end;

function SelectionSort(var AOS: array of string; const SortBy: word; const Ival: boolean; const Delim: string): integer;
var
  i, j, m, Index: integer;
  C1, C2: string;
  b: string;
begin
  Index:= GetArrayLength(AOS) - 1;
  for i:= 0 to Index do
  begin
    if (length(GetPiece(AOS[i], Delim, SortBy)) > m) then
    begin
      m:= length(GetPiece(AOS[i], Delim, SortBy));
    end;
  end;
  i:= 1;
  while (j < Index) do
  begin
    C1:= GetPiece(AOS[j], Delim, SortBy);
    C2:= GetPiece(AOS[j + i], Delim, SortBy);
    if (Ival) then
    begin
      ZeroFill(C1, m - length(C1));
      ZeroFill(C2, m - length(C2));
    end;
    if (C1 < C2) then
    begin
      b:= AOS[j];
      AOS[j]:= AOS[j + i];
      AOS[j + i]:= b;
      Inc(Result, 1);
    end;
    if (j + i < Index) then
    begin
      Inc(i, 1);
    end else
    begin
      i:= 1;
      Inc(j, 1);
    end;
  end;
end;

At least this algorithm worked for me, lol :P
Soldat Global Account System: #soldat.sgas @ quakenet