but it sounds pretty complicated.
Indeed it is
I started working on something for you, but what with it being 1 AM, I can't really concentrate
Here's what I have so far
Spoiler
--[[
Created by my_hat_stinks
Licensed under a Creative Commons Attribution 3.0 Unported License
Date of creation: 20 May 2012
--]]
--[[
****Utility functions
--]]
local function table.HasValue( tab, var )
if type(tab) ~= "table" then error("Table expected, received "..type(tab).."!n") end --Bad input
for _,v in pairs(tab) do
if v==var then return true end --It's there
end
return false --It's not there
end
--[[
****Local functions
--]]
local operators = {"+","-","*","/","="} --TODO: Powers support, Brackets support
local function InputToTable( In )
local tab = {} --Table of values
local pos = 0 --Position in table
for i=1,string.len(In) do
pos=pos+1
local char = string.sub(In, i, 1) --Character by character re-formatting
if string.find(char, "[0-9]") then --Number
if tab[pos-1] and type( tab[pos-1] ) == "string" then
tab[pos-1] = (tab[pos-1]*10) + tonumber( char ) --Shift everything left one and insert this number
pos = pos-1 --No new entry
else --We're the first digit of this number
tab[pos] = tonumber( char ) --Insert into a new entry
end
elseif string.lower(char)=="x" then --What we're searching for
tab[pos] = "X"
--Mathematical operators
elseif table.HasValue(operators, char) then
tab[pos] = char
else --Not recognised
if char~=" " then error("Bad input or unsupported character!n") end --If not space, error
pos = pos-1 --Character wasn't registered
end
end
return tab
end
local function CheckX( var )
if type(var) == "table" then return table.HasValue(var, "X") else return var=="X" end
end
local function Simplify( tab )
--There's a good chance modifying the table mid-loop will bork it, and from past experience "break" exists all loops
--We'll use a sub-function system
local function DoMath( func )
local result
--Highest priority, multiply
for k,v in ipairs(func) do
if v=="*" then
local bef = func[k-1]
local aft = func[k+1]
if bef==0 or aft==0 then
func[k-1] = 0
table.remove(func, k)
table.remove(func, k) --Twice to remove the following number, too
return func, false
end
if CheckX(bef) or CheckX(aft) then
end
end
end
return func, true
end
local done = false
while not done do
tab, done = DoMath( tab )
end
return tab
end
local function ArrangeEquation( tab )
--Verify and simplify the equation
--[[***************************]]--
local FirstEqual = 0
local SecondEqual = nil
for k,v in ipairs(tab) do
if v=="=" then
if FirstEqual==0 then FirstEqual = k
else
SecondEqual = k
break
end
end
end
if SecondEqual then --Complicates things, erase it (result should be the same)
for i=#tab,SecondEqual,(-1) do --Everything from the end to the second equals...
tab[i]=nil --Erase!
end
end
--[[***************************]]--
--Find the X
--[[___________________________]]--
local XPos = {}
for k,v in pairs(tab) do
if v=="X" then
table.insert(XPos, k)
end
end
if XPos == {} then error("Nothing to find!n") end
--[[___________________________]]--
Simplify( tab ) --Do maths
local AfterEqual = nil
for i=1,#XPos do
if AfterEqual~=nil and AfterEqual~=(XPos>FirstEqual) then
tab = MoveX(tab, XPos, FirstEqual)
break
end
AfterEqual = XPos[i]
end
end
--[[
****Base function
--]]
function FindX( In )
local tab = InputToTable(In)
tab = ArrangeEquation( tab )
end
---[[ Testing (remove the first - on this line to disable)
local In = "1+x*2=20"
local x = FindX( In )
write("x is " ..tostring(x).."n")
--]]
Untested, probably errors
Obviously incomplete, what you're looking to edit is around lines 86 to add support for all the other mathematical functions, then lines 139-146 you'll want to edit it so that it moves all the X's over to one side of the equals sign, then run the Simplify function on it again, then move everything that's not X away from the X side, run Simplify again, then a simple division should get the answer
Was planning to put multiplications by X into a table {"X", <Amount to multiply by> [, Power of X(When power support is added to the script)] }
Feel free to mess around with that till you get it how you want, but since it's incomplete I've not went through removing redundancies and optimising :P/>/>
As for the boolean thing, I think you're looking for something like this:
local IsBool, bool = false --bool doesn't need a value here
while not IsBool do --Loop if invalid
bool = tobool( read() ) --Convert to bool
IsBool = type(bool)=="boolean" --Validate
end
--Do stuff
Obviously adding prompts where required
Would also be possible with a "while true" and a break, but that's a bad practice