8
\$\begingroup\$

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("")
chosen = io.read()
if chosen == 'Health' then
    print("Input The Damage")
    Da = io.read()
    print("Input The Size")
    Sz = io.read()
    print("Input The Speed")
    Sp = io.read()
    local m = 70 * ((Da * Sz) / Sp)
    print(m)
elseif chosen == 'Size' then
    print("Input the Health")
    h = io.read()
    print("Input the Damage")
    Da = io.read()
    print("Input the Speed")
    Sp = io.read()
    local n = (h*Sp) / (70*Da)
    print(n)
elseif chosen == 'Speed' then
    print("Input the Health")
    h = io.read()
    print("Input the Damage")
    Da = io.read()
    print("Input The Size")
    Sz = io.read()
    local o = (70*Da*Sz) / h
    print(o)
elseif chosen == 'Average Damage' then
    print("Input the Health")
    h = io.read()
    print("Input The Size")
    Sz = io.read()
    print("Input The Speed")
    Sp = io.read()
    local p = (h * Sp) / (70 * Sz)
    print(p)
end
\$\endgroup\$
  • 4
    \$\begingroup\$ 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) \$\endgroup\$ – amon Mar 16 '14 at 20:21
  • \$\begingroup\$ @amon Thanks for your concern! I asked him before I posted and he was all right with it. \$\endgroup\$ – KnightOfNi Mar 16 '14 at 20:22
8
\$\begingroup\$

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("")
chosen = io.read()
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

function read3values(text1,text2,text3)
    local value1 = readValue(text1)
    local value2 = readValue(text1)
    local value3 = readValue(text1)
    return value1,value2,value3
end


function readValue(text)
    print(text)
    return io.read()
end

You may also want to extract the repeating string constants.

\$\endgroup\$
  • \$\begingroup\$ 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. \$\endgroup\$ – MrSmith42 Mar 16 '14 at 21:35
  • \$\begingroup\$ Shhhh... Just pretend :) \$\endgroup\$ – KnightOfNi Mar 16 '14 at 21:41
  • \$\begingroup\$ @KnightOfNi: I think to write an answer I do not have to know all about the language. Just the parts I want to apply. \$\endgroup\$ – MrSmith42 Mar 16 '14 at 21:44
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – KnightOfNi Mar 16 '14 at 21:53
7
\$\begingroup\$

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 chosen = io.read()
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)
    argtab[i] = io.read()
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 chosen = io.read()
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)
        argtab[name] = io.read()
    end
end
print(fun(argtab))

But that depends on the set of choices always being one more than the arguments that the calculation functions need which may or may not be a valid assumption in any broader case.

\$\endgroup\$
  • \$\begingroup\$ I think I understand this program pretty well, (although I never would have come up with it) but why do you have the double brackets for your print function? And why no quotes? \$\endgroup\$ – KnightOfNi Apr 18 '14 at 14:34
  • \$\begingroup\$ [[...]] 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.) \$\endgroup\$ – Etan Reisner Apr 18 '14 at 18:37
  • \$\begingroup\$ OK, thanks. This was a very innovative approach. \$\endgroup\$ – KnightOfNi Apr 18 '14 at 23:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.