2
$\begingroup$

I am working on creating a function that takes in any physics equation as a string and converts it to an equation that I will then paste into an interactive interface as asked here: How to make an interactive calculator for any mathematical relation?. I am implementing the first answer as a function that accepts any physics equation as a string and does two things before replacing the example of a^2+b^2==c^2.

First I want to replace any instance of "=" with "==" except for an instance of "==". The goal of this is to make a user-friendly function if the user enters an equation with incorrect programming syntax. I will then convert it to an expression.

Second, after it has been converted to an expression I will extract the symbols from the equation using this code, which I got from How to find all symbols in an expression and perform an operation on them?.

Symbols[x_String] := 
 DeleteDuplicates@Cases[ToExpression[x], _Symbol, Infinity]

The function for the first program is as follows:

StringReplace["\!\(\*SuperscriptBox[\(a\), \
\(2\)]\)+\!\(\*SuperscriptBox[\(b\), \
\(2\)]\)==\!\(\*SuperscriptBox[\(c\), \(2\)]\)", 
 Except[{"=="}, "="] -> "=="]

I am trying to base my code off this example

StringReplace["the cat in the hat", 
 Except[Characters["aeiou"], "c"] -> ""]

Unfortunately, this causes an error: enter image description here I am not sure what I am doing wrong here.

EDIT: I have my attempt here: https://www.wolframcloud.com/obj/burbery1/Published/Interactive%20Solver%20Function.nb In the process I came across two more unexpected hurdles: if the variable the user is solving for was already defined in a previous call of Interactive Solver or another piece of program that already executed, the symbol is regarded as a numerical value and not a variable.

The second problem is that the InteractiveSolver function returns a list of Null values when I run it for some reason.

I tried some code provided as an answer to this question and encountered the following error: enter image description here

$\endgroup$
6
  • 1
    $\begingroup$ Except is not accepted as a valid string pattern. As a way around, you could first replace all "==" by "=" and then replace all "=" by "==". $\endgroup$ Nov 6 '21 at 17:05
  • $\begingroup$ The function Symbols will return symbolic numeric constants as well as variables, e.g., look at the result of Symbols["Pi*x + E"]. Either modify the definition to Symbols[x_String] := DeleteDuplicates@Cases[ToExpression[x], _Symbol?(!NumericQ[#]&), Infinity] or use Symbols[x_String] := Variables[Level[x, {-1}]] $\endgroup$
    – Bob Hanlon
    Nov 6 '21 at 17:13
  • $\begingroup$ I am wondering if I should attach code in the form of a cloud notebook link or paste it directly in Stack Exchange or both. I have a little more than a page of code if you include the code in the question. $\endgroup$ Nov 6 '21 at 17:18
  • $\begingroup$ Interpreter[] might be fast enough for you: parse = Interpreter["MathFormula"]; parse["a=b^2"]. Parsing takes a little less than a second, so it's not fast. $\endgroup$
    – Michael E2
    Nov 7 '21 at 16:27
  • $\begingroup$ I don't quite understand how the Interpreter capability of Mathematica can be used to turn any string with only one equations sign into an expression with an equality checking expression (==) instead of assignment (=). Can you provide an example or explain a little bit more how the Interpreter can help me accomplish my goal? $\endgroup$ Nov 8 '21 at 1:17
1
$\begingroup$

FWIW, my take on the big problem. I'm not particularly interested in parsing strings, so I can delete if this is unhelpful.

(*"
 *  Calculator
"*)
CellPrint@
 ExpressionCell[
  Manipulate[
   Column[{
     (* displays some data for inspection *)
     Dynamic@{var, formula},
     Dynamic@Quiet[
       (* TBD:check input/output of Solve *)
       With[{sol = Solve[ReleaseHold@formula, var]},
        With[{sol0 = 
           sol /. Thread[freevariables -> value /@ freevariables]},
         value[var] = var /. Last[sol0];(* last sol *)
         Grid@Transpose@{sol, sol0} /. Rule -> Equal
         ]],
       {Power::infy}],
     (* parameter inputs *)
     Grid@Transpose@{
        freevariables,
        InputField[Dynamic@value@#] & /@ freevariables}
     }],
   
   {{formula, formula}, (* user input = held expression *)
    InputField[Dynamic[formula,
       ({formula, variables, var} = parseFormula[#];
         Clear[value];
         (value[#] = 1) & /@ variables;
         freevariables = DeleteCases[variables, var];
         ) &],
      Hold@Expression] &},
   {{var, var}, Dynamic@variables, SetterBar, TrackingFunction -> (
      (var = #;
        freevariables = DeleteCases[variables, var]) &)},
   {{variables, variables}, None},
   {{freevariables, freevariables}, None},
   {{parseFormula, parseFormula}, None},
   {{value, value}, None},(* stores values of parameters *)
   
   Initialization :> (
     (* utility (parses held expression) *)
     parseFormula // ClearAll;
     parseFormula[f_] := Module[{myformula, myvars, myvar},
       myformula = 
        f /. {Set | SetDelayed | Rule | RuleDelayed -> Equal,
          Null -> $Failed}; (* TBD: Handle user error *)
       myvars = Reduce`FreeVariables[ReleaseHold@myformula];
       myvar = Replace[{myformula, myvars},
         {{Hold[v_ == _] /; MemberQ[myvars, v], _} :> v,
          {_, {a_, ___}} :> a,
          {_, v_} :> v (* TBD: Handle user error *)
          }];
       myformula = Replace[myformula,
         {eq : Hold[_Equal] :> eq,
          Hold[x_] /; Internal`WouldBeNumericQ[x, Evaluate@myvars] :>
           (myvar = $ans; 
            PrependTo[myvars, $ans];
            Hold[$ans == x]),
          form_ :> (myvars = myvar = $Failed; form)
          }]; (* TBD: Handle user error *)
       {myformula, myvars, myvar}
       ];
     (* init *)
     {formula, variables, var} = 
      parseFormula[ToExpression["a^2+b^2==c^2", StandardForm, Hold]];
     freevariables = DeleteCases[variables, var];
     (value[#] = 1) & /@ variables;
     )
   ],
  "Output",
  CellContext -> Cell]
$\endgroup$
7
  • $\begingroup$ If I try to change the equation or relation inside the box I get an error that I would like to display in a screenshot but don't know how to. $\endgroup$ Nov 8 '21 at 1:19
  • $\begingroup$ @PeterBurbery What did you type? When I type "a^2 == b^2 - c^2", I get no error. $\endgroup$
    – Michael E2
    Nov 8 '21 at 2:01
  • $\begingroup$ When I type "a^2=b^2-c^2" I get an error because it is an assignment expression and I would like to make it convert any assignment expressions into equality testing expressions. $\endgroup$ Nov 8 '21 at 15:22
  • $\begingroup$ @PeterBurbery I get no error if I enter "a^2=b^2-c^2". The code converts = (Set) to == (Equal) when the formula is parsed. It also converts A -> b h to A == b h. Not that a student would think of that, but it's a sort of like an assignment (a substitution Rule technically), so I threw that in. Unfortunately (?) E = m c^2 gets converted to the base of the natural logarithm and E=mc^2 is in terms the single variable mc squared. $\endgroup$
    – Michael E2
    Nov 8 '21 at 16:34
  • $\begingroup$ I was pressing Shift+Enter every time instead of Enter. It is working now. $\endgroup$ Nov 8 '21 at 16:42

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.