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

Gammon Forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Trying to convert a C program into a lua script
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

Trying to convert a C program into a lua script

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


Posted by Boxknife   (19 posts)  [Biography] bio
Date Sun 05 Apr 2009 12:45 AM (UTC)

Amended on Sun 05 Apr 2009 05:24 AM (UTC) by Boxknife

Message
I wrote a program in C to generate all the possible combinations of a list of ingredients. I'm trying to convert it to Lua, but with little success.

Here's what it does:

Enter ingredients:> kalan kalan sack sack

craft kalan 
craft kalan kalan 
craft sack 
craft kalan sack 
craft kalan kalan sack 
craft sack sack 
craft kalan sack sack 
craft kalan kalan sack sack 


Here's the C source code:
http://pastesite.com/6195
And here's what I'm trying to do in Lua:
http://pastesite.com/6194

It keeps giving me this error when I try to run it:
[string "Alias: "]:40: attempt to concatenate field '?' (a nil value)

I have no idea what that means.

[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Sun 05 Apr 2009 06:14 AM (UTC)
Message
Your Lua code was:


function ColourNote(a, b , c)

end
ColourNote("red", "black", "%1")
buffer = "craft"
words = {" "}

n=0

local w
wordcount=0

  for w in string.gmatch("%1", "%a+") do
    wordcount=wordcount+1
    words[wordcount]=w

  end
  
s=0

  for i=1,wordcount,1 do
    s=bit.bor(s,1)
    s=bit.shl(s,1)
    ColourNote("red", "black", words[i])
  end

s=s+1
copys=s

x=0
hasword=0
wordsums={"0"}
wordvals={"0"}

  for i=1,copys+1,1 do
    x=i
    j=1
      while x do
        if bit.band(x,1) then
          hasword=1
          
          buffer=buffer .. string.lower(words[j])
                                 
          buffer=buffer .. " "
          j=j+1
        end
      end
      if hasword then
                    
      ColourNote("red", "black", buffer)
      end
    hasword=0

  end



I can't help thinking there is an easier way. :)

After a bit of thought, I believe a recursive function is the way to go.

My idea was, to initially show all ingredients. Then, omit one, and show the remaining ones (so in your case, there are 4 lines with only 3 ingredients). Now for each of the 3 ingredients, you recurse, so that you now omit one of the 3, showing a line of 2 ingredients, and so on, till you are down to one.

To stop duplicates a simple table of "done" stops you repeating things (eg. the last single ingredient would keep appearing often).

My example code is:


ingredients = { "flour", "eggs", "sugar", "salt" }

require "copytable"  

done = {}

function permute_ingredients (t)

    local result = table.concat (t, ", ")
    
    if not  done [result] then
      print (result)
      done [result] = true
    end -- if not shown this one yet

  -- if more than 1 item, recurse
  if #t > 1 then
 
    for i = 1, #t do
      local t2 = copytable.shallow (t)
      table.remove (t2, i)  -- get rid of one of them
      permute_ingredients (t2)
    end -- for
  
  end -- if 

end -- function permute_ingredients

permute_ingredients (ingredients)


Running this gives:


flour, eggs, sugar, salt
eggs, sugar, salt
sugar, salt
salt
sugar
eggs, salt
eggs
eggs, sugar
flour, sugar, salt
flour, salt
flour
flour, sugar
flour, eggs, salt
flour, eggs
flour, eggs, sugar


This is 15 lines, which sounds about right for 4 ingredients.

If I add another ingredient (yeast) I get 31 lines, which also sounds right (2^5 - 1):


flour, eggs, sugar, salt, yeast
eggs, sugar, salt, yeast
sugar, salt, yeast
salt, yeast
yeast
salt
sugar, yeast
sugar
sugar, salt
eggs, salt, yeast
eggs, yeast
eggs
eggs, salt
eggs, sugar, yeast
eggs, sugar
eggs, sugar, salt
flour, sugar, salt, yeast
flour, salt, yeast
flour, yeast
flour
flour, salt
flour, sugar, yeast
flour, sugar
flour, sugar, salt
flour, eggs, salt, yeast
flour, eggs, yeast
flour, eggs
flour, eggs, salt
flour, eggs, sugar, yeast
flour, eggs, sugar
flour, eggs, sugar, salt


- Nick Gammon

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

Posted by Boxknife   (19 posts)  [Biography] bio
Date Reply #2 on Sun 05 Apr 2009 06:26 AM (UTC)
Message
Brilliant!
[Go to top] top

Posted by Boxknife   (19 posts)  [Biography] bio
Date Reply #3 on Sun 05 Apr 2009 06:51 PM (UTC)

Amended on Sun 05 Apr 2009 06:52 PM (UTC) by Boxknife

Message
For those of you interested, here is a crafting script that leverages Nick's recursive algorithm.

Usage: tcraft item1 item2 item3 ...
What it does: sends all possible "craft <combination>" combinations to the MUD.


<aliases>
  <alias
   match="tcraft (.*)"
   enabled="y"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

require "copytable"  

done = {}
--Recursive algorithm courtesy of Nick Gammon
function permute_ingredients (t)

    local result = table.concat (t, " ")
    
    if not  done [result] then
      print ("craft " .. result)
      SendImmediate("craft " .. result)
      done [result] = true
    end -- if not shown this one yet

  -- if more than 1 item, recurse
  if #t &gt; 1 then
 
    for i = 1, #t do
      local t2 = copytable.shallow (t)
      table.remove (t2, i)  -- get rid of one of them
      permute_ingredients (t2)
    end -- for
  
  end -- if 

end -- function permute_ingredients

--permute_ingredients (ingredients)
ingredients = { }
local w = ""
wordcount=1
 for w in string.gmatch("%1", "%a+") do
    ingredients[wordcount]=w
    wordcount=wordcount+1

  end

permute_ingredients (ingredients)

</send>
  </alias>
</aliases>
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #4 on Sun 05 Apr 2009 08:52 PM (UTC)

Amended on Mon 06 Apr 2009 08:27 AM (UTC) by Nick Gammon

Message
That looks good!

By the way, you don't need to set w to an empty string outside the loop (it is a different w anyway). Also table.insert inserts things into a table, so that saves counting. Like this:



local ingredients = { }

for w in string.gmatch("%1", "%a+") do
  table.insert (ingredients, w)
end

permute_ingredients (ingredients)



- Nick Gammon

www.gammon.com.au, www.mushclient.com
[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.


3,274 views.

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 FutureQuest]