Scripting challenges!

Started by ., Jun 10, 2015, 10:13 AM

Previous topic - Next topic

DizzasTeR

Not the best way but okay.
[Spoiler=Code]function onPlayerCommand( player, cmd, text ) {
if( cmd == "g" ) {
local maxStars = text.tointeger();
if( maxStars ) {
for( local mainRun = 0; mainRun <= maxStars-1; mainRun++ ) {
local string = "";
for( local j = 1; j <= maxStars; j++ ) {
if( maxStars - j > mainRun ) {
string += ".";
}
else {
string += "*";
}
}
print( string );
}
}
}
}
[/Spoiler]

EK.IceFlake

[spoiler]
function PrintRowz(num)
{
    print("Number of rows: " + num);
    if (typeof(num) != "integer" || num < 1) return print("Rejected");
    local Repeat = function (str, num)
    {
        local ret = "";
        for (local i = 0; i < num; ++i) ret += str;
        return ret;
    }
    for (local i = 0; i < num; ++i)
    {
         print(Repeat(".", num - i) + Repeat("*", i));
    }
}
[/spoiler]
Untested.

.

#47
[spoiler]
function Generate(l) for (local f = function(p, l, x = 0, b = "") { while (++x <= l) b += x < (l-p) ? "." : "*"; return b; }, p = 0; p < l; ++p) print(f(p, l));[/spoiler]

Ex:
Generate(32);
Out:
...............................*
..............................**
.............................***
............................****
...........................*****
..........................******
.........................*******
........................********
.......................*********
......................**********
.....................***********
....................************
...................*************
..................**************
.................***************
................****************
...............*****************
..............******************
.............*******************
............********************
...........*********************
..........**********************
.........***********************
........************************
.......*************************
......**************************
.....***************************
....****************************
...*****************************
..******************************
.*******************************
********************************

I think I should be banned from these ;D
.

EK.IceFlake

Quote from: happymint on Apr 12, 2017, 01:41 PM[spoiler]
function Generate(l) for (local f = function(p, l, x = 0, b = "") { while (++x <= l) b += x < (l-p) ? "." : "*"; return b; }, p = 0; p < l; ++p) print(f(p, l));[/spoiler]

Ex:
Generate(32);
Out:
...............................*
..............................**
.............................***
............................****
...........................*****
..........................******
.........................*******
........................********
.......................*********
......................**********
.....................***********
....................************
...................*************
..................**************
.................***************
................****************
...............*****************
..............******************
.............*******************
............********************
...........*********************
..........**********************
.........***********************
........************************
.......*************************
......**************************
.....***************************
....****************************
...*****************************
..******************************
.*******************************
********************************

I think I should be banned from these ;D
Looks almost identical to mine but a bit more inefficient (you declare the function for every iteration rather than once outside the loop).

.

#49
Quote from: EK.IceFlake on Apr 12, 2017, 01:53 PMLooks almost identical to mine...

Not quite.

Quote from: EK.IceFlake on Apr 12, 2017, 01:53 PM...but a bit more inefficient...

Again, not quite accurate. You generate two strings I only generate one. Run a benchmark though. I'm pretty sure you'll fall for the newbie trap when you do. And you'll get some misleading results.

Quote from: EK.IceFlake on Apr 12, 2017, 01:53 PM...(you declare the function for every iteration rather than once outside the loop).

Please look at how for loops work before making that statement.
.

DizzasTeR

I did the benchmarks, and I didn't expect to see this.

[SCRIPT]  Starting Benchmark for doom's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.003
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for iceflake's method:
[SCRIPT]  Number of rows: 5
[SCRIPT]  .....
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  Benchmark ended: 0.004
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for slc's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.007
[SCRIPT]  -

Shadow

Quote from: Doom_Kill3R on Apr 12, 2017, 02:53 PMI did the benchmarks, and I didn't expect to see this.

[SCRIPT]  Starting Benchmark for doom's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.003
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for iceflake's method:
[SCRIPT]  Number of rows: 5
[SCRIPT]  .....
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  Benchmark ended: 0.004
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for slc's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.007
[SCRIPT]  -

You don't just benchmark one call. You make a big number of calls (like 1000000) then divide the execution time to this number of calls to get an accurate result (which is called an average weight).
QuotePS:is trash is ur home language??

DizzasTeR

Quote from: Shadow on Apr 12, 2017, 03:55 PM
Quote from: Doom_Kill3R on Apr 12, 2017, 02:53 PMI did the benchmarks, and I didn't expect to see this.

[SCRIPT]  Starting Benchmark for doom's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.003
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for iceflake's method:
[SCRIPT]  Number of rows: 5
[SCRIPT]  .....
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  Benchmark ended: 0.004
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for slc's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.007
[SCRIPT]  -

You don't just benchmark one call. You make a big number of calls (like 1000000) then divide the execution time to this number of calls to get an accurate result (which is called an average weight).

Ah yes sorry about that I didn't take an average one :-[

EK.IceFlake

Quote from: Doom_Kill3R on Apr 12, 2017, 02:53 PMI did the benchmarks, and I didn't expect to see this.

[SCRIPT]  Starting Benchmark for doom's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.003
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for iceflake's method:
[SCRIPT]  Number of rows: 5
[SCRIPT]  .....
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  Benchmark ended: 0.004
[SCRIPT]  -
[SCRIPT]  Starting Benchmark for slc's method:
[SCRIPT]  ....*
[SCRIPT]  ...**
[SCRIPT]  ..***
[SCRIPT]  .****
[SCRIPT]  *****
[SCRIPT]  Benchmark ended: 0.007
[SCRIPT]  -
Okay, so apparently, my method is offset by 1.
That's why you test your snippets, kids!

vito

Quote from: happymint on Apr 12, 2017, 01:41 PMfunction Generate(l) for (local f = function(p, l, x = 0, b = "") { while (++x <= l) b += x < (l-p) ? "." : "*"; return b; }, p = 0; p < l; ++p) print(f(p, l));
Quote from: happymint on Jul 04, 2016, 07:19 PMChrist, what a horrible coding style you have. Why do you have to make everything in one line when it looks so ugly.

EK.IceFlake

#55
After removing type checking and the "[SCRIPT]  Number of rows: 5" print (because others didn't do it - it's supposed to be a fair test after all), here's what I got:
[USR] Total iterations: 200
[USR] Average for Flake: 21111 us
[USR] Average for Doom: 21637 us
[USR] Average for SLC: 21889 us

I've noticed that the slowest part of this is print, and am quite sure that if we do this with variables instead, we'll reduce the total time by a factor of 10 or something.
200 iterations took about 20 seconds on my PC.

After replacing all print calls with an NOP instead, here is what I got (I used 500 iterations this time because it as a whole is much faster and this time the results aren't as reliable individually as they were before):
[USR] Total iterations: 500
[USR] Average for Flake: 307 us
[USR] Average for Doom: 308 us
[USR] Average for SLC: 326 us

Haven't quite replaced print with variables - rather, with a NOP, but it's still a reduction of not by a factor of 10 like I was expecting but a factor of almost 100.

[spoiler=The script I used for taking the benchmark]function kprint(val)
{

}

function PrintRowz(num)
{
    //kprint("Number of rows: " + num);
    //if (typeof(num) != "integer" || num < 1) return kprint("Rejected");
    local Repeat = function (str, num)
    {
        local ret = "";
        for (local i = 0; i < num; ++i) ret += str;
        return ret;
    }
    for (local i = 0; i < num; ++i)
    {
         kprint(Repeat(".", num - i) + Repeat("*", i));
    }
}

function Generate(l) for (local f = function(p, l, x = 0, b = "") { while (++x <= l) b += x < (l-p) ? "." : "*"; return b; }, p = 0; p < l; ++p) kprint(f(p, l));

function dum( maxStars ) {
 if( maxStars ) {
 for( local mainRun = 0; mainRun <= maxStars-1; mainRun++ ) {
 local string = "";
 for( local j = 1; j <= maxStars; j++ ) {
 if( maxStars - j > mainRun ) {
 string += ".";
 }
 else {
 string += "*";
 }
 }
 kprint( string );
 }
 }
}

local totalflake = 0;
local totaldoom = 0;
local totalslc = 0;

local iterations = 500;

for (local i = 1; i <= iterations; ++i)
{
    local t, to;
    print("Iteration " + i);
    print("---");
    print("Flake's method: ");
    t = SqTimer();
    PrintRowz(12);
    to = t.Elapsed.Microseconds.tointeger();
    print("Took " + to + " us");
    totalflake += to;
    print("Total counter for Flake: " + totalflake);
    print("");
    print("Doom's method: ");
    t = SqTimer();
    dum(12);
    to = t.Elapsed.Microseconds.tointeger();
    print("Took " + to + " us");
    totaldoom += to;
    print("Total counter for Doom: " + totaldoom);
    print("");
    print("SLC's method: ");
    t = SqTimer();
    Generate(12);
    to = t.Elapsed.Microseconds.tointeger();
    print("Took " + to + " us");
    totalslc += to;
    print("Total counter for SLC: " + totalslc);
    print("");
    print("---");
    print("Iteration complete");
    print("");
}

print("Total iterations: " + iterations);

print("Average for Flake: " + totalflake / iterations + " us");
print("Average for Doom: " + totaldoom / iterations + " us");
print("Average for SLC: " + totalslc / iterations + " us");
[/spoiler]

.

#56
Quote from: happymint on Apr 12, 2017, 02:23 PM... I'm pretty sure you'll fall for the newbie trap when you do. And you'll get some misleading results.

But did you disable the console output? Because that takes more time than the code itself. That's the newbie mistake #1 when doing benchmarks of code that outputs something.

There's one bottleneck in my example which I didn't even bother about. And that's the extra branching here "b += x < (l-p) ? "." : "*"". My challenge was not speed. But rather if I can keep it all in one statement. Trust me. If I wanted speed, you would've seen speed.
.

.

#57
You want speed? Here you go: https://pastebin.com/xzVvz9rW (I had to move it to paste-bin because the forum script is too retarded and collapses series of dots down to 3)

Why don't you benchmark this and then let's talk again.
.

EK.IceFlake

#58
Quote from: happymint on Apr 12, 2017, 04:54 PMBut did you disable the console output? Because that takes more time than the code itself. That's the newbie mistake #1 when doing benchmarks of code that outputs something.
That's exactly what my prediction was.
However, instead of 'disabling' it, I replaced the print functions with a NOP.

Anyways, with your new method:
[USR] Total iterations: 500
[USR] Average for Flake: 124 us
[USR] Average for Doom: 186 us
[USR] Average for SLC: 90 us

Good job :D

:edit: Not too fast.
Your script depends on you adjusting for length.
In which case:
function PrintRowz(num)
{
    switch (num)
    {
        case 0: break;
        case 1: print("*"); break;
        case 2: print("*.\n**"); break;
        case 3: print("*..\n**.\n***"); break;
    }
}
And so on

.

#59
Also, your benchmark has to much noise in it. It doesn't show the maximum throughput because it contains noise from other implementations. By the time the CPU warms up with an implementation it has to throw it away for the next one. Here are some more accurate results:

function kprint(v) return; // > dev/null
//---------------------------------------------------------------------------------------------------------------------
// warm up to avoid CPU throttling.
for (local n = 0, x = 0; n < 10000000; ++n) x = abs(n - x) % 2 * 2 / 2;
print("warm up complete");
//---------------------------------------------------------------------------------------------------------------------
function PrintRowz(num)
{
    if (typeof(num) != "integer" || num < 1) return;
    local Repeat = function (str, num)
    {
        local ret = "";
        for (local i = 0; i < num; ++i) ret += str;
        return ret;
    }
    for (local i = 0; i < num; ++i)
    {
         kprint(Repeat(".", num - i) + Repeat("*", i));
    }
}

local tm = clock();

for (local n = 0; n < 10000; ++n) PrintRowz(32);

print("Flake: " + (clock() - tm));
//---------------------------------------------------------------------------------------------------------------------
function doom( maxStars ) {
    if( maxStars ) {
        for( local mainRun = 0; mainRun <= maxStars-1; mainRun++ ) {
            local string = "";
            for( local j = 1; j <= maxStars; j++ ) {
                if( maxStars - j > mainRun ) {
                    string += ".";
                } else {
                    string += "*";
                }
            }
            kprint( string );
        }
    }
}

local tm = clock();

for (local n = 0; n < 10000; ++n) doom(32);

print("Doom: " + (clock() - tm));
//---------------------------------------------------------------------------------------------------------------------
function Generate(l) for (local f = function(p, l, x = 0, b = "") { while (++x <= l) b += x < (l-p) ? "." : "*"; return b; }, p = 0; p < l; ++p) kprint(f(p, l));

local tm = clock();

for (local n = 0; n < 10000; ++n) Generate(32);

print("SLC1: " + (clock() - tm));
//---------------------------------------------------------------------------------------------------------------------
const G_PERIOD_CONST = "...";
const G_ASTERIX_CONST = "********************************************************************************************************************************";
function Generate2(l) for (local p = 1; p <= l; ++p) kprint(G_PERIOD_CONST.slice(0, l-p) + G_ASTERIX_CONST.slice(0, p));

local tm = clock();

for (local n = 0; n < 10000; ++n) Generate2(32);

print("SLC2: " + (clock() - tm));

These were the results on my plugin x32:
[USR] Flake: 2.75
[USR] Doom: 3.108
[USR] SLC1: 3.094
[USR] SLC2: 0.359

These were the results on my plugin x64:
[USR] Flake: 2.312
[USR] Doom: 2.798
[USR] SLC1: 2.707
[USR] SLC2: 0.297

These are the results on the official plugin x32:
[SCRIPT]  Flake: 3.043
[SCRIPT]  Doom: 3.573
[SCRIPT]  SLC1: 3.575
[SCRIPT]  SLC2: 0.392

These are the results on the official plugin x64:
[SCRIPT]  Flake: 2.441
[SCRIPT]  Doom: 2.915
[SCRIPT]  SLC1: 2.85
[SCRIPT]  SLC2: 0.297

Here you can see that x64 builds yield better results due to less register pressure since x64 can use more registers on the CPU. And you can also see that some results were misleading in previous tests because there was a lot of noise from the other implementations since there wasn't enough isolation.
.