Advertisement
guitarplayer616

AlgebraMagic

Dec 18th, 2016
253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.67 KB | None | 0 0
  1. function replace(string,pattern,replace)
  2.     for i = 1,#string do
  3.        
  4.         if string:sub(i,i) == pattern:sub(1,1) then
  5.            
  6.             word = ""
  7.             word = string:sub(i,i)
  8.             for n=1,#pattern do
  9.                 if string:sub(i+n,i+n) == pattern:sub(1+n,1+n) then
  10.                     word = word..string:sub(i+n,i+n)
  11.                 end
  12.             end
  13.             if #word==#pattern then
  14.                 local p1 = string:sub(1,i-1)
  15.                 local p2 = string:sub(i+#pattern)
  16.                 result = p1..p2
  17.                 --i,i+n
  18.             end
  19.         end
  20.     end
  21.     return result
  22. end
  23.  
  24.  
  25. known = {
  26.    
  27.     vx = 50,
  28.     v0x = 10,
  29.     ax = 10,
  30.     x0 = 0,
  31.     find = "x",
  32.     equation = "vx^2=v0x^2+2ax(x-x0)",
  33.     vars = {'vx','v0x','ax','x','x0'},
  34.    
  35. }
  36.  
  37.  
  38.  
  39. function replaceKnownVars(tVars,equation)
  40.     --"y=mx+b" --> "(50)=(10)x+(5)"
  41.     local sOutput = equation
  42.     for i,v in pairs(tVars) do
  43.         if tonumber(v) then
  44.             --replace known vars with values
  45.             sOutput = sOutput:gsub(i,"("..v..")")
  46.         end
  47.     end
  48.  
  49.     --[[
  50.     local simplifyAnswer = function(equation)
  51.         local left,right = equalSplit(equation)
  52.         loadstring("i="..left)()
  53.         equation = tostring(i).."="..right
  54.         return equation
  55.     end]]
  56.    
  57.    
  58.     --sOutput = simplifyAnswer(sOutput)
  59.    
  60.     return sOutput
  61. end
  62.  
  63. function addImplicitOperators(equation)
  64.     --"(50)=(10)(30)x+2(5)" --> "(50)=+(10)*(30)x+2*(5)"
  65.     local sOutput = equation
  66.    
  67.     -- adds + to first base
  68.     addPlus = function(sOutput)
  69.         local char1 = sOutput:sub(sOutput:find("=")+1,sOutput:find("=")+1)
  70.         if char1~="-" and char1~="+" then
  71.             local p1 = sOutput:sub(1,sOutput:find("="))
  72.             local p2 = sOutput:sub(sOutput:find("=")+1)
  73.        
  74.             sOutput = p1.."+"..p2
  75.         end
  76.         return sOutput
  77.     end
  78.    
  79.     sOutput = addPlus(sOutput)
  80.    
  81.     addAsterisks = function(right)
  82.     --input right side of equation
  83.     --output = input with * inbetween
  84.         for i = 1,#right do
  85.             if right:sub(i,i) == "(" then
  86.                 if right:sub(i-1,i-1) then
  87.                     if tonumber(right:sub(i-1,i-1)) or right:sub(i-1,i-1) == ")" then
  88.                         local p1 = right:sub(1,i-1)
  89.                         local p2 = right:sub(i)
  90.                         right = p1.."*"..p2
  91.                         addAsterisks(right)
  92.                     end
  93.                 end
  94.             --parenthesis = parenthesis + 1
  95.             --elseif right:sub(i,i) == ")" then
  96.             --parenthesis = parenthesis - 1
  97.             end
  98.         end
  99.         return right
  100.     end
  101.    
  102.     sOutput = addAsterisks(sOutput)
  103.    
  104.     return sOutput
  105. end
  106.  
  107. local function simplifyAnswer(equation)
  108.     --50^2=(10+20)x+(50*2) --> 2500=30x+100+1200
  109.    
  110.     local left,right = equalSplit(equation)
  111.     loadstring("l="..left)()
  112.    
  113.     right = right:gsub("%((%A.-)%)",
  114.         function(inbetween)
  115.             loadstring("r="..inbetween)()
  116.             return r
  117.         end
  118.     )
  119.     equation = tostring(l).."="..right
  120.     return equation
  121. end
  122.  
  123. local function equalSplit(equation)
  124.     --returns 2 halves of equation
  125.     local eq = equation:find("=")
  126.     local left = equation:sub(1,eq-1)
  127.     local right = equation:sub(eq+1,#equation)
  128.     return left,right
  129. end
  130.  
  131. local function find(equation,listOfChars)
  132.     local occurences = {}
  133.     local parenthesisIgnore = 0
  134.    
  135.     for i,v in pairs(listOfChars) do
  136.         for n = 1, #equation do
  137.             local check = equation:sub(n,n)
  138.             if check == "(" then
  139.                 parenthesisIgnore = parenthesisIgnore + 1
  140.             elseif check == ")" then
  141.                 parenthesisIgnore = parenthesisIgnore - 1
  142.             elseif check == v and parenthesisIgnore == 0 then
  143.                 table.insert(occurences,n)
  144.             end
  145.         end
  146.     end
  147.    
  148.     return occurences
  149.    
  150. end
  151.  
  152. local function splitBases(equation)
  153.     --right side of equation
  154.     equation = equation:sub(equation:find("=")+1,#equation)
  155.     --add + to bases
  156.     --if equation:sub(1,1) ~= "-" then
  157.         --equation = "+"..equation
  158.     --end
  159.  
  160.  
  161.     local occurences = find(equation,{"-","+"})
  162.     local bases = {}
  163.     --local parenthesis = find(equation,{"(",")"})
  164.    
  165.     table.sort(occurences)
  166.    
  167.    
  168.     for i = 1,(#occurences) do
  169.         if i == (#occurences) then
  170.             table.insert(bases,equation:sub(occurences[i]))
  171.         else
  172.             table.insert(bases,equation:sub(occurences[i],occurences[i+1]-1))
  173.         end
  174.     end
  175.    
  176.    
  177.     return occurences,bases
  178. end
  179.  
  180. function BaseAS(equation)
  181.     local sOutput = equation
  182.     local occurences,bases = splitBases(sOutput)
  183.     local left,right = equalSplit(sOutput)
  184.     local opposites = {}
  185.  
  186.     --sOutput = addPlus(sOutput)
  187.     --add/subtract to left
  188.    
  189.     for i,v in pairs(bases) do
  190.         if v:sub(1,1) == "-" then
  191.             opposites[i] = "+"..v:sub(2)
  192.         elseif v:sub(1,1) == "+" then
  193.             opposites[i] = "-"..v:sub(2)
  194.         else
  195.             opposites[i] = "-"..v
  196.         end
  197.     end
  198.        
  199.     for i,v in pairs(opposites) do
  200.         left,right = equalSplit(sOutput)
  201.         if not v:find("%a") then
  202.             loadstring("a="..left..v)()
  203.             left = a
  204.         end
  205.     end
  206.    
  207.         --delete from right
  208.     left,right = equalSplit(sOutput)
  209.    
  210.     for i,v in pairs(bases) do
  211.         if not v:find("%a") then
  212.             right = replace(right,v)
  213.         end
  214.     end
  215.  
  216.    
  217.     sOutput = left.."="..right
  218.    
  219.     return sOutput
  220.    
  221. end
  222.  
  223. function BaseMD(equation)
  224.     --bases p/e
  225.     local result = equation
  226.     local left,right = equalSplit(equation)
  227.     local parenthesis = 0
  228.     local bases = {}
  229.     local baseLoc = {}
  230.     local basealt = {}
  231.    
  232.     for i = 1,#right do
  233.         if right:sub(i,i) == "(" then
  234.             parenthesis = parenthesis + 1
  235.         elseif right:sub(i,i) == ")" then
  236.             parenthesis = parenthesis - 1
  237.         elseif right:sub(i,i) == "*" and parenthesis == 0 then
  238.             table.insert(baseLoc,i)
  239.         end
  240.     end
  241.    
  242.    
  243.  
  244.     table.insert(baseLoc,1)
  245.     table.sort(baseLoc)
  246.  
  247.    
  248.     for i =1,#baseLoc do
  249.         if i == (#baseLoc) then
  250.             table.insert(bases,right:sub(baseLoc[i]+1))
  251.         else
  252.             table.insert(bases,right:sub(baseLoc[i]+1,baseLoc[i+1]-1))
  253.         end
  254.     end
  255.    
  256.     local copy = equation
  257.    
  258.     local parenthesis = 0
  259.    
  260.     --multiply/divide to left
  261.     --local opposites = {}
  262.     for i,v in pairs(bases) do
  263.         --left = left/( v )
  264.         if not v:find("%a") then
  265.             v = v:gsub("(%+)","")
  266.             loadstring("lj="..left.."/("..v..")")()
  267.             left = lj
  268.         end
  269.     end
  270.  
  271.     for i,v in pairs(bases) do
  272.         if not v:find("%a") then
  273.             bases[i] = nil
  274.             local lk = replace(right,v)
  275.             right = lk
  276.         end
  277.     end
  278.  
  279. --old result
  280. --result = left.."="..right
  281.  
  282. --base reconstruction based result
  283. --[[turn tBases into a string in order of indexes]]
  284.     local sConstructor = ""
  285.     for i,v in pairs(bases) do
  286.         sConstructor = sConstructor..v
  287.     end
  288.  
  289.     sConstructor = addAsterisks(sConstructor)
  290.     result = left.."="..sConstructor
  291.  
  292.     return result
  293.    
  294. end
  295.  
  296. function unknownVarsAmount(known,equation)
  297.     local vars = known.vars
  298.     local unknown = {}
  299.     print(equation)
  300.    
  301.     for i,v in ipairs(vars) do
  302.         if equation:find(v) then
  303.             table.insert(unknown,v)
  304.         end
  305.     end
  306.    
  307.     return #unknown
  308. end
  309.  
  310. function pemdas(equation)
  311.     local left,right = equalSplit(equation) --take right side of equation
  312.     local sOutput = nil --points to function
  313.     local tOutput = {0}
  314.     --iterate through right
  315.     local parenthesis = 0
  316.     for i = 1,#right do
  317.         local char = right:sub(i,i)
  318.         local backchar = right:sub(i-1,i-1) or ""
  319.         --looking for outermost in parenthesis
  320.         if char == "(" then
  321.             parenthesis = parenthesis+1
  322.         elseif char == ")" then
  323.             parenthesis = parenthesis-1
  324.         elseif parenthesis==0 then
  325.             if (char == "+" or char == "-") and (backchar ~= "*" and backchar ~= "/" and backchar ~= "^" and i~=1) then
  326.                 --negative exponent fix
  327.                 sOutput = "BaseAS"
  328.                 table.insert(tOutput,3)
  329.                 --implicit + handled within that other function
  330.             elseif char == "*" or char == "/" then
  331.                 sOutput = "BaseMD"
  332.                 table.insert(tOutput,2)
  333.             elseif char == "^" then
  334.                 sOutput = "BaseEXP"
  335.                 table.insert(tOutput,1)
  336.             end
  337.         end
  338.         --looking for +,-,^,/,*
  339.         --looking for implicit +,*
  340.     end
  341.     --higher number takes precedence
  342.     table.sort(tOutput, function(a,b) return a>b end)
  343.     if tOutput[1] == 3 then
  344.         sOutput = "BaseAS"
  345.     elseif tOutput[1] == 2 then
  346.         sOutput = "BaseMD"
  347.     elseif tOutput[1] == 1 then
  348.         sOutput = "BaseEXP"
  349.     elseif tOutput[1] == 0 then
  350.         sOutput = nil
  351.     else
  352.         error("unexpected value in tOutput")
  353.     end
  354.     --print(table.concat(tOutput,", "))
  355.     --print(math.max(=(table.concat(tOutput,", ")))
  356.     --print(math.max(tOutput))
  357.  
  358.     if not sOutput then
  359.         breakParenthesis = function(right)
  360.             --input right side of equation
  361.             local finished = false
  362.             local output = ""
  363.             if right:sub(1,1) == "(" and right:sub(#right,#right) == ")" then
  364.                 output = right:sub(2,#right-1)
  365.             else
  366.                 --error("no outer parenthesis detected",2)
  367.                 --lets assume this means its correct ie no operators or parentheses
  368.                 output = right
  369.                 finished = true
  370.             end
  371.             return output,finished
  372.         end
  373.        
  374.         local finishCheck = false
  375.         right,finishCheck = breakParenthesis(right)
  376.        
  377.         if finishCheck then
  378.             sOutput = "finished"
  379.         else
  380.             sOutput = "nextLayer"
  381.         end
  382.        
  383.     end
  384.    
  385.     equation = left.."="..right
  386.     return sOutput,equation
  387. end
  388.  
  389. function AlgebraStep(prevRes)
  390.     --input equation with 1 unknown
  391.     --output equation with 1 step worked out
  392.     local nextStep,nextLayer = pemdas(prevRes)
  393.     local sEquation = nil
  394.    
  395.     if nextStep == "BaseAS" then
  396.         sEquation = BaseAS(prevRes)
  397.     elseif nextStep == "BaseMD" then
  398.         sEquation = BaseMD(prevRes)
  399.     elseif nextStep == "nextLayer" then
  400.         sEquation = nextLayer
  401.     elseif nextStep == "finished" then
  402.         return "FINISHED"
  403.     end
  404.    
  405.     if sEquation then
  406.         return sEquation
  407.     else
  408.         error("nextStep = "..nextStep,2)
  409.     end
  410. end
  411.  
  412. function repeatAlgebra(equation,nStep)
  413.     local equation2 = equation
  414.     local neq = nStep or 1
  415.    
  416.     while true do
  417.         equation2 = AlgebraStep(equation2)
  418.         if equation2 ~= "FINISHED" then
  419.             print(equation2," : step"..tostring(neq))
  420.             neq = neq+1
  421.         else
  422.             neq = neq - 1
  423.             print("Finished with "..neq.." steps")
  424.             break
  425.         end
  426.     end
  427. end
  428.  
  429.  
  430. function solve(known,equation)
  431.     local sOutput = equation
  432.     local neq = 1
  433.    
  434.    
  435.     sOutput = replaceKnownVars(known,equation)
  436.    
  437.     if unknownVarsAmount(known,sOutput) > 1 then
  438.         error("too many unknown vars")
  439.     end
  440.        
  441.    
  442.  
  443.        
  444.     while true do
  445.         sOutput = addImplicitOperators(sOutput)
  446.         print("impOPs = "..sOutput)
  447.         sOutput = simplifyAnswer(sOutput)
  448.         print("simpFy = "..sOutput)
  449.         sOutput = AlgebraStep(sOutput)
  450.        
  451.         if sOutput ~= "FINISHED" then
  452.             print(sOutput," : step"..tostring(neq))
  453.             neq = neq+1
  454.         else
  455.             neq = neq - 1
  456.             print("Finished with "..neq.." steps")
  457.             break
  458.         end
  459.     end
  460.    
  461.    
  462. end
  463.  
  464. --print(addImplicitOperators("(50)=2(23)(43)+2"))
  465. --print(simplifyAnswer("(50)^2=+(25*36)+(743-123)/(x/72)"))
  466.  
  467.  
  468.  
  469.  
  470. shell.run("clr")
  471.  
  472. function testRepeatAlgebra()
  473.     print(known.equation)
  474.     local step1 = replaceKnownVars(known,known.equation)
  475.     print(step1.." : replaceKnownVars")
  476.     local step2 = addImplicitOperators(step1)
  477.     print(step2.." : addImplicitOps")
  478.     local step3 = simplifyAnswer(step2)
  479.     print(step3.." : simplifyAnswer")
  480.  
  481.     repeatAlgebra(step3)
  482. --solve(known,known.equation)
  483. end
  484.  
  485. testRepeatAlgebra()
  486. --solve(known,known.equation)
  487.  
  488. --solve(known,"125=(x-0)")
  489.  
  490.  
  491.  
  492. --[[
  493. print(step1.." : replaceKnownVars")
  494. local step2 = addImplicitOperators(step1)
  495. print(step2.." : addImplicitOps")
  496. local step3 = simplifyAnswer(step2)
  497. print(step3.." : simplifyAnswer")
  498.  
  499. local equation2 = step3
  500. local neq = 4
  501.  
  502. repeatAlgebra(equation2,5,neq)
  503. ]]
  504.  
  505.  
  506.  
  507. --[[print(pemdas(step3))
  508. equation2 = AlgebraStep(equation2)
  509. print(equation2," : step"..tostring(neq))
  510. neq = neq+1
  511.  
  512. equation2 = AlgebraStep(equation2)
  513. print(equation2," : step"..tostring(neq))
  514. neq = neq+1
  515.  
  516. equation2 = AlgebraStep(equation2)
  517. print(equation2," : step"..tostring(neq))
  518. neq = neq+1
  519.  
  520. equation2 = AlgebraStep(equation2)
  521. print(equation2," : step"..tostring(neq))
  522. neq = neq+1
  523.  
  524. equation2 = AlgebraStep(equation2)
  525. print(equation2," : step"..tostring(neq))
  526. neq = neq+1
  527. ]]
  528.  
  529.  
  530. --local step5 = BaseMD(step4)
  531. --print(step5.." : BaseMD")
  532.  
  533.  
  534. --print("result="..nextStep.."(\""..prevRes.."\")")
  535.  
  536. --loadstring("result="..nextStep.."(\""..prevRes.."\")")()
  537. --loadstring("result=BaseAS(step3)")()
  538. --print(result)
  539.  
  540.  
  541. --[[
  542. print(result)
  543. local step4 = BaseAS(step3)
  544. print(step4.." : BaseAS")
  545. --print(pemdas(step4))
  546.  
  547. local t,step6 = pemdas(step5)
  548. print(step6.." : "..t)
  549. local step7 = BaseAS(step6)
  550. print(step7.." : BaseAS")
  551. result=BaseAS(step3)
  552. ]]--
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement