solve.fsp - Frink Server Pages highlighter
[Try solve.fsp]
<!DOCTYPE html>
<HTML LANG="en">
<HEAD>
<TITLE>Frink Solver</TITLE>
<META NAME="viewport" CONTENT="width=device-width, initial-scale=1.0">
<META HTTP-EQUIV="Default-Style" CONTENT="Spaceship">
<LINK REL="StyleSheet" HREF="/frinkdocs/spaceship.css"
TYPE="text/css" TITLE="Spaceship">
<LINK REL="Alternate StyleSheet" HREF="/frinkdocs/apeairy.css"
TYPE="text/css" TITLE="APE Airy">
<LINK REL="Alternate StyleSheet" HREF="/frinkdocs/style.css" TYPE="text/css"
TITLE="APE Classic">
<LINK REL="Alternate StyleSheet" HREF="/frinkdocs/style2.css" TYPE="text/css"
TITLE="Compact">
<LINK REL="icon" HREF="/images/futureboyicon.png" TYPE="image/png">
<LINK REL="canonical" HREF="https://frinklang.org/fsp/solve.fsp">
</HEAD>
<%
use ../
allTransforms.frink
use ../
HTMLUtils.frink
use ../
MathML.frink
symbolicMode[true]
if ! isVariableDefined["equation"] && ! isVariableDefined["eq"]
ev = "on"
if ! isVariableDefined["equation"]
if isVariableDefined["eq"]
equation = eq // Moving to use variable "eq" for shorter URLs.
/* if (!equation)
{
equation = "h = h0 + Integrate[v0, t] + Integrate[-gravity, t, 2]"
solveFor = "h"
} */
eqStr = HTMLEncodeQuoted[equation]
solveFor = solveFor ? trim[solveFor] : ""
solveStr = HTMLEncodeQuoted[solveFor]
wchecked = w ? "CHECKED" : ""
f = f ? f : ""
fchecked = (f=="f" or f=="on") ? "CHECKED" : ""
mchecked = f=="m" ? "CHECKED" : ""
nchecked = f=="" ? "CHECKED" : ""
evchecked = ev ? "CHECKED" : ""
resultAsQuoted = resultAs ? HTMLEncodeQuoted[resultAs] : ""
extra = """ class="big" """
%>
<BODY>
<H1>Frink Solver</H1>
<FORM ACTION="solve.fsp" METHOD="GET">
<DIV CLASS="back">
<TABLE BORDER="0" SUMMARY="Equation input">
<TR><TD CLASS="noborder"><LABEL FOR="eq">Equation:</LABEL>
<INPUT TYPE="text" NAME="eq"
STYLE="width: 100%; box-sizing: border-box" SIZE="40" ID="eq"
VALUE="$eqStr
" autocapitalize="none" autocorrect="none"
oninput="document.getElementById('resultAs').value=''">
<TR><TD CLASS="noborder"><LABEL FOR="solveFor">Solve for: </LABEL><INPUT TYPE="text" SIZE="15" autocapitalize="none" autocorrect="none" NAME="solveFor"
ID="solveFor" VALUE="$solveStr
" oninput="document.getElementById('resultAs').value=''">
<TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="CHECKBOX" NAME="w" ID="w" $wchecked
onChange="this.form.submit();"><LABEL FOR="w">Show work</LABEL>
<TR><TD CLASS="noborder">Show output as:
<INPUT TYPE="RADIO" NAME="f" ID="fnone" VALUE="" $nchecked
onChange="this.form.submit();"><LABEL FOR="fnone">Default</LABEL>
<INPUT TYPE="RADIO" NAME="f" ID="f" VALUE="f" $fchecked
onChange="this.form.submit();"><LABEL FOR="f">Raw Frink notation</LABEL>
<INPUT TYPE="RADIO" NAME="f" ID="m" VALUE="m" $mchecked
onChange="this.form.submit();"><LABEL FOR="m">MathML</LABEL>
<TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="CHECKBOX" NAME="ev" ID="ev" $evchecked
onChange="this.form.submit();"><LABEL FOR="ev">Evaluate result numerically</LABEL>
<TR><TD CLASS="noborder" COLSPAN="2"><INPUT TYPE="Submit" VALUE="Solve">
</TABLE>
</DIV>
<%
if (equation)
{
if (equation =~ %r/=/)
{
equation =~ %s/=/===/
if solveFor
expr = parseToExpression["solve[$equation
,$solveFor
]"]
else
{
// If there's no "solve for" specified but only 1 symbol in the
// equation, use the one symbol. This does not put it into the
// text field, though.
// TODO: Also, this code should be unified with
// the code below that checks to see if the "solve for" symbol
// even exists in the expression.
expr = parseToExpression[equation]
syms = getSymbols[expr]
if length[syms] == 1
{
solveFor = toArray[syms]@0
solveStr = HTMLEncodeQuoted[solveFor]
expr = parseToExpression["solve[$equation
,$solveFor
]"]
} else
println["""<P CLASS="warning"><I>No "solve for" variable present. Please select a variable to solve for.</I></P>"""]
}
} else
{
println["<P><I>No equals sign present. Will not solve equation, but just evaluate the expression.</I></P>"]
expr = parseToExpression[equation]
}
symbols = getSymbols[parseToExpression[equation]]
// println["<P>symbols are: " + join[", ", symbols] + "</P>"]
if solveFor && ! symbols.contains[solveFor]
println["""<P CLASS="warning">The equation does not contain the "solve for" variable <CODE><B>$solveFor
</B></CODE>. Please choose a correct variable to solve for.</P>\n"""]
println["<P><B>Solution:</B></P><P CLASS=\"code\"><CODE>"]
last = undef
if w // Show work?
{
res = array[transformExpressionTrace[expr]]
lastres = ""
for resline = res
{
resline = HTMLEncode[toString[resline]]
if resline != lastres
{
if f=="f"
println[removeApproximations[resline] + "<BR><BR>\n"]
else
println[formatExpressionSymbolic[resline] + "<BR><BR>\n"]
}
lastres = resline
}
last = res@(length[res]-1)
} else
{ // Don't show work
res = array[transformExpression[expr]]
if f=="f"
println[removeApproximations[join["<BR>",res]]]
else
if f=="m"
{
for r1 = res
println[MathML.format[r1,true,0,extra]+"<BR>\n"]
} else
println[formatExpressionSymbolic[join["<BR>",res]]]
last = res
}
println["</CODE></P>"]
/* All of the following code is to detect variable names in the
resulting solutions and create HTML forms to allow the user to
optionally plug in values for each variable (or leave them symbolic)
and evaluate the result symbolically and numerically. */
if ev // Evaluate result?
{
println["""<DIV CLASS="back"><P><A NAME="Evaluated"><B>Evaluated result:</B></A></P>"""]
symbols = getSymbols[last]
symbols.remove[solveFor]
repstr = ""
repls = new array
println["""<TABLE BORDER=1 STYLE="width: 100%"><TR><TH>Sym<TH>Symbolic?<TH>Value"""]
for sym = symbols
{
selvar = "sel_$sym
"
varname = "val_$sym
"
sch = eval[selvar] == "S" ? "checked" : ""
lch = eval[selvar] == "L" ? "checked" : ""
if (! sch AND ! lch)
sch = "checked"
if sch
repstr = repstr + "$sym
= noEval[$sym
]\n"
if lch
repls.push[ [constructExpression["Symbol",[sym]], eval[eval[varname]]]]
val = eval[varname] ? eval[varname] : (unit[sym] != undef ? eval[sym] : "")
valstr = HTMLEncodeQuoted[isString[val] ? val : inputFormUnicode[val]]
println[" <TR>"]
println[""" <TD>$sym
="""]
println[""" <TD><INPUT TYPE="RADIO" NAME="$selvar
" ID="${selvar}
_S" VALUE="S" $sch
><LABEL FOR="${selvar}
_S">$sym
</LABEL>"""]
println[""" <TD><INPUT TYPE="RADIO" NAME="$selvar
" ID="${selvar}
_L" VALUE="L" $lch
>"""]
print[""" <INPUT TYPE="TEXT" autocapitalize="none" autocorrect="none" NAME="$varname
" VALUE="$valstr
" STYLE="width: 90%; box-sizing: border-box" oninput="document.getElementById('${selvar}
_L').checked=true">"""]
}
println["</TABLE>"]
println["""<BR>(Optional) Show result in units: <INPUT TYPE="TEXT" NAME="resultAs" ID="resultAs" VALUE="$resultAsQuoted
" autocapitalize="none" autocorrect="none">"""]
println["""<BR><INPUT TYPE="Submit" VALUE="Solve">"""]
println["""<P CLASS="code"><CODE>"""]
resultAs = resultAs ? trim[resultAs] : ""
if isVariableDefined[resultAs] and resultAs != ""
{
// If resultAs has a comma like "ft, in" or "[ft, in]", or
// with quoted terms such as ["ft", "in"], then just canonify
// it to ["ft", "in"] or if it has a zero, leave that unquoted
// like ["ft", "in", 0]
// TODO: Turn this into a function
if resultAs =~ %r/,/
{
// Remove square brackets and quotes
resultAs =~ %s/[\[\]"]//g
resultAsArray = new array
for resa = split[",", resultAs] // Split on commas
{
resa = trim[resa]
if resa == "0" // Preserve literal 0 unquoted.
resultAsArray.push[0]
else
resultAsArray.push[resa]
}
resultAs = resultAsArray
}
}
results = flatten[toArray[last]]
for eqn = rangeOf[results]
{
eq1 = results@eqn
varlen = 1
// Evaluate right-hand sides of solved equations
if structureEquals[_a === _b, eq1]
{
print[getChild[eq1, 0] + " = "]
part = getChild[eq1, 1]
varlen = length[inputFormUnicode[getChild[eq1,0]]]
} else
part = eq1
for [e1, e2] = repls
part = substituteExpression[part, e1, e2]
repstr2 = repstr + inputFormUnicode[part]
pe = eval[repstr2, false, true]
if ! structureEquals[pe, part]
if f
print[HTMLEncode[inputFormUnicode[part]] + "<BR>" + repeat[" ", varlen + 1] + "= "]
else
print[formatExpressionSymbolic[inputFormUnicode[part]] +
"<BR>" + repeat[" ", varlen + 1] + "= "]
if isVariableDefined[resultAs] and resultAs != "" and isUnit[pe]
{
result = (pe -> resultAs)
result = HTMLEncode[result]
result = formatExpression[result]
result =~ %s/\n/<BR>\n/mg
result =~ %s/\s/ /g
} else
{
if f
result = HTMLEncode[inputFormUnicode[pe]]
else
result = formatExpressionSymbolic[inputFormUnicode[pe]]
}
println[result + "<BR>"]
if eqn < length[results]-1
println["<BR>"]
}
println["</CODE></P></DIV>"]
}
}
%>
</FORM>
<HR>
<P>
View source of <A HREF="highlight.fsp?f=solve.fsp">this FSP page</A>. This
is a program written in the programming language <A
HREF="https://frinklang.org/">Frink</A>.
</P>
<P>
<I>Contact <A HREF="mailto:eliasen@mindspring.com">Alan Eliasen</A></I>
</P>
<P>
Back to <A HREF="/frinkdocs/fspdocs.html">Frink Server Pages
documentation.</A>
</P>
</BODY>
</HTML>
[Try solve.fsp]
Alan Eliasen was born
20203 days, 11 hours, 46 minutes ago.
Back to Frink Server Pages
documentation.