# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "marimo==0.24.0",
# ]
# ///

import marimo

__generated_with = "0.24.0"
app = marimo.App(width="medium")


@app.cell
def _():
    import marimo as mo
    from symbolica import Expression, N, S

    return Expression, N, S, mo


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ## General · Symbolica quick start
    A short, editable tour of exact arithmetic, symbolic algebra, derivatives,
    and pattern matching. Everything here runs in your browser.
    """)
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ### 1. Keep arithmetic exact
    `N` creates an exact number. Use it before division to avoid Python's
    floating-point arithmetic: this sum stays exactly one half.
    """)
    return


@app.cell
def _(Expression, N):
    exact: Expression = N(1) / 3 + N(1) / 6
    exact
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ### 2. Expand and factor
    `S` creates symbols. Build expressions with ordinary Python operators,
    then expand them or recover their factors. Try changing the power below.
    """)
    return


@app.cell
def _(Expression, S):
    x, y = S("x", "y")
    expression: Expression = (x + y)**3
    expression
    return expression, x, y


@app.cell
def _(Expression, expression: "Expression"):
    expanded: Expression = expression.expand()
    expanded
    return (expanded,)


@app.cell
def _(expanded: "Expression"):
    expanded.factor()
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ### 3. Substitute and differentiate
    Replace a symbol with another expression, or differentiate with respect to
    one variable. Both cells use the expression you defined above.
    """)
    return


@app.cell
def _(expression: "Expression", y):
    expression.replace(y, 1).expand()
    return


@app.cell
def _(expression: "Expression", x):
    expression.derivative(x)
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ### 4. Rewrite with patterns
    A symbol ending in `_` is a wildcard. This rule replaces every `f(argument)`
    with the square of its argument, including symbolic arguments.
    """)
    return


@app.cell
def _(Expression, S, x):
    f, a_ = S("f", "a_")
    functions: Expression = f(x) + f(2) + f(3)
    functions.replace(f(a_), a_**2)
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    ### 5. Cancel common factors
    Simplify a rational expression algebraically. The result below is `x + 1`;
    the original fraction is still undefined at `x = 1`.
    """)
    return


@app.cell
def _(Expression, x):
    rational: Expression = (x**2 - 1) / (x - 1)
    rational.cancel()
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md("""
    **Your turn:** change the expression, try a different replacement rule,
    or type `rational.` to explore more operations. Function signatures appear
    as you type. Download the notebook from the gallery to use it locally.
    """)
    return


if __name__ == "__main__":
    app.run()
