solve2.fsp - Frink Server Pages highlighter
[Try solve2.fsp]
<!DOCTYPE html>
<HTML LANG="en">
<HEAD>
<TITLE>Frink System Solver</TITLE>
<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">
<META NAME="viewport" CONTENT="width=device-width, initial-scale=1.0">
<LINK REL="canonical" HREF="https://frinklang.org/fsp/solve2.fsp">
</HEAD>
<%
use ../
systemSolver2.frink
use ../
HTMLUtils.frink
use ../
MathML.frink
// showApproximations[false]
symbolicMode[true]
if !isVariableDefined["equations"]
ev = true
// equations = equations ? equations : "x^2 + 3x - 2 + 4y + 3y^2 = 3x - y + 10"
eqStr = HTMLEncode[equations]
rows = max[length[splitLines[equations]]+1, 8]
solveFor = solveFor ? trim[solveFor] : undef
solveStr = HTMLEncode[solveFor]
wchecked = w ? "CHECKED" : ""
f = f ? f : ""
fchecked = (f=="f" or f=="on") ? "CHECKED" : ""
mchecked = f=="m" ? "CHECKED" : ""
nchecked = f=="" ? "CHECKED" : ""
evchecked = ev ? "CHECKED" : ""
conformalChecked = conformal ? "CHECKED" : ""
solvedChecked = solved ? "CHECKED" : ""
showorigChecked = showorig ? "CHECKED" : ""
if resultAs
resultAs = trim[resultAs]
resultAsQuoted = resultAs ? HTMLEncodeQuoted[resultAs] : ""
extra = """ class="big" """ // MathML format
%>
<BODY onLoad="document.f1.equations.focus()">
<H1>Frink System Solver</H1>
<FORM ACTION="solve2.fsp" METHOD="GET" NAME="f1">
<DIV CLASS="back">
<TABLE BORDER="0" SUMMARY="Equation input">
<TR><TD CLASS="noborder" COLSPAN="2"><LABEL FOR="equation">Equations (one per line):</LABEL>
<TR><TD CLASS="noborder" COLSPAN="2"><TEXTAREA WRAP="off" ROWS="$rows
" COLS="80" autocapitalize="none" autocorrect="none" spellcheck="false"
NAME="equations" ID="equations">$eqStr
</TEXTAREA>
<TR><TD CLASS="noborder"><LABEL FOR="solveFor">Solve for: </LABEL><INPUT TYPE="text" SIZE="5" autocapitalize="none" autocorrect="none" spellcheck="false"
NAME="solveFor" ID="solveFor" VALUE="$solveStr
"> (<I>leave blank for all</I>)
<!-- <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 isVariableDefined[equations] and trim[equations] != ""
{
if (equations =~ %r/=/)
{
equations =~ %s/=/===/g
equations =~ %s/^\s*\/\/(.*)//mg // Skip commented-out lines
equations =~ %s/^[\r\n\s]+//s // Remove leading whitespace
equations =~ %s/[\r\n\s]+$//s // Remove trailing whitespace
equations =~ %s/[\r\n]+/,/sg
// println[equations]
str = "new System[[$equations
], []]"
// println[str]
system = unsafeEval[str]
// println[system]
eqs = system.solveAll[]
if solveFor
eqs = system.solveFor[solveFor]
println["<P><B>Solution:</B></P>"]
if f=="m"
println["<DIV CLASS=\"back\">"]
else
println["<P CLASS=\"code\"><CODE>"]
for eq = eqs
if f=="f"
println[HTMLEncode[inputFormUnicode[eq]] + "<BR>"]
else
if f=="m"
{
if structureEquals[noEval[_a===_b], eq]
eq = substituteExpression[eq, noEval[_a===_b], noEval[_a=_b]]
println[MathML.format[eq, true, 0, extra]+ "<BR><BR>"]
} else
println[formatExpressionSymbolic[inputFormUnicode[eq]] + "<BR>"]
if f=="m"
println["</DIV>"]
else
println["</CODE></P>"]
} else
{
println["<P><I>No equals sign present. This is probably not a system of equations. </I></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 isVariableDefined["equations"] and trim[equations] != "" and ev // Evaluate result?
{
println["""<BR><DIV CLASS="back"><P><A NAME="Evaluated"><B>Evaluated result:</B></A></P>"""]
symbols = new set
for eq = eqs
symbols = union[symbols, getSymbols[eq]]
symbols.remove[solveFor]
repstr = ""
repls = new array
println["""<TABLE BORDER=1 STYLE="width: 100%"><TR><TH>Sym<TH>Symbolic?<TH>Value"""]
for sym = lexicalSort[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" spellcheck="false" NAME="$varname
" VALUE="$valstr
" STYLE="width: 90%; box-sizing: border-box" oninput="if (this.value.trim().length != 0) {document.getElementById('${selvar}
_L').checked=true} else {document.getElementById('${selvar}
_S').checked=true; this.value=' '}">"""]
}
println["</TABLE>"]
println["""<BR>(Optional) Show result in units: <INPUT TYPE="TEXT" NAME="resultAs" ID="resultAs" VALUE="$resultAsQuoted
" autocapitalize="none" autocorrect="none" spellcheck="false"><BR>"""]
println[""" <INPUT TYPE="CHECKBOX"
NAME="conformal" ID="conformal" $conformalChecked
onChange="this.form.submit();"><LABEL FOR="conformal">Conformal</LABEL><BR>"""]
println[""" <INPUT TYPE="CHECKBOX"
NAME="solved" ID="solved" $solvedChecked
onChange="this.form.submit();"><LABEL FOR="solved">Fully solved</LABEL><BR>"""]
println[""" <INPUT TYPE="CHECKBOX"
NAME="showorig" ID="showorig" $showorigChecked
onChange="this.form.submit();"><LABEL FOR="showorig">Show original equation</LABEL><BR>"""]
println["""<INPUT TYPE="Submit" VALUE="Solve"></DIV>"""]
if f=="m"
println["<BR><DIV CLASS=\"back\">"]
else
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]]
results = eqs
suppressed = 0
RESULT:
for eqn = rangeOf[results]
{
eq1 = results@eqn
varlen = 1
// Evaluate right-hand sides of solved equations
preamble = ""
// This matches a solved equation
if structureEquals[_a === _b, eq1]
{
preamble = preamble + getChild[eq1, 0] + " = "
part = getChild[eq1, 1]
varlen = length[inputFormUnicode[getChild[eq1,0]]]
if showorig
{
if f=="f"
preamble = preamble + HTMLEncode[inputFormUnicode[getChild[eq1,1]]] + "<BR>"
else
if f=="m"
preamble = preamble + MathML.format[getChild[eq1,1], true, 0, extra] + "<BR>"
else
preamble = preamble + formatExpressionSymbolic[inputFormUnicode[getChild[eq1,1]]] + "<BR>"
preamble = preamble + repeat[" ", varlen] + " = "
}
} else
part = eq1
for [e1, e2] = repls
part = substituteExpression[part, e1, e2]
repstr2 = repstr + inputFormUnicode[part]
pe = eval[repstr2, false, true]
// println["pe=$pe
, type=" + type[pe] + ", resultAs=$resultAs
, eval=" + eval[eval[resultAs]]]
if ! structureEquals[pe, part]
if f == "f"
preamble = preamble + HTMLEncode[inputFormUnicode[part]] + "<BR>" + repeat[" ", varlen + 1] + "= "
else
if f == "m"
preamble = preamble + MathML.format[part, true, 0, extra] + "<BR>" + repeat[" ", varlen + 1] + "= "
else
preamble = preamble + formatExpressionSymbolic[inputFormUnicode[part]] + "<BR>" + repeat[" ", varlen + 1] + "= "
if solved && !isUnit[pe]
{
suppressed = suppressed + 1
next RESULT
}
if isVariableDefined[resultAs] and resultAs != "" and isUnit[pe]
{
if conformal
if ! (pe conforms eval[eval[resultAs]])
{
suppressed = suppressed + 1
next RESULT
}
if pe conforms eval[eval[resultAs]]
result = (pe -> resultAs)
else
result = inputFormUnicode[pe]
result = HTMLEncode[result]
result = formatExpression[result]
result =~ %s/\n/<BR>\n/mg
result =~ %s/\s/ /g
} else
{
if conformal && isVariableDefined[resultAs] and resultAs != ""
{
suppressed = suppressed + 1
next RESULT
}
if f == "f"
result = HTMLEncode[inputFormUnicode[pe]]
else
if f == "m"
result = MathML.format[pe, true, 0, extra]
else
if solved
result = formatExpression[outputForm[pe]]
else
result = formatExpressionSymbolic[inputFormUnicode[pe]]
}
println[preamble]
println[result + "<BR>"]
if eqn < length[results]-1
println["<BR>"]
}
if f=="m"
println["</DIV>"]
else
println["</CODE></P>"]
if (suppressed > 0)
println["<I>$suppressed
items suppressed because of above options.</I>"]
println["</P></DIV></FORM>"]
}
%>
<HR>
<P>
<A HREF="solve2.fsp" TARGET="_blank">Open new blank solver</A>
</P>
<P>
View source of <A HREF="highlight.fsp?f=solve2.fsp">this FSP page</A> or the <A HREF="colorize.fsp?f=allTransforms.frink">transformation rules</A> that solve these equations.
</P>
<P>
<I><A HREF="mailto:eliasen@mindspring.com">Alan Eliasen</A></I> was born
<%= round[now[] - #1969-08-19 04:54 PM Mountain#, minute] -> ["days", "hours", "minutes"] %>
ago.
</P>
<P>
Back to <A HREF="/frinkdocs/fspdocs.html">Frink Server Pages
documentation.</A>
</P>
</BODY>
</HTML>
[Try solve2.fsp]
Alan Eliasen was born
20218 days, 1 hours, 26 minutes ago.
Back to Frink Server Pages
documentation.