[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Table Sorting

Table Sorting

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Thu 05 May 2005 07:32 PM (UTC)
Message
Is there any way of sorting tables in a predefined way? I was thinking that I could it by having a second table with the correct sorting, then loop through it and checking each key to see if the first table had it, if so I would add it to a third table which would then be a correctly sorted table. But there has to be a better and faster way, right..?

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Flannel   USA  (1,230 posts)  [Biography] bio
Date Reply #1 on Thu 05 May 2005 07:38 PM (UTC)

Amended on Thu 05 May 2005 07:39 PM (UTC) by Flannel

Message
From the lua manual:

table.sort (table [, comp])
Sorts table elements in a given order, in-place, from table[1] to table[n], where n is the size of the table (see 5.4). If comp is given, then it must be a function that receives two table elements, and returns true when the first is less than the second (so that not comp(a[i+1],a[i]) will be true after the sort). If comp is not given, then the standard Lua operator < is used instead.
The sort algorithm is not stable, that is, elements considered equal by the given order may have their relative positions changed by the sort.


Basically, it sorts them by default (a < b) or does the PHP thing (usort) where you give it a function that can do your complicated comparisons (and uses the results from that to sort).

So, your use would depend on what you want sorted (and how).
And I believe it uses a bubble sort internally.

~Flannel

Messiah of Rose
Eternity's Trials.

Clones are people two.
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #2 on Thu 05 May 2005 09:06 PM (UTC)
Message
This is for keeping score on my afflictions (states of my character). For now I have them in a table called aff (like: aff['paralysis'] or aff['stupidity']) where they have a boolean value. I then check them one by one:
if aff['stupidity'] then
    eat('orphine')
elseif aff['paralysis'] then
    eat('maidenhair')
etc..

In zMUD I started off with having these afflictions in an array, which I sorted to have the most annoying/lethal ones in the top. Then I just picked the off using (translated to LUA):
cure(aff['1']). It got slow (damn tanky zMUD) so I replaced it with single variables for each affliction. I can't quite recall why I would want to use this method, other than laziness with all the IFs. ;) But still, if there's a method for doing this sorting, I'd like to learn.

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Flannel   USA  (1,230 posts)  [Biography] bio
Date Reply #3 on Fri 06 May 2005 04:35 AM (UTC)

Amended on Fri 06 May 2005 04:43 AM (UTC) by Flannel

Message
You could have another array (table, technically) that is just numerically indexed, that contains the afflictions from highest to lowest severity.
Then use the values in that to cycle through your afflictions in order.

And actually, you could have a third table with affliction names and their remedies (keys are names, values, remedies, like studidity => orphine) so you could have everything be dynamic, you cycle through your numerically indexed array to get the names of the keys, and then a simple if aff[names[i]] then eat(cures[names[i]]) in a loop.

I guess in code it would look something like this (I think):
for _,name in pairs (names) do
  if aff[name] then
    eat(cures[name])
  end
end

~Flannel

Messiah of Rose
Eternity's Trials.

Clones are people two.
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #4 on Sat 07 May 2005 09:30 PM (UTC)
Message
That's how I had it setup in zMUD. But with LUA, it's still a little harder for me to do. The next curve seems steeper, so to say. Mind explaining what that snippet of code does? Especially the underscore is there for. And also, is there some easy built-in functions to add/remove a value to an numeric array (table)? Remove duplicates? Found a snippet of code in lua.org to check if a value was present, so I'm thinking I'll have to code the add/remove/duplicate-functions on my own as well? (couldn't find anything for that in the PIL)

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Flannel   USA  (1,230 posts)  [Biography] bio
Date Reply #5 on Sat 07 May 2005 10:02 PM (UTC)

Amended on Sat 07 May 2005 10:06 PM (UTC) by Flannel

Message
http://www.lua.org/manual/5.0/manual.html#5.4
Has add/remove things. For duplicates, I think you'll have to iterate over it yourself.

As for the underscore, it could just as well be a k or whatever.

for k,v in pairs (table) puts a value k (key) and v (value) into the loop. I believe the underscore just says we don't care what it is (since we're only concerned with the values), I have no idea if it's any faster doing that though.

Instead of worrying about removing duplicates, why don't you just code in a check when adding values?

Anyway, that code loops through all the values in a (numerically indexed) table 'names' (presumably where you keep the names of afflictions, in the order you want to cure them) and for each of those names, it checks the value of that affliction (in the aff table, using the name as the key) and if so, it sends the value from the 'cures' table (again, using the name as the key).
What this doesn't however do, is break once something is found, but that's easy enough to do (just add a break statement into the if block).

~Flannel

Messiah of Rose
Eternity's Trials.

Clones are people two.
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #6 on Mon 09 May 2005 07:04 AM (UTC)
Message
I think you can solve this problem more creatively than using lots of tables. In Lua a table can consist of tables (ie. a table of tables).

Thus a single table could hold afflictions (by name, say) and for each one hold stuff like what the cure is, what string identifies it and so on.

Then rather than trying to sort the table for efficiency simply have a second table of the active afflictions. Tables can contain pointers (references) to other tables, so your second table could simply be a list of the active afflictions, you add to it when you get one, and delete from it when it is cured.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #7 on Mon 09 May 2005 09:14 AM (UTC)

Amended on Mon 09 May 2005 11:02 AM (UTC) by tobiassjosten

Message
Would you mind explaining how that would look? With the reference I mean. I do have multidimensional arrays for another module, tracking -> track['crox']['dstab']['miss'] would give me the amount of times crox have doublestabbed me, but missed. But you're talking about something else?

Edit: Remade the routines into using Flannels example, which might be a really smooth was of doing it.
How does this look?:
curesHerbs = {["stupidity"] = "orphine", ["paralysis"] = "maidenhair"}

function curePrompt ()
    if canEat () then cureHerb () end
end

function cureHerb ()
    for _,name in pairs (curesHerbs) do
      if aff[name] then
        eat(curesHerbs[name])
      end
    end
end

function canEat ()
    if bHerb and doHerb == false then
        if anorexia == false or doSalve == "epidermal" or doFocus then
            if unconcious ~= true and stunned ~= true and sleeping ~= true then
                if entangle['transfix'] ~= true then
                    return true
                end
            end
        end
    end
    return false
end

Edit2: Just came to think of an issue with this, concearning salves. They can be targeted (eg, apply mending to head) for better control of what you cure. In some cases you must target the salve. Can this be done by splitting strings in some way? Like, if I add the cure "restoration_head" for the affliction "crip_head", it sends apply("restoration", "head").

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Tue 10 May 2005 07:17 AM (UTC)

Amended on Tue 10 May 2005 07:19 AM (UTC) by Nick Gammon

Message
This is what I am talking about.


-- table of herbs and cures

curesHerbs =
{
  { name = "stupidity", cure = "orphine" },
  { name = "paralysis", cure = "maidenhair" },
  { name = "sleep", cure = "wildvine" },

}

tprint (curesHerbs)

-- current afflictions

currentAffs = {}

table.insert (currentAffs, curesHerbs [1])
table.insert (currentAffs, curesHerbs [3])

for k, v in currentAffs do
  print ("name = ", v.name)
  print ("cure = ", v.cure)
end -- for 

-- remove 2nd item

table.remove (currentAffs, 2)

tprint (currentAffs)


My table curesHerbs is a table of tables, where each item has a name (eg. name, cure).

The if an affliction is current you insert it into the currentAffs table (using table.insert). You can iterate through the current ones, see the "for" loop, where the value (v) is the reference to the original table, so you can dereference it (eg. v.name).

You can then remove it from the currentAffs table (using table.remove) however it still exists in the "master" table.

Output:



Master table 

1:
  cure=orphine
  name=stupidity
2:
  cure=maidenhair
  name=paralysis
3:
  cure=wildvine
  name=sleep

For loop, showing current afflictions

name =  stupidity
cure =  orphine
name =  sleep
cure =  wildvine

Current afflictions, after removing 2nd item

1:
  cure=orphine
  name=stupidity


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #9 on Tue 10 May 2005 09:57 PM (UTC)
Message
How will that for-loop scroll through the table? I did it as Flannel suggested and it worked excellent, if it werent for the fact that FOR seems to loop through the tables in a reversed alphabetic order.. Who the #¤%& wrote that FOR-routine?

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Akraa   (3 posts)  [Biography] bio
Date Reply #10 on Fri 13 May 2005 12:43 PM (UTC)
Message
hmm, Nick, is there any way to maintain the priorities from the curesHerbs table when you transfer it to the affliction list?

Because in your example, that would just make it a first on first off curing setup, so like, the actual order that affs are cured in isnt taken into account,despite the fact that you set priorities in the original table.
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #11 on Fri 13 May 2005 07:51 PM (UTC)
Message
With Nick's setup, you could instead loop through the curesHerb-table and check if the current value is true in your affliction-list. Methinks.

I've been pondering this some, and come up with the thought that there must be a more efficient to track/cure afflictions with LUA's tables. Let me explain IRE's affliction/curing-system some, and perhaps some of the veterans gets an idea?

There are alot of afflictions, which all have their effect. Some restricts an action (attacks/curing-method/ect), some damages you, some decreases the information sent to you.
These afflictions are all normally cured in just one way: eating a herb, applying a salve, smoking a herb or drinking an elixir. There are however some other curing methods, which you get access to buy training certain skills. These curing methods have their own lists of afflictions they are able to cure, which interlaces with the regular ones. All curing methods have their individual balances, and you'll have to use them wisely to not get behind on the curing.

For now, I have a function which adds afflictions to an affliction-que, one which removes from my "current list" and one which loops through my balances and sends out the appropriate cures The latter one is called everytime I get balance back from a curing method, and when I get afflicted with something.
To complicate it further (allthough I don't know what value it could have to you) there's also illusions mixed in this. Some classes are able to conjure illusions to mess upp your affliction-tracking. Hence why I use a que before adding the affliction to my "current list". Whenever I get a prompt, the system hasn't detected an illusion (by unlikely happenings/bad illusioners) and the affQue has items in it, I add them all to my "current list".

Now, how would you go about tracking and curing these afflictions? A plus is that the system is usable by people who lack the special curing methods.

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Akraa   (3 posts)  [Biography] bio
Date Reply #12 on Fri 13 May 2005 10:04 PM (UTC)
Message
hmm what if you added a third part to the herbcure thing,

curesHerbs =
{
{ name = "stupidity", cure = "orphine", active = "0" },
{ name = "paralysis", cure = "maidenhair", active = "0" },
{ name = "sleep", cure = "wildvine", active = "0" },
}

could you a) change the "active" in each set from another script or trigger (like when your paralysis trigger goes off, have it set curesHerbs[2] to { name = "paralysis", cure = "maidenhair", active = "1" } ?)
and b) go down the table in priorty then have it, when it finds a line with active = 1 to send that to the curing cue then stop its search until herb balance is regained? (ie only process the instance of active = "1" that is highest on the priority list, then exit out of the table)

if those two can be done, can anyone explain to me how to do it?
[Go to top] top

Posted by tobiassjosten   Sweden  (79 posts)  [Biography] bio
Date Reply #13 on Fri 13 May 2005 10:31 PM (UTC)
Message
Check out Nick's post above, it explains it all. Just add a break when it finds something to cure. And for the updating, don't know the syntax to do it in LUA, but I'm sure it's doable.

Simplicity is Divine | http://nogfx.org/
[Go to top] top

Posted by Akraa   (3 posts)  [Biography] bio
Date Reply #14 on Fri 13 May 2005 11:57 PM (UTC)
Message
I found a way to edit the cureherb table here http://www.lua.org/pil/13.4.2.html

if Im understanding it right, then I could trigger the paralysis line to:

rawset (curesHerb[2], active, 1)

which would set

{ name = "paralysis", cure = "maidenhair", active = "0" },

to

{ name = "paralysis", cure = "maidenhair", active = "1" },

that is, if im understanding it properly.


How would the syntax for adding a break to curesHerb = {} work?

so when I have:

curesHerbs =
{
{ name = "stupidity", cure = "orphine", active = "0" },
{ name = "paralysis", cure = "maidenhair", active = "1" },
{ name = "sleep", cure = "wildvine", active = "0" },
}

it would go through the table down to:

{ name = "stupidity", cure = "orphine", active = "0" },
{ name = "paralysis", cure = "maidenhair", active = "1" },

then immediately go to the curing attempt, rather than continuing down the table?
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


55,078 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]