diff --git a/day 73 - bresenhams line.ipynb b/day 73 - bresenhams line.ipynb
new file mode 100644
index 0000000..78f6918
--- /dev/null
+++ b/day 73 - bresenhams line.ipynb
@@ -0,0 +1,821 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "
\n",
+ "
\n",
+ "
Loading BokehJS ...\n",
+ "
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "\n",
+ "(function(global) {\n",
+ " function now() {\n",
+ " return new Date();\n",
+ " }\n",
+ "\n",
+ " var force = true;\n",
+ "\n",
+ " if (typeof (window._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
+ " window._bokeh_onload_callbacks = [];\n",
+ " window._bokeh_is_loading = undefined;\n",
+ " }\n",
+ "\n",
+ "\n",
+ " \n",
+ " if (typeof (window._bokeh_timeout) === \"undefined\" || force === true) {\n",
+ " window._bokeh_timeout = Date.now() + 5000;\n",
+ " window._bokeh_failed_load = false;\n",
+ " }\n",
+ "\n",
+ " var NB_LOAD_WARNING = {'data': {'text/html':\n",
+ " \"\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
+ " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"- re-rerun `output_notebook()` to attempt to load from CDN again, or
\\n\"+\n",
+ " \"- use INLINE resources instead, as so:
\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"from bokeh.resources import INLINE\\n\"+\n",
+ " \"output_notebook(resources=INLINE)\\n\"+\n",
+ " \"
\\n\"+\n",
+ " \"
\"}};\n",
+ "\n",
+ " function display_loaded() {\n",
+ " if (window.Bokeh !== undefined) {\n",
+ " var el = document.getElementById(\"75c75969-bea0-4564-af39-7e895b7c4445\");\n",
+ " el.textContent = \"BokehJS \" + Bokeh.version + \" successfully loaded.\";\n",
+ " } else if (Date.now() < window._bokeh_timeout) {\n",
+ " setTimeout(display_loaded, 100)\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " function run_callbacks() {\n",
+ " window._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
+ " delete window._bokeh_onload_callbacks\n",
+ " console.info(\"Bokeh: all callbacks have finished\");\n",
+ " }\n",
+ "\n",
+ " function load_libs(js_urls, callback) {\n",
+ " window._bokeh_onload_callbacks.push(callback);\n",
+ " if (window._bokeh_is_loading > 0) {\n",
+ " console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
+ " return null;\n",
+ " }\n",
+ " if (js_urls == null || js_urls.length === 0) {\n",
+ " run_callbacks();\n",
+ " return null;\n",
+ " }\n",
+ " console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
+ " window._bokeh_is_loading = js_urls.length;\n",
+ " for (var i = 0; i < js_urls.length; i++) {\n",
+ " var url = js_urls[i];\n",
+ " var s = document.createElement('script');\n",
+ " s.src = url;\n",
+ " s.async = false;\n",
+ " s.onreadystatechange = s.onload = function() {\n",
+ " window._bokeh_is_loading--;\n",
+ " if (window._bokeh_is_loading === 0) {\n",
+ " console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
+ " run_callbacks()\n",
+ " }\n",
+ " };\n",
+ " s.onerror = function() {\n",
+ " console.warn(\"failed to load library \" + url);\n",
+ " };\n",
+ " console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
+ " document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
+ " }\n",
+ " };var element = document.getElementById(\"75c75969-bea0-4564-af39-7e895b7c4445\");\n",
+ " if (element == null) {\n",
+ " console.log(\"Bokeh: ERROR: autoload.js configured with elementid '75c75969-bea0-4564-af39-7e895b7c4445' but no matching script tag was found. \")\n",
+ " return false;\n",
+ " }\n",
+ "\n",
+ " var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.5.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.5.min.js\"];\n",
+ "\n",
+ " var inline_js = [\n",
+ " function(Bokeh) {\n",
+ " Bokeh.set_log_level(\"info\");\n",
+ " },\n",
+ " \n",
+ " function(Bokeh) {\n",
+ " \n",
+ " },\n",
+ " \n",
+ " function(Bokeh) {\n",
+ " \n",
+ " document.getElementById(\"75c75969-bea0-4564-af39-7e895b7c4445\").textContent = \"BokehJS is loading...\";\n",
+ " },\n",
+ " function(Bokeh) {\n",
+ " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-0.12.5.min.css\");\n",
+ " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-0.12.5.min.css\");\n",
+ " console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.5.min.css\");\n",
+ " Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.5.min.css\");\n",
+ " }\n",
+ " ];\n",
+ "\n",
+ " function run_inline_js() {\n",
+ " \n",
+ " if ((window.Bokeh !== undefined) || (force === true)) {\n",
+ " for (var i = 0; i < inline_js.length; i++) {\n",
+ " inline_js[i](window.Bokeh);\n",
+ " }if (force === true) {\n",
+ " display_loaded();\n",
+ " }} else if (Date.now() < window._bokeh_timeout) {\n",
+ " setTimeout(run_inline_js, 100);\n",
+ " } else if (!window._bokeh_failed_load) {\n",
+ " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
+ " window._bokeh_failed_load = true;\n",
+ " } else if (force !== true) {\n",
+ " var cell = $(document.getElementById(\"75c75969-bea0-4564-af39-7e895b7c4445\")).parents('.cell').data().cell;\n",
+ " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
+ " }\n",
+ "\n",
+ " }\n",
+ "\n",
+ " if (window._bokeh_is_loading === 0) {\n",
+ " console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
+ " run_inline_js();\n",
+ " } else {\n",
+ " load_libs(js_urls, function() {\n",
+ " console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
+ " run_inline_js();\n",
+ " });\n",
+ " }\n",
+ "}(this));"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import numpy as np\n",
+ "from bokeh.plotting import figure, show, output_notebook\n",
+ "from bokeh.palettes import Set3_12\n",
+ "\n",
+ "output_notebook()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## algorithm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def bresenham(x0, y0, x1, y1, color, canvas):\n",
+ " # swap major and minor axis\n",
+ " if abs(y0 - y1) > abs(x0 - x1):\n",
+ " x0, y0, x1, y1 = y0, x0, y1, x1\n",
+ " canvas = canvas.T\n",
+ " \n",
+ " # swap x-axis direction\n",
+ " if x0 > x1:\n",
+ " x0, y0, x1, y1 = x1, y1, x0, y0\n",
+ " \n",
+ " # initialize\n",
+ " dx, dy = abs(x0 - x1), abs(y0 - y1)\n",
+ " dz = 1 if y0 <= y1 else -1\n",
+ " p = 2 * dy - dx\n",
+ " \n",
+ " # draw\n",
+ " while x0 <= x1:\n",
+ " canvas[y0, x0] = color\n",
+ "\n",
+ " if p > 0:\n",
+ " p -= 2 * dx\n",
+ " y0 += dz\n",
+ " p += 2 * dy\n",
+ " x0 += 1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## plot"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def plot(canvas):\n",
+ " w, h = canvas.shape\n",
+ " \n",
+ " plot = figure(x_range=(0, w - 1), y_range=(0, h - 1))\n",
+ " plot.grid.visible = False\n",
+ " plot.axis.visible = False\n",
+ " image = plot.image([canvas], \n",
+ " x=0, y=0, dw=w - 1, dh=h - 1,\n",
+ " palette=['#000000'] + Set3_12)\n",
+ " \n",
+ " show(plot)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "n = 50\n",
+ "canvas = np.zeros((n, n), dtype=int)\n",
+ "\n",
+ "# 8 basic lines\n",
+ "m = n // 2\n",
+ "bresenham(m, m, n-1, m+10, 1, canvas)\n",
+ "bresenham(m, m, n-1, m-10, 2, canvas)\n",
+ "bresenham(m, m, m+10, n-1, 3, canvas)\n",
+ "bresenham(m, m, m+10, 0, 4, canvas)\n",
+ "bresenham(0, m+10, m, m, 5, canvas)\n",
+ "bresenham(0, m-10, m, m, 6, canvas)\n",
+ "bresenham(m-10, n-1, m, m, 7, canvas)\n",
+ "bresenham(m-10, 0, m, m, 8, canvas)\n",
+ "bresenham(m, m, m, m, 0, canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ " \n",
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plot(canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [],
+ "source": [
+ "n = 100\n",
+ "canvas = np.zeros((n, n), dtype=int)\n",
+ "\n",
+ "for i in range(10):\n",
+ " x = np.random.randint(0, n, 4)\n",
+ " bresenham(*x, i + 1, canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ " \n",
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plot(canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "n = 200\n",
+ "canvas = np.zeros((n, n), dtype=int)\n",
+ "\n",
+ "for i in range(n):\n",
+ " bresenham(0, 0, i, n - 1, i % 10 + 1, canvas)\n",
+ " bresenham(0, 0, n - 1, i, i % 10 + 1, canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ " \n",
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "plot(canvas)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.0"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}