{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from notebook_preamble import J, V, define" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# [Quadratic formula](https://en.wikipedia.org/wiki/Quadratic_formula)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Cf. [jp-quadratic.html](http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " -b ± sqrt(b^2 - 4 * a * c)\n", " --------------------------------\n", " 2 * a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Write a straightforward program with variable names.\n", "This math translates to Joy code in a straightforward manner. We are going to use named variables to keep track of the arguments, then write a definition without them." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `-b`\n", " b neg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `sqrt(b^2 - 4 * a * c)`\n", " b sqr 4 a c * * - sqrt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `/2a`\n", " a 2 * /" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `±`\n", "There is a function `pm` that accepts two values on the stack and replaces them with their sum and difference.\n", "\n", " pm == [+] [-] cleave popdd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Putting Them Together\n", "\n", " b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n", "\n", "We use `app2` to compute both roots by using a quoted program `[2a /]` built with `cons`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Derive a definition.\n", "Working backwards we use `dip` and `dipd` to extract the code from the variables:\n", "\n", " b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n", " b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n", " b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2\n", " b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n", " b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n", "\n", "The three arguments are to the left, so we can \"chop off\" everything to the right and say it's the definition of the `quadratic` function:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's try it out:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-0.3819660112501051 -2.618033988749895\n" ] } ], "source": [ "J('3 1 1 quadratic')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you look at the Joy evaluation trace you can see that the first few lines are the `dip` and `dipd` combinators building the main program by incorporating the values on the stack. Then that program runs and you get the results. This is pretty typical of Joy code." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " . -5 1 4 quadratic\n", " -5 . 1 4 quadratic\n", " -5 1 . 4 quadratic\n", " -5 1 4 . quadratic\n", " -5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n", " -5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n", "-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2\n", " -5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2\n", " -5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2\n", " -5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " -5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " -5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2\n", " 5 25 16 . - sqrt pm 1 2 * [/] cons app2\n", " 5 9 . sqrt pm 1 2 * [/] cons app2\n", " 5 3.0 . pm 1 2 * [/] cons app2\n", " 8.0 2.0 . 1 2 * [/] cons app2\n", " 8.0 2.0 1 . 2 * [/] cons app2\n", " 8.0 2.0 1 2 . * [/] cons app2\n", " 8.0 2.0 2 . [/] cons app2\n", " 8.0 2.0 2 [/] . cons app2\n", " 8.0 2.0 [2 /] . app2\n", " [8.0] [2 /] . infra first [2.0] [2 /] infra first\n", " 8.0 . 2 / [] swaack first [2.0] [2 /] infra first\n", " 8.0 2 . / [] swaack first [2.0] [2 /] infra first\n", " 4.0 . [] swaack first [2.0] [2 /] infra first\n", " 4.0 [] . swaack first [2.0] [2 /] infra first\n", " [4.0] . first [2.0] [2 /] infra first\n", " 4.0 . [2.0] [2 /] infra first\n", " 4.0 [2.0] . [2 /] infra first\n", " 4.0 [2.0] [2 /] . infra first\n", " 2.0 . 2 / [4.0] swaack first\n", " 2.0 2 . / [4.0] swaack first\n", " 1.0 . [4.0] swaack first\n", " 1.0 [4.0] . swaack first\n", " 4.0 [1.0] . first\n", " 4.0 1.0 . \n" ] } ], "source": [ "V('-5 1 4 quadratic')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.15" } }, "nbformat": 4, "nbformat_minor": 2 }