Lua Formula Code

A friend of mine dabbles in lua, and he recently sent me a code which applies an equation we were discussing. I personally am very mediocre with lua, but my Python senses are tingling - I feel as though this code could almost certainly be shortened. Any thoughts?

print("Choose what you want to find:")
print("Health")
print("Size")
print("Speed")
print("Average Damage")
print("")
if chosen == 'Health' then
print("Input The Damage")
print("Input The Size")
print("Input The Speed")
local m = 70 * ((Da * Sz) / Sp)
print(m)
elseif chosen == 'Size' then
print("Input the Health")
print("Input the Damage")
print("Input the Speed")
local n = (h*Sp) / (70*Da)
print(n)
elseif chosen == 'Speed' then
print("Input the Health")
print("Input the Damage")
print("Input The Size")
local o = (70*Da*Sz) / h
print(o)
elseif chosen == 'Average Damage' then
print("Input the Health")
print("Input The Size")
print("Input The Speed")
local p = (h * Sp) / (70 * Sz)
print(p)
end

• We can only review code that you have written yourself. Has your friend given you permission to post this code here? (There is a rather banal reason for this restriction: all user content on the Stack Exchange networked is licensed under CC-BY-SA, and nobody but the copyright holder can issue a license) – amon Mar 16 '14 at 20:21
• @amon Thanks for your concern! I asked him before I posted and he was all right with it. – KnightOfNi Mar 16 '14 at 20:22

I have never written any Lua code before, but a short view in a tutorial at http://www.lua.org/ let me come up with this:

Extract a method which returns 3 values:

print("Choose what you want to find:")
print("Health")
print("Size")
print("Speed")
print("Average Damage")
print("")
if chosen == 'Health' then
Da,Sz,Sp = read3values("Input The Damage","Input The Size","Input The Speed")
print((70 * ((Da * Sz) / Sp)))
elseif chosen == 'Size' then
h,Da,Sp= read3values("Input the Health","Input the Damage","Input the Speed")
print(((h*Sp) / (70*Da)))
elseif chosen == 'Speed' then
h,Da,Sz = read3values("Input the Health","Input the Damage","Input The Size")
print(((70*Da*Sz) / h))
elseif chosen == 'Average Damage' then
h,Sz,Sp = read3values"Input the Health","Input The Size","Input The Speed")
print(((h * Sp) / (70 * Sz)))
end

return value1,value2,value3
end

print(text)
end


You may also want to extract the repeating string constants.

• I was not learning the hole language, only the syntax of functions. And I was pleased to see the possibility to return more than one value. I would love to have this directly build in the language in java. – MrSmith42 Mar 16 '14 at 21:35
• Shhhh... Just pretend :) – KnightOfNi Mar 16 '14 at 21:41
• @KnightOfNi: I think to write an answer I do not have to know all about the language. Just the parts I want to apply. – MrSmith42 Mar 16 '14 at 21:44
• I was joking/being friendly... the clue was in the emoticon. I agree that you don't need to be an expert to answer the question. – KnightOfNi Mar 16 '14 at 21:53

Possibly not exactly how I'd write it if I was writing this myself but given the example code and the lack of any other context it works and is reasonably clean.

local choicetab = {
Health = {"Damage", "Size", "Speed", cb = function(Da, Sz, Sp) return 70 * ((Da * Sz) / Sp) end},
Size = {"Health", "Damage", "Speed", cb = function(h, Da, Sp) return (h * Sp) / (70 * Da) end},
Speed = {"Health", "Damage", "Size", cb = function(h, Da, Sz) return (70 * Da * Sz) / h end},
["Average Damage"] = {"Health", "Size", "Speed", cb = function(h, Sz, Sp) return (h * Sp) / (70 * Sz) end},
}

print([[Choose what you want to find:
Health
Size
Speed
Average Damage
]])
local tab = choicetab[chosen]
if not tab then
error("Not a valid choice")
end

local argtab = {}
for i, v in ipairs(tab) do
print("Input The "..v)
end
print(tab.cb(unpack(argtab)))


This might be better for the choice printing loop if you aren't concerned about the order possibly changing (it should be stable but isn't guaranteed to be) since it shows you all the valid choices (even if you remove one or add more).

print("Choose what you want to find:")
for name in pairs(choicetab) do
print(name)
end


Additionally, if you didn't care about the order of the information prompted for either you could do away with storing that information in the sub-tables of choicetab and do something like this instead:

local choicetab = {
Health             = function(args) return 70 * ((args["Average Damage"] * args.Size) / args.Speed)   end,
Size               = function(args) return (args.Health * args.Speed) / (70 * args["Average Damage"]) end,
Speed              = function(args) return (70 * args["Average Damage"] * args.Size) / args.Health    end,
["Average Damage"] = function(args) return (args.Health * args.Speed) / (70 * args.Size)              end,
}

print("Choose what you want to find:")
for name in pairs(choicetab) do
print(name)
end
print()
local fun = choicetab[chosen]
if not fun then
error("Not a valid choice")
end

local argtab = {}
for name, v in pairs(choicetab) do
if name ~= chosen then
print("Input The "..name)

• [[...]] is a lua long string. See the mutliline quotes section of this page. But basically it just allowed for the literal newlines to be in the string instead of needing to use \n or multiple calls to print. (Also described in the manual.) – Etan Reisner Apr 18 '14 at 18:37