EventScripts Forums
Mattie's EventScripts and Source Forums
Mattie recommends...
Premier Sponsor:Platinum Sponsor:
 
Script Categories
addon (49) admin (269) admins (14) advert (15) adverts (19) afk (15) alerts (12) ammo (23) anti (15) auth (16) automatic (12) awp (23) ban (18) ba_jail (17) bhop (19) block (19) bomb (40) bonus (23) bot (24) bot-management (19) bots (17) bunnyhop (11) Buy (21) cash (65) chat (57) cheat (11) clan (16) classes (22) color (21) colors (18) command (20) commands (18) config (22) connect (42) CS:S (16) css (2500) Damage (35) database (11) dead (15) death (19) deathmatch (70) deathrun (12) disconnect (18) Dissolve (11) dm (20) dod:s (11) dods (386) easy (17) effects (120) English (15) entity (21) es_tools (12) Eventscript (12) flashbang (25) français (99) french (36) fun (286) funny (16) Gabeee (11) gameplay (174) give (16) gravity (11) grenade (25) grenades (29) gun (14) GunGame (26) GunGame5 (11) guns (17) Hack (15) headshot (32) health (54) hegrenade (13) hl2dm (329) HP (13) info (48) information (16) jail (26) jailbreak (11) join (23) jump (12) kick (23) kill (44) kills (22) knife (57) leveling (36) management (14) mani (15) map (25) map-management (27) maps (15) match (17) menu (106) message (20) messaging (52) mod (109) model (14) models (32) money (42) motd (12) music (29) mute (18) nades (18) name (13) noblock (35) player (40) player-management (31) player-tracking (28) popup (55) props (23) protection (27) punishment (50) python (63) quake (18) radio (21) random (36) rank (35) rates (16) rcon (13) realism (21) respawn (61) restrict (36) round (20) rpg (24) rules (42) say (11) scout (19) Script (20) script-helper (25) scriptpack (33) sdk (149) server (44) server-tools (42) shop (12) silly (31) simple (27) skins (24) slay (13) soccer (11) sound (45) sounds (92) spawn (63) speed (25) statistics (13) stats (48) STEAMID (23) Superhero (13) surf (31) Team (25) team-balance (14) teleport (12) text (14) TF2 (143) time (17) timer (14) tools (15) tracers (17) triggers (11) uedi (18) uses_auth (18) utility (11) vip (11) vote (36) voting (22) war (20) wcs (24) wcs:Python (32) weapon (77) weapons (114) web (14) welcome (12) zm (24) zombie (90) zombiemod (51) zombies (11)
Script Authors
*XYZ*SaYnt (12) .:MiB:. (11) .eMko* (6) 101satoon101 (10) 3R10N (24) 4u571n91 (5) 7355608 (9) Absolute (8) Ace Rimmer (40) adminc (5) Adz (8) AgathaKnuppelkuh (8) aidden (8) ajax (5) ak_47 (6) Al3c Tr3v3lyan (6) allstareng (5) ashbash1987 (9) ATAMAH (7) aznone (5) B00M (5) BackRaw (41) BFH_RedBull (8) bigfabi (7) Bioko (7) Blade (10) bladesback (13) bobdole (11) bodzsar1 (8) bonbon (36) Brainsucker (30) cagemonkey (8) carbon-14 (10) CaskioUTF (5) cbirou (15) ChaCaLz2psy4 (5) CharlesT (5) Chrisber (5) chrismrulz (9) Chun (6) cladiron (10) clipz934 (8) Colster (21) Cookieman8 (7) craziest (10) DanielB (19) Darkness123 (8) Dave (9) dbozan99 (7) deathx9 (5) Deathyy (16) dhack (16) Di[M]aN (12) DoCky (27) Don (15) dordtcore (8) DragonFreddo (8) Drassil (5) Einlanzers (42) EmbouT (10) emilplov (7) Errant (10) Eun (6) Fantole (9) Franc1sco (9) freddukes (18) Frequency (6) Fulmine (5) GAMEREN2 (8) german9114 (13) GODJonez (38) GoodfellaDeal (5) Hansi (6) HitThePipe (7) HOLLDIDAY (9) Icetouch (6) ichthys (25) infamous1 (9) Jeff91 (45) JoeyT2006 (30) Juba_PornBorn (12) jxl180 (10) KDBFame (6) L'In20Cible (7) Largo Usagi (10) Lobe (11) loKkdoKk (7) lolo-le-haricot (7) LosNir (5) Lumpi@Work (9) M4rc3L-XCN (7) macshot (6) Matth (5) Mattie (20) MBchrono (15) McFly (20) Medda (5) Memphis-84 (10) Messiah93 (12) Mickyy (5) micmacx (6) Mitchell (5) Mordavolt (7) MrScriptaz (5) mryoung (6) Nicolous (26) ojii (31) Omega_K2 (6) Owned|Myself (8) P3N (7) pand3mic (5) parsimba (5) Pascal257 (9) PatPeter (7) PDrop (10) Phaedrus (18) PhantOm Fury (7) phoenix131 (8) pinkyyy -.- (5) pitbull0993 (7) randomknifer (9) Ratzee (6) ReaCtioN2oo9 (6) Rennnyyy (17) revolutionfighters (6) RideGuy (12) Rio (9) Roeliekt (6) runamagic (13) sandking220 (6) Sarcasm_Poisoning (10) saRs| Johnny-5 (13) Schubaal (10) sea212 (5) sega74rus (7) sgt.angel (6) sicilia (5) sicman_adrian (22) skillz92 (7) sn4k3 (18) snake38 (10) sonicsight (7) spoonman184 (8) stabby (22) stas (22) Strontium Dog (30) SumGuy14 (25) SuperDave (45) surfteam (5) TaCo (5) TanaToS (17) Tealk (6) teowow (16) TheCheeTaH (20) TheDonFather (5) theresthatguy (6) Tiny Tod (7) Totyahun (9) uedi (38) Undead (25) usernamesaretaken (15) Warren (13) westham (6) WhiteAvenger (7) Wonder (14) X-Mania (5) XE_ManUp (13) xfalcon61 (5) zSweetXz (5) [Cs]Lord_Inferno2 (11) [NATO]Hunter (28) ||Wolf|| (10)
Search

Post new topic Reply to topic
Author Message
User avatar
Experienced
Profile

Posts: 446
Location:
Yes.
 
New postPosted: 2009-01-02, 6:43 pm 
   Post subject: Rolling Average

PYTHON:
    #!/usr/bin/python





    class avg():

       

        def __init__(self, size=20):

            self.size = size

            self.samples = []

            for each in range(size):

                self.samples.append(0)

            self.total = 0

            self.sum = 0

            self.index = 0

       

        def add(self, value):

           

            self.total += 1

           

            self.sum -= self.samples[self.index]

            self.sum += value

            self.samples[self.index] = value

            self.index = (self.index + 1) % self.size

           

           

        def avg(self):

            return 1.0 * self.sum / self.size

       

       

        def debug(self):

            print self.samples

            print self.total

            print self.index

            print self.sum

           

        def getSize(self):

            return self.size

       

        def getTotal(self):

            return self.total

           

    b = avg(100)



    for each in range(101):

        b.add(each)

    print b.avg()

    b.debug()


Initialize an array with a certain number of values (this is how many samples you want

Then use the add() method to add values. This keeps a rolling average of the past past 20 numbers, and only takes O(1) for averaging and adding. It also keeps a totalsum of all the values ever added, so that you can still calculate the total average of all the values ever put in there.


This would be a good method for ping kicking scripts.

_________________
Image





User avatar
Mentat
Mentat
Profile

Posts: 4727
Location:
C:/ProgramFiles/Bonbon/Bonbon.exe
 
New postPosted: 2009-01-02, 7:23 pm 

PYTHON:
    b = a('''class avg():

       

        def __init__(self, size=20):

            self.size = size

            self.samples = []

            for each in range(size):

                self.samples.append(0)

            self.total = 0

            self.sum = 0

            self.index = 0

       

        def add(self, value):

           

            self.total += 1

           

            self.sum -= self.samples[self.index]

            self.sum += value

            self.samples[self.index] = value

            self.index = (self.index + 1) % self.size

           

           

        def avg(self):

            return 1.0 * self.sum / self.size

    b = avg(10)

    for each in range(11):

            b.add(each)

    average = b.avg''')

    >>> b.timeit(1000)

    0.050582127058047988

    b

    >>> b.timeit(1000)

    0.049756533302417694

    >>> b.timeit(1000)

    0.054354324362453355


versus

PYTHON:
    b = a('''def average(values):

       return sum(values) / float(len(values))

    b = average(range(11))''').timeit

    >>> b(1000)

    0.0041035243305884705

    >>> b(1000)

    0.0040042100322636998

    >>> b(1000)

    0.0039947116183611797


DUN DUN DUN

_________________
SicmanAdrian wrote:
I don't think it is possible but maybe SuperDave could try?

abcdefghijklmnopqrstuvwxyz
"It doesn't work" doesn't help us out, help us help you, be more specific!
Remember, when posting non Python code, post in the ES 1.x discussion forum, you'll get better help!
SuperDave wrote:
It's very difficult to see errors in that script because it is some of the worst looking code I have ever seen. And I've seen bonbon's code

Please do not PM for free private scripts/help!


User avatar
Experienced
Profile

Posts: 446
Location:
Yes.
 
New postPosted: 2009-01-03, 2:45 am 

The cost of accuracy.

My example uses a low amount of memory and is made to be updated quickly.
a normal list is not made to be modified often.

_________________
Image


User avatar
Guru
Guru
Profile

Posts: 1268
 
New postPosted: 2009-01-03, 9:55 am 

Adminc's version is better IMO, because its packed into a class which could be easily modified into say my existing player class.
To improve speed you could compute the average when the .add() function is called, so the .avg() function uses a lot less CPU (Just prints the existing value).


User avatar
Mentat Philosopher
Mentat Philosopher
Profile

Posts: 5238
Location:
Kirkby, Nottinghamshire, United Kingdom
 
New postPosted: 2009-01-03, 4:35 pm 

Sorry.. I like Bonbon's version better... :)

Maybe it's just the simplicity and speed... but... meh

-freddukes

_________________
|--------------------------------------------------------|
| SourceRPG | AdMail | Comments | VoteMap | SpawnProp |
|--------------------------------------------------------|
IRC wrote:
<SuperDave|away> Common sense is overrated


User avatar
EventScripts Administrator
EventScripts Administrator
Profile

Posts: 12890
Location:
irc://irc.gamesurge.net/eventscripts
 
New postPosted: 2009-01-03, 11:42 pm 

Looking for speed and low memory consumption, eh? Try deque: http://www.python.org/doc/2.5.2/lib/deque-objects.html

This:
PYTHON:
            for each in range(size):

                self.samples.append(0)
would be faster and have less memory consumption as:
PYTHON:
            for each in xrange(size):

                self.samples.append(0)
or even better:
PYTHON:
            self.samples = [0] * size

Surely you don't need to do all the work you put into your class, most of the default Python functionality is fast enough:
PYTHON:
    from __future__ import division

    from collections import deque



    class avg(object):

        def __init__(self, size=20):

            self.size = size

            self.samples = deque()



        def add(self, value):

            self.samples.append(value)

            if len(self.samples) > self.size:

                self.samples.popleft()



        def avg(self):

            return sum(self.samples) / len(self.samples)



        def debug(self):

            print self.samples



        def getSize(self):

            return len(self.samples)



        def getTotal(self):

            return sum(self.samples)

bonbon's comparison isn't exactly fair, though, as each iteration she rebuilds the class. The class should exist before the code is timed (there is an argument for that in timeit.Timer).

_________________
Image
EventScripts Wiki --- #eventscripts --- Python.org --- es_install FAQ


Last edited by SuperDave on 2009-01-04, 6:17 am, edited 1 time in total.

User avatar
EventScripts Administrator
EventScripts Administrator
Profile

Posts: 12890
Location:
irc://irc.gamesurge.net/eventscripts
 
New postPosted: 2009-01-04, 1:39 am 

Let's take another look at timing the three pieces of code:
PYTHON:
    >>> import timeit



    ### Built-in ###

    >>>  timeit.Timer('''average(xrange(100))''',

    ... '''def average(values): return sum(values) / float(len(values))'''

    ... ).repeat(3, 1000)



    [0.0093556583308611607, 0.0077057279626444597, 0.0076034803306015419]



    ### Avg ###

    >>>  timeit.Timer('''a = avg(100)

    ... for x in xrange(100): a.add(x)

    ... a.avg()''', '''class avg():

    ...

    ...     def __init__(self, size=20):

    ...         self.size = size

    ...         self.samples = []

    ...         for each in range(size):

    ...             self.samples.append(0)

    ...         self.total = 0

    ...         self.sum = 0

    ...         self.index = 0

    ...

    ...     def add(self, value):

    ...

    ...         self.total += 1

    ...

    ...         self.sum -= self.samples[self.index]

    ...         self.sum += value

    ...         self.samples[self.index] = value

    ...         self.index = (self.index + 1) % self.size

    ...

    ...

    ...     def avg(self):

    ...         return 1.0 * self.sum / self.size

    ...

    ...

    ...     def debug(self):

    ...         print self.samples

    ...         print self.total

    ...         print self.index

    ...         print self.sum

    ...

    ...     def getSize(self):

    ...         return self.size

    ...

    ...     def getTotal(self):

    ...         return self.total ''').repeat(3, 1000)



    [0.2550028006352818, 0.25386327033180578, 0.25405351797502362]



    ### New avg ###

    # We have to "from __future__ import division" in the global scope

    >>> t = timeit.Timer('''a = avg()

    ... for x in xrange(100): a.add(x)

    ... a.avg()''', '''from collections import deque

    ...

    ... class avg(object):

    ...     def __init__(self, size=20):

    ...         self.size = size

    ...         self.samples = deque()

    ...

    ...     def add(self, value):

    ...         self.samples.append(value)

    ...         if len(self.samples) > self.size:

    ...             self.samples.popleft()

    ...

    ...     def avg(self):

    ...         return sum(self.samples) / len(self.samples)

    ...

    ...     def debug(self):

    ...         print self.samples

    ...

    ...     def getSize(self):

    ...         return len(self.samples)

    ...

    ...     def getTotal(self):

    ...         return sum(self.samples)''').repeat(3, 1000)



    # We cut it down a bit, but the default functions are worlds faster --

    # especially because there we only iterate over the range values once.

    [0.16462120185667573, 0.16148784272860439, 0.1621060777277421]

adminc wrote:
a normal list is not made to be modified often.
Lists are meant to be modified as often as needed. I don't see why you mention that since you use a list in your code.

deque objects are meant to be added to or removed from very quickly, from either the left or right. In fact, deque objects are what Queue objects use to store data.


Edit-- Here, got it down a little further by basing the class off deque:
PYTHON:
    from __future__ import division

    from collections import deque



    class avg(deque):

       def __init__(self, default=[], size=20):

          self.size = size

          deque.__init__(self, default)



       def append(self, value):

          deque.append(self, value)

          if len(self) > self.size:

             self.popleft()



       def avg(self):

          return sum(self) / len(self)
PYTHON:
    >>> timeit.Timer('''a = avg(size=100)

    ... for x in xrange(100): a.append(x)

    ... a.avg()''', '''from collections import deque

    ...

    ... class avg(deque):

    ...    def __init__(self, default=[], size=20):

    ...       self.size = size

    ...       deque.__init__(self, default)

    ...

    ...    def append(self, value):

    ...       deque.append(self, value)

    ...       if len(self) > self.size:

    ...          self.popleft()

    ...

    ...    def avg(self):

    ...       return sum(self) / len(self)''').repeat(3, 1000)

    [0.14285474829901545, 0.14415435481325289, 0.14290224036854227]
It goes down even further if we initialize the class with the values we want (the way bonbon does in her example):
PYTHON:
    >>> timeit.Timer('''a = avg(xrange(100), 100).avg()''',

    ... '''from collections import deque

    ...

    ... class avg(deque):

    ...    def __init__(self, default=[], size=20):

    ...       self.size = size

    ...       deque.__init__(self, default)

    ...

    ...    def append(self, value):

    ...       deque.append(self, value)

    ...       if len(self) > self.size:

    ...          self.popleft()

    ...

    ...    def avg(self):

    ...       return sum(self) / len(self)''').repeat(3, 1000)

    [0.0065946929009328414, 0.0066522421145691624, 0.0065731817870755549]

_________________
Image
EventScripts Wiki --- #eventscripts --- Python.org --- es_install FAQ


Last edited by SuperDave on 2009-01-04, 6:27 am, edited 3 times in total.

User avatar
Professor
Professor
Profile

Posts: 2376
Location:
I Come From a Land Down Under
 
New postPosted: 2009-01-04, 4:03 am 

SuperDave just pwned you all :P


User avatar
Mentat Philosopher
Mentat Philosopher
Profile

Posts: 5238
Location:
Kirkby, Nottinghamshire, United Kingdom
 
New postPosted: 2009-01-04, 6:51 am 

Just so you know, to emphaises SuperDave's point, deques are not the most efficient container for removing data contained in the middle of the container (He already stated at the ends...)... Basically they're good for stack like objects FIFO and LIFO storages, but for Random Access (insertion / deletion) sort of like a mix between a C++ Vector and List... So if it's a random list you're defining, still use a list for insertion to the middle... But things like gamethread delays (FIFO) systems and Queue objects such as this, deque's are the quickest...

Just my 2p.. Hope I haven't confused you more... :)

:)

_________________
|--------------------------------------------------------|
| SourceRPG | AdMail | Comments | VoteMap | SpawnProp |
|--------------------------------------------------------|
IRC wrote:
<SuperDave|away> Common sense is overrated


Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group