This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Slyth's profile picture

[Lua] Finding What "x" Equals

Started by Slyth, 19 May 2012 - 07:08 PM
Slyth #1
Posted 19 May 2012 - 09:08 PM
Ok I was thinking yesterday and I thought can io.read() do boolean aka true false?
then i thought if I could make a program that when you type in
5 + x = 10
that it would read what you typed and then activate a loop that tried out "x" and then saw if it was true or false and if it was true printed

your answer is "whatever was true"

and if it was false resumed the loop.
So just wondering if that could happen. Just try it out and post it here if it will work.
Thanks it would teach me alot.
Luanub #2
Posted 19 May 2012 - 09:27 PM
Here you go play around with this.


local answer = false
local x = ""

while not answer do
term.clear()
term.setCursorPos(1,3)
print ("Solve x (5 + x = 10)")
x = tonumber(read())
if x + 5 == 10 then
   answer = true
else
   print("Incorrect try again")
   sleep(1)
end
end
print("Your answer "..x.." was correct")
Slyth #3
Posted 19 May 2012 - 09:33 PM
ok cool that gave me some great ideas. amazing how fast yall responded!
Slyth #4
Posted 19 May 2012 - 09:39 PM
just not quite what I was looking for, but do you think you could do one that you type in an equation and it finds x or is that not possible?
still that program was great!
MysticT #5
Posted 19 May 2012 - 11:41 PM
Well, it's possible, but not easy. Depending on the type of equations you want to solve it would take a lot of work to write that. The problem is more in reading the input and "understand" it, to then solve it. Just google for it, you'll see everyone says the same.
Slyth #6
Posted 19 May 2012 - 11:54 PM
alright, just wondering if it was possible, I was gonna try it but it sounds pretty complicated.
my_hat_stinks #7
Posted 20 May 2012 - 01:28 AM
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
MysticT #8
Posted 20 May 2012 - 02:52 AM

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
So bad there's no such tobool() function :P/>/>
my_hat_stinks #9
Posted 20 May 2012 - 01:40 PM
So bad there's no such tobool() function :P/>/>

Told you, it was 1 AM :D/>/>
Making a function like that's pretty simple

local function tobool( var )
  if type(var) == "boolean" then return var --Bool, return itself
  elseif type(var)=="string" then
	return (var~="false" and var~="") --string, return true unless it's empty or "false"
  elseif type(var)=="number" then
	return (var>0) --Number, return true if it's a positive number
  else return var end --Other, can't convert
end