<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Tom Moertel's Blog</title>
    <link href="http://blog.moertel.com/xml/atom/feed.xml" rel="self" />
    <link href="http://blog.moertel.com" />
    <id>http://blog.moertel.com/xml/atom/feed.xml</id>
    <author>
        <name>Tom Moertel</name>
        
        <email>tom@moertel.com</email>
        
    </author>
    <updated>2025-08-27T00:00:00Z</updated>
    <entry>
    <title>When Google Takeout Fails</title>
    <link href="http://blog.moertel.com/posts/2025-08-27-when-takeout-fails.html" />
    <id>http://blog.moertel.com/posts/2025-08-27-when-takeout-fails.html</id>
    <published>2025-08-27T00:00:00Z</published>
    <updated>2025-08-27T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2025-08-27">August 27, 2025</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;google&#39;." href="/tags/google.html" rel="tag">google</a>, <a title="All pages tagged &#39;takeout&#39;." href="/tags/takeout.html" rel="tag">takeout</a>, <a title="All pages tagged &#39;backups&#39;." href="/tags/backups.html" rel="tag">backups</a>, <a title="All pages tagged &#39;data&#39;." href="/tags/data.html" rel="tag">data</a></span></div>

<div itemprop="articleBody">
<p>When Google Takeout fails, you’re basically on your own. Here are some quick tips for getting your data when things go wrong.</p>
<p>Oh, you tried to download your precious data from a bunch of Google products and days later you got an email with the subject “We couldn’t create a copy of your Google data”? Surely, for something as important as this, Google is going to Respect the User and provide meaningful help and options for moving forward.</p>
<p>Joke’s on you. Because what Google actually provides is nothing. Seriously, the email says only that “Something went wrong and we couldn’t create a copy of your Google data. You can try to create a new export.”</p>
<p>Well, that’s helpful.</p>
<p>What else can we try? It turns out that you can glean <em>some</em> information by going to <a href="https://takeout.google.com/manage">takeout.google.com/manage</a> and clicking on the failing export to reveal this screen:</p>
<p><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnAAAAHgCAYAAAAlnVB9AAAQAElEQVR4AeydBWAUyRKG/9mNe4Dg7hzu7u7u7u7u7u7u7nI89JCDw93d3eJu+7o62WUTEhIgskkqpGd6uqvtmwnzb/X0rErDP0yACTABJsAEmAATYAJxioAK/MMEmAATYAJM4JcJcAEmwARikwALuNikz20zASbABJgAE2ACTOA3CLCA+w1oXMQwCHAvmAATYAJMgAkkVAIs4BLqmedxMwEmwASYABNImATixahZwMWL08iDYAJMgAkwASbABBISARZwCels81iZABMwDALcCybABJjAHxJgAfeHALk4E2ACTIAJMAEmEH8JaNxdEfD+DXwP7YZLh7oyfM6TAp/zppRxj+kj4DlrNPwf3oXGxTHGQLCAizHUBtUQd4YJMAEmwASYABMIj0BgAAKePoBT/TL4UiIbvlUrAudhveBz9bIMsphGI+Mem9fCfcMqODapjC+lc4LEneeCidB4uEuz6NqwgIsuslwvE2ACTIAJMIF4RyCeDygwEAHPHsGxXml8a1ABfs+eAIoCxdIK5lVrIvGmgzIkvf0BSW+9l3HbERNhO2QMFBtbKKZmoB/3VUvwpXgWeC2dBo2PDyVFeWABF+VIuUImwASYABNgAkwgzhEICIBjzWL4Vr8c/F++ANRqWHXoIYWaw4UnsJ65Cuo8BWWQYxPCjo5Nm3WCaavucPjvIRyuvIDdrKUwzvYXSPi5LZ2PL4XTw+/yWUB47BCFPyzgohAmV8UEmED0E+AWmAATYAJRTcDv7DF8LpgW/u/eyKqtu/ZF0muvYdFvtDymjbOrKy5cuYGV67di8bodmLdyM+YtWYX5C5fg7H/n4O/vT2YwqVIP9jtPIOnVVzDJk0+mOXVqAudODWQ8qjYs4KKKJNfDBJgAE2ACTIAJxDkCXuuXwKl3e0BMn5oWKyW9aOY9hwEqFR4+u4fKbcph3d9HcODYWZw9fhhWJkYwUTSwt7WFBkZwdPHE1i3b0aVzV7Rr1Qrbt29HgPDmwdgYdpsOw37ResnE98pFPG9cT8ajYsMC7pcpcgEmwASYABNgAkwgPhDwWrsIbnMnS/FmM3EubJduk8+xPX7xCJWalUPj7g0AaxVyZ8uFlHaWaNa0OQrmzYtMSW2RPokdsmZIi5TWRsiYIgmyJrVGjlQOeH/3Bnp3aof9B49IRMZlqiDJ6Ttwy1EMbdIsRZ1pUbO4gQWcxMsbJsAEmAATYALRTICrNygCfqcPwW3BNCne7JdtgVndZqDn3qYvHo+WA5rhneNHeAf6YVLftbAwViNPjmywsU+ERHY2SJ3IHlbwg1WABzKlSo1c6dMgV6ZMyJM1MzKkToWS+fPg1LHDGD5qPL5++wZVoiRIt3En7B1s8PZbIDos9sCf/rCA+1OCXJ4JMAEmwASYABOIUwRIvDkP7AYx1wm7+WtgXKK87H+PIe2w88A2eHl5w8fZCw7mSWBtbolALzeojYzh4+EBT8evCPByh7G/J2yNNbBWA+ZqBZaWljC3sBDTq4HiWI0caZLD09MT85csx/U7V2Ekpl639LNA6sRq3HwZgF6rPGWbv7thAfe75LgcE4h7BLjHTIAJMAEmIAi4Th4FjZ8fzEqXh0n56iIFaNW9BY78cxLOX7zg9c0bavHP1N8BZkZGsDQzha+3J7xdXeDl9A1e7s7Q+HrDz8sLPm6fxd4VKk2ASPNFgKhXowmEsShnbWUJaBTMXTUTF2+cFWJQwYzWZrK984/88d8Dfxn/nY3qdwqFV+b4HX+sOe2LUTu9MeOgD3Ze9MNnV0145gaf7hfgh+Ovzsjg7e9t8P3lDjIBJsAEmEDCIPDi5UusXbsWs2bPwrz587Bn7148efokYQz+D0fpMWMUAj59gFHGTLCevVrW1ndUX1y5cQVqlRpGUAGe/gj090eOIjnh4+MFRUyl+nl7wM/HE5qAAChC2gQIjRDo6wV6XYixsbFIC4SPl8gXefTKEH9RzsrKCr7+AaIOH4yc0RNPXz5C9lRqTG1pDvoZs12Up8hvBNHL3ygVqsjcw75oNN8T0/72webzfrjwJABHb/tj2UlfNF/kid7rvXH7dQAQqpyhH3oH+mLExYUyePj9PmRDHyf3jwkwASbABOIGgUVLFqNlq1bo2q0rtm7fhmPHj+PQ4cNYtnwZevbqhdZtWmPlqlVxYzCx1Eu/x2tky9bDJkExM8ee/+3C8bNHoTZTYGplAms7S9gnthVeN3NYmVvD+esn+Ht7IECIN5UQZ8ZmZjA3t4A5vbRXeNpMTUxgaWUL+lFUKgSKfxqNBn5CAKrEsY/w3BkFWuDz+y8YP3MQmaFCbmOkTKSCs4cGq074yrRf3ah+tYC+/f13gWgohNvBG35wEp3Qz9OP338XgMFbvTFdCDz9dI5/J/D06VP8888/MgQGBn7P4BgTYAJMgAkgoSO4ceMG6jWojwMHDuDL1y9InDgxGjVqhM6dOqF9u/aoWqUK0qdLh0+fP2Pnrp2o37AB7t+/H2vYvnz5gl27duF///tfiD64ubnJ9E2bN4dI9xPTjmS/aPHiEOlRfeB3YyRMa3yC1aCSMC5WDr6+vli8YRGg1sDPNwAeHt7wENOiGgTASOWHNElT4OG9O1D7+8Dc2h6K6JCX02d4u32Fu9Mn4aXzg1pRoPj7AoGijJEKRmLq1EuMJ1BRQW1kDFNTU3j7usPWIjHevX+OjVtXwFgNTGga5IXb9K8PfufntwXcAyHehm3zluqRGs7goMKQWqbY1tsCJ0ZY4uAgSyxqa47mxY0pG8KDCDFGGefNjwQGDBiATuIPkcKtW7d+NOAUJsAEmAATSJAEbt66iVFjRssH4rNnz45FCxdh6+Yt6NKpMxo3aozmzZph4ICBWLF8BcaPHYeMGTMKIeKBEaNG4v6D2BFx1N8Vq1Zi/sIFGDV6lO68rRRplL5h4wZ06NRRl3702DFQ+oG/D6B6zRqILkeG/+sFsk3zRnPlftGq+XB2coKFmbHwvFnAyspceM4C8eWbG5x8NKiXLhlUCoR3zgpP7t/D0UP7cebsv3j1/DE8XRzh6+4ID8fPcBRTsu6uLvD08BD1KkK4mSDQzwcenu5C1/khsa2CTGkSI2v6FDh77ij8/f1QIKMaye1UcPXS4ParAPzqz28LOPKoeYjBUYPty5hgVWdzVM1jBAdrhZJgbgLkSKVCp/Im2NHHAs1LmEiBJzN5E4KAhzjhjx490qXt27dPF+cIMHHiRIwaNQr0yS32eHDLTIAJMIGYJ3D79m2MGDkS5KEqW7YsZs+chaxZssiO0H3jyNGjOCbEz4ePH2Ra8eLFMW/OXNSsUVMKvuEjRuDL168yLyY379690zX3UO/+du78eV06eem0B1u2fPfIkXjTiClIbV5U7TWeok8BnrI6xTSJ3F+8eh6mwrtkoTJBxiRJkNIhOeysrZE8kT1K5MyDwC8fkDhRMnh4eeDD49vwcP6GJ89e4Prte3DzcEWgtw9IpH389glnrlzBfyKcv3oN3xwdAQ1w79Z1GMELFoH+yJQqJdKlTAoba3OcOHVEtt+5kqncT9/368/Z/5aAm3nQB16+omei2Y7lTNCqlLGIhf+b2EpBp3I/twm/dPzPWbRokXzAsUaNGqAHIXfu3Ck/PcX/kUduhDt27MCmTZvkf0aRK8FWTIAJMIG4T4BEzPCRI4S3xh/FixXHyOEj5D2CRrZ4yWL07tsHc+bOwaw5s9G2XTusW7+OsmBmZoZuXbsif/788BLTgf3695PpMbmxs7PTNVe5UmVdPHOmTLp4lsxBQpQSihQpQjsZaAqSnh2TB1G48b3ZV9amzjIWUJvj9p2rcLCyQMZUqZHJISmyCAGXyt4W2VMmQd4MKZE1eTJ4fn6DVBoXvH7yCLbWJlDZ2OOV40f4GdnAUWMFD5jg4YvX+ODuBxNjczj6ASnSZxJTpr7C8+YPe4fEyKHxE949B1jbJoHaIiks7JPjztMgp02pHEayT6+//PqjU78l4M4+CpANpkuiQo18QY3LhCjYaIQLMuDxfVDQuDhFrkZauut6B5rgEJlCnmK6+q2jBo8+BMLNO0iMRqZcaBuNu5vsK/U38Nvn0NmROt63b5+069atG3Lnzi2FyqlTp2Qab5gAE2ACTCBhEnjw8IH0vNHoRwwfTjsZSKjtP3AA1lbWKFmiJEoIrxtlbNm6Fdu2b6OofO5q1IiRMk6ermfPnsl4TG02bdiINq3boEe37mjdqpWu2enTpqNP794yfZTwLGoz+vXth9GjRsv0lWIqWFEUbVYU7TUI/HxQ1mWcuZPcX7v6HyzNzWjBKFw8ffDBzV1wM4KVrT1MLe1ga5cIXk5fkTZDBqRImxqps+dGvsxpULtUeaROnhze5nbIma84FGML+Hh7Qy28hkaJkuKLpx+SpEwOT5UFrITnzkSlwDJpSrgHWMDJy1K0Z453n77Ax9cHthYKElurQDOaX3/xrR0qOYpf2Lz6GigboiKVchnBTjRO8T8N/vduwaVfJ3xtUBmOPdrJ8LVhVbiNH4JAp29hV+/vhsBHgxFwygKBVwt9D7ebQ+N8KcwyHj7AhrN+aLXEE22XeaLHWi/Um+OJVad80W21FypO8UD7FV5hltVPDPzwDq5DeuJrvYqyr9Tnb01rwWPFfIhJcH3Tn8ZfvnyJjx8/wsbGBvRsQ/369aU9fZeajISz8fX1xZkzZ7B8+XLMnTsXJAI/fw5fQH748AH79+/H/PnzsWrVKpBA9PHxCbN2+tRHbvsNGzZgxowZWL16Na4It7D8brdQJeh5vZs3b4Jc3qGy5Cc/yrt3754uS2tP0wH0xb8nTpzAggULpIft4sWLIep5+PAhqLy2XaqHjmmvq5AjTIAJRESA8+Mogdmz58ieDxk0WAgLUxmnzanTp2mHwYMHYeyYMRg3dhymTZkq02gxnIyIjbWYChwzeoyIAbR6VUZicNOqZUvUq1cPFhYWIVqtVbOWTE+UKFGI9NKlSsn0lClThkiPkgNNIECBKjOypi1o8eD9Fy/x8sMnePlp4AsVAoU/x8fLX3jQNHDz9Ef6Wh3h5+EMB1sb+AYYwV9tilTpMyJ/4cIomsweNhZ2yJAqDWhRSfK06VEmZ1bkSJsEZhaWSG5rhEJ2gNrMCs6+fvjk7ARf4fTxdHeGq9MX3Lx3ByZGkKtRIX7eOoo+in1kf39ZwF19HuR9owaKZVbT7ofg4weQ0PtZ0C/ks2crnAf3hO/d2/rJMu599jS+Na6OgAd35LFu4/UKAZfLQ/NugS5JG9F83YPA62UQ+HyWNknuv7pp0H2NF9af9RVqW5wlmRq02XrBD08+RQ5e4KcPcOrbCT7Xr8jCKnFxKsJlTQeeOzbDeWD3SIu4sWPHggRT9+7dYWJigqZNm8q3OZ89exZv375FWD93795F6dKl0aZNG0ydOlWKsn79+oFc0CS69MUU1U0CjJ6d6Nu3rxR7kyZNQvv27VGmTBmEXqXk7u6ODh06oE6dePJlWwAAEABJREFUOhgj/mNYsmSJfAatcePGaNiwIT59+hSiS5RGf6De4tNHiAxxQJ/4KK9jx47iKOi3UaNGoLTnz5+jcuXKoLw5c+bIZ9yaNWsG4qAVln369JG2np6esjD1i8q2a9dOHvOGCTABJhBfCdCH9Ddv38jhlRLCRkaCN1kyZ0YZcQ8oVrRYcAqQKXhq0tHJSZdGkWxZs9IOL4WzQEZiaEP3EnIEPHjwIESL9P87pV+/fj1EOn1Qp/Rz586FSI+6A3HPFx4yqk9Rm9BOOBk8kUg4T9KnToMsaVIjsaUt/Lw00ASqYGpsjBdvXuHhI+Fcev8airjH2av8kdrKBEnM1bA1CkBiMfWq8fGGolHDGn7CEWMJjZ+fKGsGE08nGAX4widADRd/sRfTfv6BgfD284S7jzs0RkJzPH8o+1EyW5CWOn3PXx5HdvPLAu7e2+8ix8xYCbOdp0IIdRBerJ+FO2+C6gn8+B5ua5ZCIzxKKisrWNRpAIcDp5Bk698wr1EXiqmpbMNlzCBAAJQHAZ4IeNRfHAtRpxhBsSsPVdH7UFfwhirnbsA4lTTTvBwJjctVGafNgqM+eOcU1G6JLGqs7GyBff0t0LGsCSxMwh4LlQsdnPt3QaDjN5ls1bojEh84jSQHz8CiUXOZ5vfkITw3rJDxiDbXrl2TJvT8G0VIxJUoUYKi0mMmI3qb9+/fo3bt2lJIZRZ/xCTcZs6cKcUQPTNAomvPnj26EmvWrJECjLxd5cuXx+TJkzFy5Ej89ddfsg4SZuRepwJkQ4KMvHPm5uZSTM4XHjsSTInEJ6WbN29KYacVVFQmUiEMo0ZCyDmJ/2hIsFH/STDSUuujR49i48aNskSePHlQtGhRqNVqeVygQAF5THuZwBsmwASYQDwlQIJGOzQjIyNtVO5HjRwFCvIgeHP9RpAgsrK0DE4J2tGLZClGgpD2MRXo2b1BQwajb/9+mDlrlq7ZDeL/d0ofNmI4evTqqUu/evUqKH38xAmoUasmyPmgy4yKiEa/EpU8CIQGyR2SIE0SB5iYmAqPmzeMTYzhkNQBSZIkQYoUybDp3BksOnka8HJFgJsz/D3d4OvqCAQEwsYhFb59fC28aEYwUpnBHj5IbuwP+wA3mBoZw9TYBP4mVnASwk/t5wVTIxUU0aZKTA+rVYH49u0D6Cd1YhXt8OJzkD6RB5HYBJWKhKHWxCJIT8lDb+FylJE/2LjPnghNsDCznbMcln2GAcL1qDgkg9WAkbBs11XWHiBu9l67Nsm4xvUW4Pg/GVfsK0BV4AgUS3owUoGSrBbUpZ8DignoR/Ogj3CbBkiP27nHQd7D8jmMMLGxGTI6KLA2V9CipDEmNTYl8whDwO3rCPgc5IWybN4G5m2D+gchQE3yF4Y6aTJZh9dR0b/gccmEMDbHjx8HfUpJkSIF0qZNq7No0qSJjNM7cfS9aRQfPny4vLCLFy8OcpWTgCMRtnLlSjmdqiiKnJL08vKCq6sr5s2bJ+siL9fatWvRUri0O3fuLN/NU6VKFfl8xcKFC6UNrWSiVU30fW70xzR9+nTUrVsX48aNw+XLl2UfyQNHU7CywB9sSATS9OnQoUNB/adpVHoGkKqkcdN+lvijp6lkrft96dKloGOaNqZ8DkyACTCB+ErgZwIu9JivXL2CqdOmwVh4jYYOGRoi21x8GKcEemyF9jEVaHpS29atWze1Uew/sF8X//AhSMBQwpRpQVPAFKexawUcHUdNIHFEQdSmMhYbCMHmiXcfv8BXeNFMzc2QOElSWAiPnJ/w1Ln4eMFPTLmqhEqi/gT6usPbwwVuLk5wc/oMT9dvuPz3Jrx5+Qhfv30SwiwA7s7foFaE5AhURL4rvH08oXawxjezAJiZqmBrBiSxNIWVqTE0igp+wY8x5UwT5KS4/txf9iuyG9G1yJoG2dXIZxwUEdubr4JhiLj+b87UKiztYP5DmChEk9bOzCQo5ivmgCmmiIvMKOP3FSmURsG8cSsoxkFt+j24R0nQvN8g91CMoMr3d1A81FaxyCZTNJ7Cw+XvikvPgsQbJTYoYky7ECFvOrVQx4jwx/vkEZ2NWfW6CPz6GR6zJuBLjVJwHjlAijuVfSKQJxHB06q6AqEi5C2jJBJliqJQVAaaWiT1/+LFC/nsmUwUG5pS/ffff0GCZt26dSIl5C+VI1FHz8bRHy153+jVG+R+r1evXghjRVFAni8SahMmTJCikF7VQUbkdSMRR3FtMBKfAEkkkpePRCF567R5v7Pv2bMn6JkB/bItWrSQhzTuqP/jlVXzhgkwASYQJwhoZx6osz/7//bU6VMYOWoU6P/8mdNnIGfOnFREF+jDPB0YB99HKR4TgZ6/07aTJ09ebRRpUqfWxVMkT6GL58qVSxensSvK93uiLiOqIkKgUVWmahNohCfNx9cfJsZmSGKTGBZm1gjwD4CzqxvefvoEZzdXOQukMjWDqbUZAjX+sEiXB84BZnA1tsYLdy98EtOjtArV3cgSTkIT+Ph5w8fPH+8tffHe1AtWlmpYWZvC2jQQGe2/wc7UB6ksVTAS3j6In3tvAsQWKJAxpKdVJv5ko/pJXphZf6VSwTx4uvHgDT8xmDDNkDW56odwLfj5OWM1kCVZyKYtatQOuyKRapwrj9gCAa+EZ41iGl/aAiZBU6VBB6G2qYTnLThJ4/0R/z36rmyTWCvBOSF3mZKpQyaEceR7/64u1alXe3xrVgueRw4KLWkEdfKUsOnRD4l3HoF5+x46u7Ai9Aepnbp8/fo1NmzYECKQV47K7dq1i3Yy0PQpRVKLPwCabqR46KB9DoLSaeEB7Rs0aEC7H4KtrS1o8QRl0LvoHB0dYWJigkqVKlHSDyFbtmxIJKZSyROo7csPRpFMILEZ2jRZsmRQFAX0jISv8GiGzudjJhDzBLhFJhA7BBTl+31KEyw4wurJzuB7xHgxU0KPxoS20Qo4+hAeOi86j3ds246CBQqiUoWK6Nqli66ppUuWokb1GjJ95IgRuvTJEyehfbt2Mn3enLnyXqDLjIqI8HgBwbojWEOYClFmI+6DUBnBxdkNH785wU0IskChp/yFAPNw9YCHpyecxLSpsZUdTKxsYWJtDX9vF5hofGAd4AdbIfbSiHoS21qLahRoTEzgF+APX+GK8xUeuED4wlJ434TjDYms1UhEws00UDiMzOGQOIkcmVbA5c8Q3D+ZGvHm16yD60tlr8gYLVK49iJAxiPa0MqOfdf8pJmRGJiMyE1QXX5hLGCQ2WIT+P6d2AKKvT3kj8pc7iA8a0GRMLZOF74nGlkjS3K17pj6ojvQi2jfbaeX9EPU5K/vnxICxRSlYmkFkzz5kHjzASTatA+mDYK8SD8UDJVAU5ok4iiZpgrJG6cf7ty5Q1lyqlPr+qYpUUqkT1q0jyho7e213H5SgAQcZZOAo314QeuZc3Z2Ds8kUukkHiNlyEZMgAkwgQRIgDxmFGjoLuJeQ/uwAj1LTLMZ+fLmCysb7z+8l+naD+vyIIY2U6dMwZAhQxD6//t+ffvK9FSpQjphmjdrLtOzBi+8iPJuBskNaAJ8ZNXu/sIZJKSByliFLy6O8HD/Bke3r/CGPxLZ2yFtihRInTQZjNRqPHv/HoFCPKgVNeytrZA4WUqoNCZQBRjD21foICEQTQO8YWZlCX+VCVzVXjBWAmFFekcIOj8/X3xxV+PypyRiajYxzI1M8VeGoAUmQgPK/hiTrYxFbvNbAm55R3OhKINIDNvmjacfw55K1XaBPjzMOhgEjNI6lTOhnQxKsAvR99FDOR0pE/U2flfPw//TR5lilC1YPFkGT7UGOCHw7Y9TiWSscdpDO0AxgWKeGqWzfXdNngpjpcfrb4F4EYkX6ZnX/O7Nsm7XBUn2n4TtnBVQgpW0OMPQeHshoh9aGUo2PXr0kKs99cWbNk6eNnpWTLsoIXny5FQEkRVPGTJkkPa0GlRGfrIhkacoCujTWmBg2OeTPgWSl46qSRlqmXdYZX72WhOqgwMTYAJMgAmETYCmEVu1aCkzW7RsIR9zkQehNqtXrgKFUMnykP7PHjBwoIw3athQ7mNqQ/cEb29vOaOi3yb1idIp6KdTnNLonkfxKA9CeAFCrVHFwQLORnjT3N3d4O7jBS9/f+H108DC1BgqlQJLC3PY2NlAZWyCQKGwfIUog7EFrJOkhp+4R3o5v4ef4gY/aw2sUliL6VFfmFlawVNoOT9ff3iYBQoZqIK3tz80fgEwEd47xcoaEPWYCmEX4OmOrNnyUm9wP3hxaO50wf2TqRFvVBGbhG3RvaKJLqPrGi+M3ukDIU6h0aVCXHCAk4cGXVd74egdf5mTWExf1itkJOO0sZ8yn3Yy0DvfNG6uMk4bzZtXcJs7laIQZGFaLGh1piplWwAK6EfzbDA0LjdENLhlTSACb3YC/IM8RErKoFUu6R0UZA6etl112he3XgXo+kp9nLjHR9QR8a8qS3bQalmydFu3AgHPH4uotm0NXEf3x9daZeH33wmRHvYvecZompBy6Vkwej1GWIFeKUI2e/fupR3o04qiKHj16hVu3KAxy+QQG1p0oJ3epNeEUCZ5++gPg+L6gV5HQosIyBNoYmIin50ICAhAr1699M10cVpEQM/U2dnZgZ7Ro4ykSZPSDmGJRK1IlQZRsKEFH1FQDVfBBJgAE4gTBOjVSiTkqLOnTp+m3Q+BvuCewg8ZAPbu2yeTyftWt05dGY+pzZChQ1CnXl3UrlsH9Py0tt0dO3fI9Doib+CgIHFJec+fP5fpNJaatWsJ/RB8X6XMKAkK1A5NQT+BX8/TDmVLlZdizE144ozFHGeAmQWMrKyE30cNZy834TFzwRcPR5Sp3QeJ7ZNCURQxRWosvGw2UJtbw9jaTkhCBSo/L/gLT5VnoDH8/BW8gKvw8hmLPFMEmNkg0CYx/K3soRJ7s0T2cNeo4SLsLK1s8NVNg3tv/GFsBORJq8av/Py2gKuezwiDaprq2jr/xB9Vp3mg+nQP1JgRFKqJeOMFnngWvDTW3lLB1p4WujIUUf2VG+blK1IUvg/u42ujqvhao7QIpfC1QxMEfPok82z6DoZxoSABB2M7qApelOkIcEXgteIIOG0rgp0IVtA4Br2GQrGuDFW2YAEorIfXMRPboN9BW7xlX6uLvjZd6InnkfC+BZUE7Kcv0kbh2K0NvlYX/a1ZGl+ql4TPpaCpW/d1K3U2oSMdg9+LVrVqVViGWvKtb6t9qe+lS5dA3ixyk08RLmmyodWktKiB4tpA74W7desWKlSoIFeX0qs66OXA9ImmefPmMk1rS560Vq1ayVWd5PGj9GXLltEOhw8fli/vlQfBmxMnToCEIB3qrwLVrp6dPXs2ZekCfR1YVL3PR+tJpEUZugY4wgSYABOI5wQURcHkSZPlKKdNn4aPH4Nmo2RCBJujx45h2fKg/9NbiP//IzCP8uw7d78/L37xUvD9WrSydt06sQ36fcqadCEAABAASURBVP0m6D13dNSz93fHATkSyFNH6VEZjLJ1k9X5Xmks97WrNYCppQUCTPxgYmECC1tLmJqZwD/QX3jPApBEpcbM3FXx4spVGKmBQJUK3n4+8BdTov7CS+fu4QW18LoZWdkJ0WcFPyHinMV0d6AqE1xcvsHHyASBVlbwFl43DzdPeLi5wdPXB188A5E2RxHZh6+ugXJv9xtfivDbAo5arJ7XCPQetbSJg6ohD5zwFMLHHzL4i36J8ZApyuUwwvbeFlAHmco07cZq2ERYd+8TdCg8QBoxQHovnJDgMs2m/zCY1mgg49qNYpsXqqJBq1IBodQDfYBALwjZK02keCtI06iKPKYNeeGWdjCHg/ACavsqPJ30Ohekslcho0MYnaOCoYIq21+wGTgiKFW4UjVibltDy4GFC5YSLes1gv3SIBFJx/qBHs7XLi6gl/jq54WO0xQqvZyXLmTtJxh65QYtJiBRRh62PHnygL7vLkeOHPKbGaiOQ4cOwdjYmKLyk4+ZmZn02NEqn3z58iFv3rzypb/Ozs6gZw0mTpwobak9EnPUHqXRaiaqm8p16tQJ5Klr27atLCsLiM2gQYPEFrJt6gPZ09eBDR48GNQ/mfmHm9atW8saNm/eDBKkYS2AkAa8MSwC3BsmwAT+mECB/Pl1X0XVpl1bLFm2NESdx44cBQX9xFlzZmO2CJTWrUtXNKgf8v5J6dEdLC2+O2uSJUuuay5ZsmS6uPYddZSQOfhFxBRXlO/3bTqOqqByKA6htKRO0Hi+lx619JkyCtGmgrWdClY2GhgZ+cPGzBRZLWzQ0sUUj701ePLqjfCsBcDbxxcWFlZQm5rgm5MTfIReURkZialUFTwDFVIiQvip8N+Fu6inSgcTGxu4uLrB6dNXuH78CuevrvB0dEeAtzea1w96Xn7PJT/QT4vS3x1idByZEDnF8pOarM0VrO1qLsVZl/ImyJlKLa0TCW8bxac3M8OefhYYXd80TPEmjdVGMGvYCkn2nYB1j36wbNJChkSL1iLJ/pMwpefOhPJFiB8FimVmqMt8garIdShpR8mgyrkD6pJvoCr8NyBUb4gi4iBrchU2dLfA5h4WaFTEWIZZLc2xpos53jgKxSlstL8qKKiRprgMJqogQaTNM61eD0kO/gv7mYtlX6nP9qMnI8m+f2DRawgQLKC09tr9+fNBrls6dnBwoN1PA02JkgG9M472RuJiOXjwIEho0TMGNB1LD7HSs2sk9uh9bRkzZiRTGdKkSQNqk14l4iNEJok2FxcXoY016NevH/7++2+o1UHnjArQNzRQmrm5OTw8PEB109Ql2ZAHjESnoihkKkOhQoWwY8cOcVFbyOfnyN5bXJwkAEePHi1t/nRDq2jpBcRUD9VN3kiKc2ACTIAJJAQCrVu11om4ffv2oW79eli8ZDEuitkZ+j/385cvePDwIQYPGYL6DRuA3ulJXLp17Qr6/5PiMR1WrFiJ5MmTI0f27Oit91jOwvkLpBOB0gcOGKjr1ozpM1C1SlVpP3zoMKh+uOfrTP8ook7aUJb3uz5A7gd0GAw7U1MYGwUiEF5IZmuO/okzoZ6jER4+eQyjEqXRqGVjXL1+C96+gcI7B9gkTYWUqVMgZZoUsLCxQKCJEQIVfwQKz9CT1+9hJqZNd+86hhwXn8HV2xdO7q5iqtQZTh8/I9DDExUKFISV8Nx9dgnErgu+MDVW0FZvbYDsWCQ2qkjYRMqEXs3RtLgxFrQ1w4kRltjZ10LGC2VUyy9rjUwlipU1zBq0gEWXfjKos+cErfL8aVkjGyhWOaHKPFoGJZmY5zdNKoooIvz4+8lFA3cfDZLbKeheyUSG/OlU+OauAXkPqURN4VmkvaWxBcaXGCCDtakVJYUIipk5jPIXln2lPhuVrSz6YhPCJvRBuXLl8PLlSxmMwxF5+mVoqvSlsD99+rQumcp16NAB9NJdEmwXLlwATZ2SkNI+k6YzFpFEiRJh06ZNuH37Ni5evCjfLUfPv5GAMzU1FRbffxVFAXnQ6Cu26B1xJP7IY/hQ/OdAU7Nh/VGRcLx58yboWyWofmqHvGZZsmSR46Q0bQtPnjyRadqpV226dv/ixQuZr98vEo/EgV4Mee/ePVBbWnveMwEmwAQSAgEScbRYgRac0Qf2/QcOYMzYMWjavBlatW6Fvv364tbtW/KDNy0yW792Xax43rTnIknixNiwbj3mz5uPFClSaJNBz+PR++ooPVfOnLp0choMHDBA2kfV7I2ucr2ISbGVeKFJi4aP3+Cd2wfY2dijQska8HLzhY2HGjVv+UDz+B1cnJzhITxuTx9/QLb8JeEEB9x7+hpfXTzh5uwKKKZAgAaKygi+3kK8ifgnRxecP3MMfxWqince7rhw6iK6+9nAVgg7c0tjmIgipibGqF+3NehnzUlf2sHB5rtTRCZEchNlAi6S7cWa2QdnDeh5vBaLPbH8RBA0/c7svRLkxqS0irmMaGfwgUQOCTb64wi9TDusztMfDn0iIs8f/bGEZaNNUxRFLlSg/wjI3kh4/rR5Ye1NTEzki3mp/ojqDqt8ZNKoD/TMoKL83sUemTbYhgkwASYAGCYDmlHZvnUb1qxejXZt26JA/gLyFR1JEidBlsxZhKerN9auWYt1ItB9wTBHEcu9UptjiVUzPAoww5TzC2Rn6lduiRapiqDKCwVfvznhg/BofnH6BsVYhfc71sErQIW/yjaGT+L8uHX3Pt59cYSTiwcURQUPrwB4Cu/Ps+ev8c+/l1C5+wb4a0zg6OkJR3c3vLlxDzXfBMDcOxAe3gGoV6sFTEzMcPmpP3ac94WdmK1c29NS9uNXNwlGwKUQHjd6Do8A/XPXHx1XeGH7BT8p5rqt8cLOy0ECLmNSFWixBdlxYAJMgAkwASZgaARSp0qNFs1bYNrUqdi5fQe2bN6MxYsWoXatWkiVMqWhddfg+jOt/CiYqU1w/PVl/P30uJg+NUaBJu1wz8kR7t6e8PH1hZGihp+fP/yfXseda68QCBUSZyoC+wLtcOrMOVy79wj3X37G6y9uOHp4J774pUCZtnOgNrdDgI+PXJnq6eeHc3cf4IIQfenuOqFjpSYoXqAE3Lw0GLXFS3JpUkI4P6x/zymRYAQckepZ2QTZU6opipdfA7HilC92XPLDk+D32KWwU2GS3td9SUPeMIFYIMBNMgEmwASYQPQQsDKxRLuc9WXlA09Nwwvn17ASU751ly/Fq7QpECD0lFqlwFStwMbCHNcmdYbjVw+YmqqQMkNyfDApim+WhfDfjTdwM/8Lf9VdiNSF6kIjplP9hXi7tW8JLAJ8YKJS4YurKz66uiFfjTqoWLuRbLPtQg98ddMgkZWCblXEvKpM/fWN6teLxO0Si9uZYUZzM5TJboREwnVpbabgr1Rq9BDiblkHMySzFWcubg+Re88EmAATYAJMgAn8hMCAol1QLX0JadHp8DB8cv+MRA5J0XTCBDzKnh6vVRpYmlnCzsICyVxe4cnVWxAONfh4OiGFgwVS2gPpSrfGpVuvQatR3dy84eHmg89v3sH0xTVYGBvDR/jt3AM1aDRmNEp37izbGrnFGy+/BILWDazvbSnTfncTjoD73eriRrmCGdQY28BULrTYN8ACC9uaoWFhY1gJMRc3RsC9ZAJMgAkwASbABP6EwILKE5HRNjXeuH9Cy4MD8NjxOeyFiOs0bhLStm6Otw62CDQyhqW5Ffx3jIeLiz+ePf6EN2894aZOCw9XdwT6+cLM1BRGRiooigL3fzfBSuMNRRznKFIUs06dQPmWLeHi44oJ/67BoTtf5DdZre5piVSJVPiTnz8r/Sctc1kmwASYABOIfwR4REwgDhE40mQ9qqYrgdduH1Brd2csvbYexubmqNCoKVosWoQ0bZvDTEyv+n57g0fbl+DKuauwNFHB38sLFmamSJ0mDTQBAVBrAvHx6hFo3t9A1uLF0G/1aozdtxdps2fHa5d3aCUE4qbHm2GUYRaWdLZAmuD35+IPfljA/QE8LsoEmAATYAJMgAnEbQILq0xEi+w15CDmXt+AnsdG463reyRK4oAqnTqj+6EDaLdsKXI5OMPByh+JhGfO0+0rPNy/IpGdCczV3khh7IjGZVNg3pkzGL9vHwpXrw5XP3fMv7oaDfd1xyPHF0hp6YDdTQcjdzq1bOtPN6o/rYDLMwEDI8DdYQJMgAkwASbwSwTGlR6IsSV6IYVlEhx/dR4VtrfGyH9n4vanezA2M0O28mXRbNxYzJzQAVOHVMeUQTUwZ2RdTB1aB8O6VUDPnnVRq1tPpMySBU7ezlh4bS0qbmuFxTe2wMXXA/UzV8T+hiuQVkzZ/lLHfmLMAu4ncDiLCTABJsAEmAATSBgEWuasj/U1ZqJK+pJywDsfH0GjA31QclMjjDg9HfueHMPjb8/wxfObzKcNxR9+fYKzby5J0dZify8U3dgQC69vgpufJwoly4n11adhevkRsDW1oSJRFljARRlKrogJMAEmwASYABOIywTS26XFosoTcLLpRlTPWAaprZLhi5cTdgnxNkSIuFp7uqDk5ibIurKiDBSvs7cbOh4ZIUXb1c8PYG9qjQJJc2BDjenYUmcBiqcuHC1IWMBFC1aulAkwASbw6wS4BBNgAoZBILVNSsyvOBYnm2/Bkopj0DVPExQU3rTMtmngYG6n6yTFswjRVyh5LlRKVxLbas/F6RZbsa3uIhRLVUhnFx0RFnDRQZXrZAJMgAkwASbABOIFgUoZy2Jg0a7YKrxph5qsw7lWu/G48wkZKP6/xmuxpfZ8LKkyAQWS54G5kXmMjJsFXIxgjiuNcD+ZABNgAkyACTCBuECABVxcOEvcRybABJgAE2AChkyA+xbjBFjAxThybpAJMAEmwASYABNgAn9GgAXcn/Hj0kyACRgGAe4FE2ACTCBBEWABl6BONw+WCTABJsAEmAATiA8EWMBF1VnkepgAE2ACTIAJMAEmEEMEWMDFEGhuhgkwASbABJhAWAQ4jQn8DgEWcL9DjcswASbABJgAE2ACTCAWCbCAi0X43DQTMAwC3AsmwASYABOIawRYwMW1M8b9ZQJMgAkwASbABBI8AYMQcAn+LDAAJsAEmAATYAJMgAn8AgEWcL8Ai02ZABNgAkzAoAhwZ5hAgiXAAi7BnnoeOBNgAkyACTABJhBXCbCAi6tnjvttGAS4F0yACTABJsAEYoEAC7hYgM5NMgEmwASYABNgAgmbwJ+OngXcnxLk8kyACTABJsAEmAATiGECLOBiGDg3xwSYABMwDALcCybABOIyARZwcfnscd+ZABNgAkyACTCBBEmABVyCPO2GMWjuBRNgAkyACTABJvB7BFjA/R43LsUEmAATYAJMgAnEDgFuVRBgAScg8C8TYAJMgAkwASbABOISARZwcelscV+ZABMwDALcCybABJhALBNgARfLJ4CbZwJMgAkwASbABJjArxJgAferxAzDnns5E/kAAAAQAElEQVTBBJgAE2ACTIAJJGACLOAS8MnnoTMBJsAEmEBCI8DjjS8EWMDFlzPJ42ACTIAJMAEmwAQSDAEWcAnmVPNAmYBhEOBeMAEmwASYwJ8TYAH35wy5BibABJgAE2ACTIAJxCiBBCjgYpQvN8YEmAATYAJMgAkwgSgnwAIuypFyhUyACTABJhAvCfCgmIABEWABZ0AnI6a68unTJxw7dhyXL1+JqSa5HSbABJgAE2ACTCAKCcR5Aefq6ooWLVujbLmKKFS4GEqXKYehw4bDx8cnXEzv379Hy5ZtUKZsBRQuUlzux44dD39//3DLxKeM69evo2u3Hpg5a3Z8GlZCGAuPkQkwASbABJiAJPBHAu72nXsYOGQkvnz9KiuL6c0//5xAseKlcOHCRbx+/Rrfvn3D27fvsGPHLpFeEi9evPyhS+vXb0ClylVx/sIFvHnzBl9F32m/YeMmlChZGu/evf+hDCdED4HGjZuhfIVKePbsWfQ0wLUyASbABJgAE4inBH5NwOlBIPG2aMlyfHN0xImT/+rlxEz06dNn6N6jF7y8vNCqVUucPnUCly9dwP8O7kfKlCnh7OyCBg0bwc3NTdchEnpTpk4XZbzRpUsnnD59ApcunsO+vbuRJk0afPnyVXjmWuvsORK9BN68fYuXL1/B19c3ehvi2pkAE2ACTIAJxDMCvyXg7gjP20Ih3nz9/FC8WBE0alA3xrGsX79RTnnWqlUDEyeMQ7p0aeHgkAR//fUX/jl+BDY2NlLEXblyVde3NWvWSbHQuXNHDBs6BOnSpkXSpEmRN28e7Nm9A0ZGRnglPHnnzp3TleEIE2ACTIAJ/DkBroEJMIGoJfDLAu7O3fuYv3gZ/Ei8FS2Cju1aS+ETtd2KuLZx40Zj964dmDJ58g/G5ubmKFiggEy/dOmy3NNm2bLF2L5tM7p36wpFUShJF5IkSYJKlSrK45MnT8v9zzZXrl7FiRMn4eTsLM3u3r2LqcK717VrDwwcNAQ7d+6CRqORefqbgIAAWY7KUj5xXLZsufQmDho8FO7u7vrmeP/hg3xWrVevPujWrQcmTJyMe/fuhbAJ72DP3n0YJPrSpWt3TJkyDXfu3A02DTl2SqRnCalP//1EvN64cVP2/e27d1Tkh+AovLHz5y9E7z59QW3Sc4XnxfR2aMOTp07Lejw8PGTW2f/OyWNqn6bBZWLwhjyoq9esRc+evdGlSzdMFOM/c+ZscC7vmAATYAJMgAkkTAK/JODu3XuAeQuXSM9XsaKF0bF97Ig3OlVqtRoFCuSHtbUVHf4QAgMDZJqxibHc04bKFClSBPb29nQYbjAxMQk3T5sxefI0dOrcFY8ePcLw4SNRr34jrFi5CseOH8eePXsxZOhwlC5THrdu3dYWkXuaLqRyFO7euw96hm/6jFk4cuQodu/eo5vypQUVI0eNRtmyFbBkyTL879BhHD12HGvXrkOdug3Qtm0HeHt7yzpDbx4/foyy5Spg4MDB2C36cvz4P1i5arXoY0Mp6IyMvzPRln358qUcz+DBw7RJP+xnz5kjbU6f/jdEHgnR2bPnokTJMpg3fwEOHjwEapOeK2zVqg0aN2kmBb+2EAlRGr9WrJLwpWMK30UmpKijcUyaNAWHDh/B8X9OYI0Yf7v2HdG6TTsEBgZqq4zEnk2YABNgAkyACcQfApEWcPfvP8Ts+YtAHqSihQuiU/u2seJ5iyz6W7fvSNMypUvLfUQbFxcXnD37nzSrU6e23EdmM3nyVGzbvgNFhTBcuGCe8PBtwfTpU/FXjhx4JzxVLYWAoQUWYdXVpk1b6XFr06Y1hg0bgvr168E4WFyRB2vLlm0wNTVBt65dsH7dGmzZvFGIxaFInDgxzpw9iypVq//g5aNFGSQmX79+g2zZsmLatCnYsX0LFi9agBIliktBN2fO3LC689tpo0ePxaLFS0R5DTq0byf6ulr2ddTIEUiUKBGuXr2GylWqi/yg31YtW6BN61YwMzOTCdWqVpHHlJYqVSqZ9uHDR+HJ6wcnJ2fUq1cXGzesk2zHjBmFlClT4D/htWvTtr205Q0TYAJMgAkwgWgjYKAVR0rA3X/wEDPmzJcej8IFC6BLp/ZCvKkNdEjAzJmz4ezsjCRJEiN37lwR9pM8SPPE1B9N6WXMmAE5cmSPsIzW4O7de+jYoT02blyHWrVqokiRwmjSuBF27doup2Spzs6du2nNQ+xdXd3koovx48aga5fOmDN7puhzEqxevRanxDQj9X/P7l0YOnQwypQpjeLFi6FL5044dvQwsmTOjDdv3qJb954h6mzWvBVoYQfZ792zC02bNEbhwoVRo0Z1bFi/Fp07d8TDh49ClPmTA1oJvHnLVinG1q1dg9GjR4q+lpF97dixPY4e+R+srKzkKmHte+dIhI0fPxa2tray6T59eoGOKWTJklmmnTt/Xo6Dnk+cO2cWSpUqKdm2b9dWMDuAcmXLSGErjXnDBJgAE2ACTCCBEVBFNF7yvM2YPV9nduXadXTs2gvtOnWPVKDFDrrCMRA5JKYaly1fIVtasngR6Hk4efCTzabNW7Bu3Xrh/TLC7Fkzf2L5YxYJPhJYKlVIlNTu1CmTQOlPnz3Dhw8ffii8etUKZBZCLHQGCSJKmzB+HLJmzULREMHOzhZr1qyUaafFdCYJUDqg58VevnxJUZDooT7Ig+CNoihy8cZff+UITvnz3foNG2UlXbt2RrFiRWVcf0PewvXCe7h71w4pwPTzfhZXq4J40ph8fHxDmJLwW7t2tRR1ITL4gAnETwI8KibABJjADwSC7pI/JH9PcAv1UP33HMOLXbh4Eb1695Wewl69egjPU6EIO/m//x3CmDHjpNAa0L8f8uXLG2EZfYO2bdsI4Wesn6SL08KI6tWqyv5sEV4qXUZwhDxjwVHdjhYIvHjxQnqnKleupEsPHaGpRlpFS8/U0XQi5e/avUdOcZcrV1ZOXVJa6ECCsrHwEIZO/51jEo5ar1rLFs3DrYKeVcyfP1+4+WFllC9fTq4Qfv78BSpWqgISivTqGGozLHtOYwJMgAkwASaQkAhEKOCKFimE7l06QvtTpVIFrFmxGOtWLY1U6N2jq7ZotO6v37iBFi1ay2fCmjRujP79+kbY3j8nTqBP335yRWrnTh3Qrduv95VE1M8ayl8gv8x+EMa0pZHRj9PQz589l/bk2aPXmsiDMDaKoqBo0SIyh75ZgSJ3gp/7KyGmWuk4vJA+fbrwssJODyf1y5cv8rUs5BF0cHAIx+r3ku3s7LBr5zZkz55NPks4btwEVK5SDQULFcHcefPx8uWr36uYSzEBJsAEmAATiAcEIhRwNEatiFMUBcf+OYntO/dIrxLlGUKglZ4NGzaRXalfry6mTZssPWoyIZzNv/+eQdeuPYTgAzp16ohhw4aGY/nz5Ig8QprglZJqdaRQi34HibqI6qVeBQSvtFWrg8po9wEBgZQdbtAEasLN+1lG6HKKEjSm6FoNSi9XPnzoIHbu2IaaNWqARK2zswsWLFgkxRx9n+vP+st5TIAJMAEmELsEuPXoIxB0B45E/STiunXuAJVKhaPHT0gRF5FQiES1f2xCr52oV78hFEVB7do1MWfOLBn/WcU05dixUxch3jTo1LEDRgz/PfFGbbx4+ZJ24YbLwS8SzvnXX+Ha6GdkzpxR9p+mDml6VD9PP06i6crloJcUFypUUGblDZ7+/dm73MiQ6qa9flAURR5SvTISxsZJiCf9ZAeHJHLxAi3GCOsZP33bP4nT+BYtmo8T/xzD+XNnQR5Ges0KTZf/Sb1clgkwASbABJhAXCUQaQFHAyQR16VjO6jVQSJux649CAj2MFF+TId79+6hTt36UvBUq1oVC+bPi7ALFy9dQvsOHaUHkV55MWLEsAjL/Mxg7dp18PHxCdPk48eP8n1oauEha926VZg2oROTJ0+OLFmywNXVFYcOHQ6drTum5+Rev3kDU1NTFCtWTKY3a9pEnBs1zp07j0+fPsm00BsShTt27gydDEtLK5kW3rvlvLy88f79j98TW7JkCVluw4ZNch/W5vnz57h+/QZ8wvnKrLBEI62k/ffMGdDrXfTrTJ48GWgBAzGllyDT61L08znOBEIS4CMmwASYQPwk8EsCjhDQC3w7d2gnhQJ54nbs3C3FEOXFZLh//z5q1a4nxVuVypWwZMnCCJun95G1bt0O5Dkk8TZq1IgIy0RkQK/yoG85oK8V07f19PRE3379ZVK2rFkjfHmwNAzetGzRTI5r+IhRePz4SXDq9x29661J0xYyoUyZUnJPG3pmLkOGDBQFvRSXXmEiD4I3JHgmT5kaZp30HJuiKFI4Hv/nRHCJoB0JrEaNm/4gpiiX3t1GYmr5ipXy3WyUph+or7Xr1EfDRk2wfdt2/SwhPoNemPzkyVNdunbqmLxr7dp1xKDBQ+RzdjoDEaEvuKD3EYooqN+058AEmAATYAJMICERUP3OYINEXNvg6dST2LPv79+p5o/KdO7STZZXFAX0FU9Fi5ZAWKFatZrSjjZDhg4DTb2pxDTw338fDNOe6mjQsDGZRypkyZIZ9I0D5ctXlN428ght37EThYsUx+XLV0HvQNu+fUuk6tIa0Yt9q1evJr9poWq1Gujbtz/u3buPZ8+egb7xgOqmr61KmzYtVixfpi0m90cOH4S1tTXo/XQFCxWVLxl+Izx1p06dRoWKlUGeshw5fnyNCL1wt127NrKOrl27Y8bMWXj58qV8CW/5CpXw4MEDZM6cSebrb8qUKY2OQtBTGn07AglHapv6unjJUsmBxGy6dGlB4yI7bShcqLCM9h8wCNpA3+BAiWNGjwR9I8Y//5wEtX/+/AWQR5P6QWKSbOgbNWxsbCjKgQkwASbABJhAgiLwWwKOCJGI69qpvbzJlizx4/u/yCYmAnmHPn/5gvDCl69ffugGeW/Cs6d0x2+OP5QJL2H4sKFo2bIFPn/+gi5C+JQtVwHDho0ATQHSdOjZM6fli2zDKx9e+uJFC9Clc0fJ94AQm7Vq10WlytXkNx6Qx6tQwQL493RITxnVRXmXL51HihQppOdq+PCRKFO2Ajp07CwE0Ce0EN698eNGk+kPYcjgQfLbG8gLtnTpciGcKsuvwfr06TNmzZohnz37oZBIGD58GOgFvjSde+LESdSuU0/2ddasOcJTq0KuXDlx+tSPfZ01azqyiuliRVGwb99+Geh8iiqRLl06IYiPIKmDg5i6/QD6RoviJUqjRs06Qszeg4NIv3L5AplyYAJMgAnERwI8JibwUwKqn+ZGkEnPxK1YMh8pkiePwDLqs8/9dwYvnj+JMFy7elnX+MkTxyO0pzpPhyGMdJWEivj6+mHSxPG4c/uG/MaEatWqoHv3rjh86CAunD/7wxQfvVyX2qBAgidUdSEOSRg9fHAXixbOR/NmTUFf8TV50kQ8engPO3eGnI7UL0hfUXX+3Bn8c/wIevbojlo1anzhNAAAEABJREFUa2DG9Gm4eeMqqDy9f47ap9WdocsdOfw/nPjnKAYNHIBqVauAvh7s3t1baFC/HsaPHyf50Vdh6ZejePt2bUF9XbVyOVq1agn6VoqJE8bh7p1b+PvAPjIJMxw9ekiyW7lymRBwe1CtWlWdXdo0aXBJiNED+/eCppXp3XAkas+JsZFIJbGqM+YIE2ACTIAJMIEEROCPBFwC4hThUEk0devaBUuXLIbWkxVhoUgYKIqCmkKATZkyCfPnzZEetMgKl4wZM2LQoAFYKARg48YNYWlpGYkWASrXs2d3LF26WAqxyLZHlVesWAEk3Ej4kZAjLpT+s0D9qlSxIvLmyR2mGX0d2iQhXNesXgkStbHxgSHMjsX3RB4fE2ACTIAJGCwBFnAGe2q4Y0yACTABJsAEmAATCJuAIQu4sHvMqUyACTABJsAEmAATSOAEWMAl8AuAh88EmAATiH8EeERMIP4TYAH3m+eYFhX079cnzFdr/GaVXIwJMAEmwASYABNgApEiwAIuUph+NGratDH69OmNTJky/pjJKQmeAANgAkyACTABJhCdBFjARSddrpsJMAEmwASYABNgApEnEGlLFnCRRsWGTIAJMAEmwASYABMwDAIs4AzjPHAvmAATYAKGQYB7wQSYQJwgwAIuTpwm7iQTYAJMgAkwASbABL4TYAH3nQXHDIMA94IJMAEmwASYABOIgAALuAgAcTYTYAJMgAkwASYQFwgkrD6ygEtY55tHywSYABNgAkyACcQDAizg4sFJ5CEwASZgGAS4F0yACTCBmCLAAi6mSHM7TIAJMAEmwASYABOIIgIs4KIIpGFUw71gAkyACTABJsAEEgIBFnAJ4SzzGJkAE2ACTIAJ/IwA58U5Aizg4twp4w4zASbABJgAE2ACCZ0AC7iEfgXw+JmAYRDgXjABJsAEmMAvEGAB9wuw2JQJMAEmwASYABNgAoZAgAWc9izwngkwASbABJgAE2ACcYQAC7g4cqK4m0yACTABJmCYBLhXTCA2CLCAiw3q3CYTYAJMgAkwASbABP6AAAu4P4DHRZmAYRDgXjABJsAEmEBCI8ACLqGdcR4vE2ACTIAJMAEmEOcJRImAi/MUeABMgAkwASbABJgAE4hDBFjAxaGTxV1lAkyACcQzAjwcJsAEfpMAC7jfBMfFmAATYAJMgAkwASYQWwRYwMUWeW7XMAhwL5gAE2ACTIAJxEECLODi4EnjLjMBJsAEmAATYAKxSyC2W2cBF9tngNtnAkyACTABJsAEmMAvEmAB94vA2JwJMAEmYBgEuBdMgAkkZAIs4BLy2eexMwEmwASYABNgAnGSAAu4OHnaDKPT3AsmwASYABNgAkwgdgiwgIsd7twqE2ACTIAJMIGESoDHHQUEWMBFAUSuggkwASbABJgAE2ACMUmABVxM0ua2mAATMAwC3AsmwASYQBwnwAIujp9A7j4TYAJMgAkwASaQ8AiwgIudc86tMgEmwASYABNgAkzgtwmwgPttdFyQCTABJsAEmEBME+D2mEAQARZwQRx4ywSYABNgAkyACTCBOEOABVycOVXcUSZgGAS4F0yACTABJhD7BFjAxf454B4wASbABJgAE2ACTOCXCMRBAfdL42NjJsAEmAATYAJMgAnEOwIxIuA0vr7w//oFfm9fw/flCw7MgK8Bvgb4GuBrIOavAWbOzKPoGvB7+wb+jt8Af/9YE4bRJ+ACA+H/+ZO8WPzevUWgmxs0fmKgGg3AgRnwNcDXAF8DfA3wNcDXQBy9BjR+fgh0cYHvmyDHlP+3r0HnMgblXLQIuAA3V/i+foVAD48YH1AMsuOmmMCvEmB7JsAEmAATiG8EhAgNdA3WPV6eMTa6KBdw/l8+I+BrzCvRGCPGDTEBJsAEmAATYAJMIDQBmnn8+BEBTk6hc6Lg+McqolTA0XNuge7uP7bCKUyACTABJsAEmAATSAAEApydQCG6hxplAo6ecaMQ3R3m+pkAE2ACTCDmCXCLTIAJRJ4AeeE03t6RL/AbllEj4MhtSKsxfqMDXIQJMAEmwASYABNgAvGNAC3klIs2o2lgUSLg/J0cASHioqmPXC0TAMAQmAATYAJMgAnEHQKagAAERONjZVEi4DSeMbfqIu6cOu4pE2ACTIAJMAEmEOsEYrEDgW6u0db6Hws4ekmvJhZfZBdtZLhiJsAEmAATYAJMgAn8AQGNjw+iSyP9sYALjMF3nvwBQy7KBJgAE4gtAtwuE2ACCZiAxtcnWkb/xwKOPHDR0jOulAkwASbABJgAE2ACcZyAwXrgePFCHLiyuItMgAkwASbABJhA7BDQaKKl3T/2wEVLr7hSJsAEmAATYAJMINYJcAcMlwALOMM9N9wzJsAEmAATYAJMgAmESYAFXJhYOJEJMAHDIMC9YAJMgAkwgbAIsIALiwqnMQEmwASYABNgAkzAgAmwgIvg5HA2E2ACTIAJMAEmwAQMjQALOEM7I9wfJsAEmAATiA8EeAxMIFoJsICLVrxcORNgAkyACTABJsAEop4AC7ioZ8o1MgHDIMC9YAJMgAkwgXhLgAVcvD21PDAmwASYABNgAkwgvhKITgEXX5nxuJgAE2ACTIAJMAEmEKsEWMDFKn5unAkwASbABH4kwClMgAlERIAFXESEOJ8JMAEmwASYABNgAgZGgAWcgZ0Q7o5hEOBeMAEmwASYABMwZAIs4Az57HDfmAATYAJMgAkwgbhEIMb6ygIuxlBzQ0yACTABJsAEmAATiBoCLOCihiPXwgSYABMwDALcCybABBIEARZwCeI08yCZABNgAkyACTCB+ESABVw8Opuv371D4Tp1cfDEiRgb1fItW2SbF65f17bJeyYQbQS6DBsurzdfP79oa4MrZgJMgAnEBQIs4H7hLFVs0RJ5q1fXhaL16qNWh46YumQJPn75+gs1fTf18PTEldt38M3J6Xvib8YCAwPh4uaGmLy5+fj6yjb9/QN+s9dcLDwCdF3ce/IkvOxIp7u6u8tr7O2HD5EuY6iG7uLvha5xaDSG2kXuFxNgAr9NgAv+CgEWcL9Ay9vXB17ePiiYKzeK5M2HLOnT44ujI9bu3IX6Xbrg1v0Hv1BbkOmTl6/Qsm9f/HflSlACb5lAMAG6LoZPnxF89Pu7B0+eymts8/79v18Jl2QCTIAJMAGDIsAC7jdOx4JxY7Fy2lRsmjcXF/bsxsiePeHs6opBU6bAV3ikQlfp7uGJD58/C6fBr3sN/P398f7TJ3h7e4euNsJjV+GN+yQ8g+SZC8/YR/T33ceP8BPthGdD5akPTi4u4ZlEeXpQvz4Jnn6/VLenlxfeh2JN/f/05Qs+ff0KiodXoaOzMz4Lm/DyfyVdIzxEVN87ce78A8L3TpKNcxRx/SjGSB7dX+kn2QaI/tE1EJnzSx4wupapDJUNL1A/3n38JK758CwgPgx5443wCrp7eIRrRO1QPXRewzWKwgyuigkwASYQVwiwgPvDM6VSqdC2UUM0rF4Nr969w4nzF3Q1Pnr2HA26dUeBWrVQtmkz5K5aDSu3btPl1+/aDc379JHHg6dOQ8lGjXDqQlB5uqlNXLgQ+WrURLlmzZFX7LuNHCmFoCzwk42JsQl6jB6NQnXqonSTJqjati0u3rgRogSJmd5jx4np4Boo37wF8lSrjnFz54EEo77h1gMHQFPF1Afa1+ncGTfv39c3CRGn6duh06ahdOMm2LBnjxRMNK5KLVuFsHv34aMc767Dh3Xp1I/py5Zh8YaNgllt0a/mKNaggfBw7tTZhI6QJC7fvLmsa9W2bXLM5QRrEhBke/zsf6jUqpXg0FT2qYKYBj/y7xnK0gUSPq37D0Cx+g1QSvSbeL0V/SvbtCmoTjL0Fp5XGsecVavoUBcWrF0n237x5q0ujc57k169ZH3lxbkrWKu2PO8k6hD8c/HGTRATarOImIqv0roNrt25K3NPnj8v66SDh8+eyTj1j47DCgeOH5fnqEyTpshfsxaa9+4jr0WyHSvOKV03FN+y/4CsS3sN0rletnlzMOsWso7GPXrg0fPnZC7DRyGGadx//3MCI2bMBI2FrmU6V8fOnJU2tNH2c832HRg6fbrsB52XEuL8nRDjIRtt8PHxAfWrUO06oMcSCop9rzFjhXj+pjURwk+DfUePoXiDhvI6KCAYjp8/H3Y2tjobjjABJsAEEjIBFnBRdPZrVawoa7pw/Zrc03M6jcTNkEQdCbyxffsge+bMmLliBf538qS0yZYxI3JlzaoXzwobK2t5TOJt4569KFesGMb16ysF4qkLF9FT3OikwU82o+fMwePnL0SZ6ihbtKgQfV/QbtBgPHnxUpYiLxTVc/rSJTSoWhUTBw5AmSJFsEWItUGTp0gb2mw98Le80VpaWMi6aleqiJdCqLTo2w9v3r8nkxCBPE0TxE1237HjqFmhAtqImzcZfPnmiK9iqpni2hAQGABK99bzLJLNtr//xtpdO1GheHEQUzNTE0xdshQbhRjUlg2xF56ur45Osq55a9aidOHCqFy6FNRqNc6I8fUaOxZGaiP0bNMaAzp1FHE1+k2YgOt3g8SSh5cX6nXpisu3bolp8bxoVb8e7K1tUKN9e/lco4enl2xOA41sg7ypMiF44+7pIdMDAvxlyjvhzawrptOfiqnxVvXqYWTvXsieKaM877uPHJE2bsLj1GnoUEBRZJ/6tGsLek6NhJan4GFjbY1cWbKCfizMzeU1kjl9Ojr8Idx7/Bgk/tOnTo3RvXujY9MmoOfm+o6fgEDBJk2KFMiQNq0sl8jWVtaVNEliiCzMW7MGc1atRpJEidCgWlV5rdx++Ai1O3YSYuqrLBMQGCjHN27ePJy7dg11K1dCpZIlZX97jxuHq7dvSzs691/EeV4qBOF/l6+gTqVKqFiiBJyEZ7r7yFF4+uqVtKNN+8FDsFVca6WLFMboPr1B1yB9cOk5ZozsM9mQiB0iPgiQZ7ha2TKoVqYMDp44iUs3b1A2BybABJhAgiegSvAEoghA6uTJZU2OwdNhbu7uqFm+POaMHCGnWFuKm/mG2bOlzbj5C+R+2tAhGCk8NXTQSdx4l4sp2IK5c9EhUidPgU7CA7Rowni0qFsXUwYPljc68nQEiCkvaRTOxkiIl93LlmLqkMFyqnd4j+4g0bZmxw5Zgrx7ebNnR38hUqYIm6bCQ7hk0kQ4JE4kb9JkRG2MF2LMxMQEf69eJeuaLTyAvYQ3L4m9PW4/ekRmukA3+mlCaO08dBgt69XFsO7ddHm/EvEW3pnlkydj4fhxmDNqJIiZqegDPWcYUT3EavmUyVgsBJq5mRlmCLFM+3WzZqKvGGu3li2xavo0yWLpxk2yuovXb8BRTJ2S6NskpsTHCI/otkULkUOIbekxI6UjLSO3WbppM1RCmK0S4mOMEO1thYjdIjgqioJRM2eBhM7zV69Bnsq2DeqD+kRMl0ycgPH9+yEwIBCFcufG8qlBQjptyh9CQl0AABAASURBVJSg62Js375hduDs1atCjGkwXJzj1qK+od26YZa45vq0awc6h52aNcXQrl1l2Wrlysq66lauLET9J6wQ3uDkDg44vnEDpglBuXLaVMwdNUroSkUKd1lIu1GAbQsWYMbw4aBrZbZog/gsEt5SrYl2f3TDetmHpZMngdgrigISzWT/5MULXL1zB41r1MAycZ5b16+PqeLvoFmd2rj14AFuCGFNdjOWrwCd943iw8gCIRTnjR2DAytXgsSvth3eMwEmoEeAowmOAAu4KDrlfsGrMMnbQ1WmFp6PyYMHIZUQdvSKjfPXruP56yAvBD2bRoKK7MILvYVXhjx35Ck6KzwaNG1JN1ua9nr38VN4xWR6SyH4bIUXRx6Ijfb4QvA0Knl4yPNRqVRJ6Xn6T4iA+8KTkzFNWiksRBHQM2jUxyqlS8Ha0pKSZOjSvBnO7NguxalMCN4sF54XmjLNkSkTSAQFJ//yjrySBXPn1pXLnD699Iy9FZ4t6pMuI4xIoTx5dKnU92evXsPYyAj7j/8DElYUDp/+F2ampqDn5Mj4+NmzENoE40IJpGnDhIeMDH4hkPDYL6YzaVr9svDoUXsUSChZCS8mecRo+jDvXzlgL7xhExcuAnk8qQ/2tnaoVrYsrCwtfqFFoFnNmjASY2wmpk0nifrOXL6MnMKrW754MTn28CojzzDlkZij/lKcQo0K5SUfmvYkkUlpFKqXLYcUyZJSVIaKwguXNHFi0AcKmRC8yZUtmxjD9+ulaL58sn/kEabztyl4IQUJfmKjDd+cnGUND8SUMXlUX7x5g0zCc5grW5AnkjKpfQfRJsU5MAEmwAQSOgEWcFF0BZBngaqimxrtvcRUWL8JE8VUXAf0GDUaAyZNQpOevSgrUmG/mIakZ41a9esPmkqiKdDFGzcGl9UE78Pe6QsgrUWyJElACy3omMTN3NWrUalVa3QcMhRDpkxFS9HOpZs3KVuGL9+Cnkcqlj+/PI5oc014TqytLHH/6VOcE4IwIvvw8jOl/XGqMGuGDNL8a6hpWJmotyHPo/aQxkoeKBK8+48dg35ImTQpUohAtl8cv4G8jDSNSMfakD5VKugLG236z/YkUCgEagJDtEdtO4hpyoxp0kBRSC5CeJNWoFShQmJK8CZourNqmzboMnwESOD9rI3QeXZCCG4R05t5hEf10KlTsg567m7K4sWg8xzaXnusfW1NwWCPrzad9lqOfnrvWsuRORNlhQg0bevh6alNk/s82bPJvXajKIr0SEL8kPfxnRDiIoqL16+HYPRQXDfEh8S1tk4SuWSrH4rkyat/yHEmwASYQIIlwAIuCk49eRPomR6qqkrp0rQDPYB99MwZ9GrTGjcO/Q8X9+7BtYN/y7ywNvqSjMQHPQhOwuX6/w6CVrreFHW0rFsnrKI/pNGzX/qJdCOnG6dWXJ6/dk16pCqWLIFbRw7j/J7dso/phGjRlkseLHBOnDunTZJ7uqnTs050M5YJwRt6Zo2mCunZs9Fz5oKEU1CWIkWL/vgoXeu5CT1DSc9vUb5+uPXgoRRTycR0n376z+KJ7OykByrvX3/hyIb1IcLfq1fLqVQqn0pMVZPoCv1M3/3HT0IIIEVRyFxvXPIQtMqXYjQ+Eh+W5uZIJLxpodvct3KF7AM90wbxk1hMQ6+eMR1nd+6Q1wU9q0jesx3/OyRyf+33r6xZsH3xInkez+/aiczp0mH97j24Evx8mq426mTwQVIh6ClK3l3a6wc/f3+oVSopbLXp1+/e00blnryNj8V0qL6nlzKu3LpNO10gO7r+KIG8oRmFl5fic8aMljy0nA6uXYPD69ehUfXqsLG2IhP5ih4ZCd5QXf9evhR8xDsmwASYQMImEH8EXAyeR0/hXaPXGtDzOLSCscvw4aAHvEsKj0qhPEHTf1+cHGWP6EF8GRGbl2/fiW3IX2sxtUYp1+/cBQlB8ho5OjtL8VAgVy45nUX51N7pi5G7ea3fswfal7ZSnbNWrgQ9rE8LIqguZ1c32qGomN6i57XogF6zoZ1Wo2OaCqYbLi2ceBc8ZUtia9Ts2XIl4/9OnCQzXWhZrx5o+rNn69ay7cnCA0SZKpUCepCepuNc3dwpSYqgOavXyHjozfPXr3FETHPSzZrCpZs3cfXObZB3RusZCl0mvGNaNEJi9ea9oFWzpF8uXL+BvDVqYO2OoJWttSpWkMXJC0bChQ6or11HjaKoLpA4I/FF09CUTxnvhDfp1MWLFNWFprVr47PwXu7UE2Iubm5ylW+v0WOkHbWdq0pVHBPTtzRGek6vQ+PGMu9r8HVDB9QmecrouUBt3yhdP9DCB6rr2cuXMjmREIb1qlaRcWdXV7knDyNFXr1/B7q+SIQTT7VKhX3CO0kLKCifhBY9J0ntNalVUwpgSqdw8ORJ3XQp2dGKVqo/b44clK0Ld8VUPL1mhBJobFSO+l68QH75TFu7Rg2lGJ+xbJluut7fPwD9x09AhRYtpZc4kRDfuYUn78nLlzhz6bJ8xo/qoulVen6T6ubABJgAE0joBFjA/cYVUKpRY9DrPeiVCvTqhv+uXJUPvdOD6NrqaOpRURS5wpEeyO49ZhzqBz9MrrWhfab06UDCYNvBg/irUmXsFTfUjGnTIlWyZNiyfz86DxuOOStXg6bFvglhR2UiCjT1RDfDmh06oEDNmli1bbsUgvRAO5UlYUjibPqy5Rg2fYZ8YL1K6zYhbthqtQpLxbSvoiig10HQN06Ua9YMe48eQ5JE9nKlJ9UVOnRu3gx2NjbYfvB/upWng7p0lsKhcJ06oNdh5KpaDU7hjIXETL+JE1GiQUOUa9Zc2quE0OjfsWPopiI8Hte3j3z+il7pQSyqijG2HThQjrNmhfKyfEEhklMK1neF8KDXvLTo0xckiLy8vKTnUBoFb2hhA4ncEvUbyJWa9CoN6ltwttx1btZUsh45axaK1quP5qK+wnXqyrzurVvJfdtGjUDjpNe4VG/XHjRN3m7wYNmvCiVKSBva0BQrvSiaXvFC/CktdKDFDWqVSk7VN+vTB3U6dcasFSthbmqKQrmDngmkVbB0jf3z3znkENfYdCGeaMp4fP/+clEAvc6jett2yClE5bSly2T/B4e6Vmklct3OXVBZTLsXqVsPcoGLsTGGdAu5WEWtVoOm/olN3uo1MHDSZFDaovHjZdeJdclCBUEePcpvP3iI+FuqgaNCzOYV08B07ZDhqF69pNDrNGwYitavL18BU79LV3ltUT4HJhCVBLguJhAXCbCA+4WzZm5qJm+8dPOlkDJ5clQtW0ZO/ewXU2SUpq2uSN68WDB2jDxcv3s3Lt68gT3Ll+nKC3Ug82izQ0x/keiiVXcWZmaUhL3Clp7VunD9unytRpPatTCse3dZXlEUaRN6oyiKzF89fTqC3kv3XginQGQWIvH4po3QTqGmTJZUTrlRWwdPnAA9eD9RCBt68F1/DGWKFsG2hQtgY2WFF2/f4psQXaWLFMaJzZul6KT26QF6KqNSB11KNIbFEydIMdJ1xEgykQ/nd23RQk7J3bh3T07x/btju6yDhKQ0Ct7Qa0CmDR0CHz8/fHVykjfsldOmhSsYiSO1T0FRQnLJLQTB36tWSg/gK+H9pJcRE4tjG9ZDO4VI4uLYxg0oV7yYfMXI7YcP5cPzl/fvC+7R992muXPkazi8fX0lj07NmsnVrdS2SogosqSp0XO7dyG/mLqlZ7nuiPosLcxB/ciZNeiBfJXwSl7ctxfp06QBefFogUqyxIlxdMMG6Hu05owehcJ5cktBZWX5fWEAtaMN9Czfya1bkcjODncfPgI9/J89UyY5nZrY3k6aUf92LVmMxHZ2si5bIbApg7xsa2bOkOfh9YcPUKtUKJg7t5zSpUUXZKMNPYX4pA8An79+hZePD1KLa//v1auQLlVKrYncN6pRHeRNJM8heX8T2dni0t49sLaykvm0oeuzT/t28hq5fOuWOIUK6PqglaaUTyF/zpzYK4Qm9dXD0wvkJaSFN/WrVAFdt6IQmXFgAkyACSRYAkF33QQ7/F8b+D+bN+HW4UO6cHrrFiwcN05O74VVU9WyZXH7yGHcO3YUVw7sx1+ZM8uy9DybSk9s0LNul8QNnWxrlA/yDNHD6ae3b8NdUfbO0SMY2KkTWtStI8unSRnypqltO13q1DKfVu5NHTIEd0U5Kn9o7VrQIgatHe3p/XP0TB7lU3/qi2m3RRMmyGf1KF8b6EZ69e8DcgxUH918SRBo83u0aiXbLFmwoDZJiI48Mo1eZaJNHNi5E2gc1N7BNaulkKB26fURWhva0/RdPXGTvn7wb9kmCanShQtRVpiBJBvZ0Hkh8RjaKFO6dDixZbPkSG1LFqGepTMRnqQVU6bobOhZLBJ2NG2nLxQojUQ41UMshnTtgvaNG8mxZhJeU23btGqXnkmTduL83fjf/5BNiCptPu2pryQkg5gcxZmdO5A6RdCraCifAk2hbp4/X15Du5cuoaQwQ4qkDvK8UXtU3wEhWsljpm+cOX16XBBCiq6x3m3b6rLIy0fnga5RKr91wXwprHQGwREvbx8M7tJFPjNJtifFtZ9BCNDgbN3OS4itYT26yz6T3cW9e2GjtyIawT+92rTR2VCf6foIztLtsmfOhCtCSFM91O9W9epheM8euCn+Bumc6Qw5wgSYABNIgARUCXDMPGQmwASYABNgAkyACcRpAlLAxekRcOeZABNgAkyACTABJpDACLCAS2An3JCHe2T9OkwbOtRgukjThDRFajAdioWO0KtbiEObhg1+2jo9BkB2A7t0/qkdZ8Y7AjwgJsAEYokAC7hYAs/N/kggVfLkcoXrjzmxk0IP6of1/Fbs9CZ2WqVXt0gOVt8XIYTVE3omjexoMU5Y+ZzGBJgAE2ACUUuABVzU8uTaYpoAt8cEmAATYAJMIAESYAGXAE86D5kJMAEmwASYQEInENfHzwIurp9B7j8TYAJMgAkwASaQ4AiwgEtwp5wHzASYgGEQ4F4wASbABH6fAAu432fHJZkAE2ACTIAJMAEmECsEWMDFCnbDaJR7wQSYABNgAkyACcRNAizg4uZ5414zASbABJgAE4gtAtyuARBgAWcAJ4G7wASYABNgAkyACTCBXyHAAu5XaLEtE2AChkGAe8EEmAATSOAEWMD95gUQEBDwmyW5WGwR8PH1Rc+JE/Hp27c/6sLWQ4ewds+ecOt4++kTxi1ejECNBgGBgbLNz3/YZriNxaGMb87OGLNoEVzd3eNQr7mrTIAJMAHDJMAC7jfOy6EzZ1C3Vy/cffLkN0pzkdgioBGC6tX79/Dz8/+jLji6uOCLk1O4dXh4euLT16+AaI+CbNP/z9oMt7E4lOHq4SG5kJCOQ93mrjIBJsAEDJIAC7jfOC3/+/dfJLazw7Fz536jNBeJ7wSyZciApWPHQqXiPy/9c50hVSosHzcODokS6SdznAmESyBQeM29P3+E27OYSvN0AAAQAElEQVQncLp7G443rsWDwGP40/PodOcWXJ88gteHdwjw8gz3+onvGXyH+cUzTN6Dd58/Y0C7djh95QrchbcFej8fhefFy9sbtL/x4AGev32LQDGNpmfyQ5Smlm4+fIibwv6zo2OI/LcfP4LafP7mLW49eiTznFxdQV6gr8ILdPXuXeFR8pPpGrElb8/FW7fw8MULeIp+iCT56+3jgw9fvoD6Rp7Dl+/eyfSwNl9EH6g/1B61EdrGW/yn+uTVK1y5cwdUT+jpZGJy/+lTUN9oOlFbnvr3RoyHPGHaNBqbTAtOoD5SX2kc1+/fl6k05Ub9oHHfuP8AbsKTQxnE9dmbNzh3/TqoP36hvFyU//rDe1zW9vMn54E4ExuqlwKNQfaLvGiUIMJ7wY/6K6Ly18PLC49fvsT9Z8/gojctSP2ga0QahbHx9fOT/b0kztMLcR78w5mOp/5TH2gqluq7fPs2aLz6vKmfNCVM7dP15uTiKlsMKvtBjv3B8+cgr6DM0NtQmbviPN0QnN+La1ovS0apXjqHd4SnmdjLxOANnSPqC+UTu+BkuaPxUx6N76XweMrE4I0cT/B5oL8Rqofaob4/F+dSf2xUxFF4O2+Jv42nr1+DeJPn08XNjbJCBGfxN/FB/O2FSBQHxE37d0Cc6Xq9JDjS9UJtCxP5G8TrI/SvTWJL1yMZUL+o73TuHj5/Ic87pXOIegJ+4px/u34VN8cPx4k6VXG2TXNc7NkFVwf1xbXhgzgwA1wd3A+XenfDf+1b4WT9mrg8oAc+nDgGn69fkJB+WMD94tnedugQMqZOjbzZsiFV0qSgG49+FROWLMGiLVswaMYMrNixA0Nnz8bI+fP1TULE6ebXZexYLBZllm7fDopfEaJMa9Rr8mTMXLMGoxfMx4b9+2Uy9WHKihXSdum2bfjq7CzTZ61di8GzZmHd3r2Ysnw52o0YAefgmx2JjGFz5oAC1Xfk7H+yTOjNbSESO44ejYWbN2PBxo1oP3IkHgkxqLUjAdN/2jSMX7wEa/bskfWNXbQIdHMkGxJ/1O4M0edVu3ej75QpWLBpE2UhMCAAPSZMAN0EZYLY0I2++/jxMk8cYuS8eZgk+k79JH6UdvjsWVAbHURfFm7ZLKaun0pRPHrhQowRYcv//oeJS5ein2hLv27iOXDGTKzetVuWn7NuPVUXZli8dSvWB/Mlg3li7NQvuonTMd3ge0+ahG/i5kLHxKHf1Kkg5tNWrgTZkiCiPBJDdP4pHjqQEOguGEwQ/V0n2hsxdy4WCdaUHtqW2qZ6dx09iiHivK4R53WUuJYGiGtLa3vq0iWMF9cc2S0UnO89DZrWXyTGM2D6DDH2XZgqrpWugrH2WqCyJEZaDR2KOeKaWS6u0x4TJ2LnkaOUJcO1e/fkuVqxaxcWChbtxbVEH0Yok/pF9sSc+jRg+nTdOSYR3ElcP5S38e+/MWTmTEwRfKgchR7jJ+gEONks3b4DVJ7O9VBxfU5btYrMZKD22g0fDjoXM1avRqcxY+Tfwt4TJ2S+/oaEYmeR7+HppUsm8UVc3IXgJ75z16+Xf4903RIzus611wuJPLLVXsdUyb9Xr4CuMYrT3xjlT1q2DFNWLMee48cpmUMUEvARN997c6bhdNN6uD5iML5cuAj+YQKRIeAiPtjfnTkVZ1o1wZUhfeH57k1kisV5G1WcH0EMD4C8bi1r1ZKtFsiZEyQu5IHe5vWHD9gkbrI0jTZH3CTvCy+H/id7rSml9Rc3v2EdO2GluKkvF9NLo7p1A4lADz3PnqeXNzaLG+HsIUO0RUHeinVCQKwWoiKFg4Psx4UbN7BeiJhlop4NQmTlzpJFCjry4FBB8vSVL1oU60W5bs2aUlKIQN4/EgiT+vTFanFDp7pHde2KQaJtrQdm1IIFsLWywsbp0+Q04QohDMjDc/baNdBNsp9ot0KxYlhH/RDCdIG48Z+4eFHmhWjsJwfkcdsi2qRxaM3effqEecOGY40Yb/F8ebFP3MRfCO/mZsF5sRAMNF4fPz/sFGKHylB//jl/HvOFAFg+fpwcs5mpCWWFGRpVFZ/0xRi0mdeFgLEwN5deS0ojQWMpjlMK1nRMIntAu7ag8VPbqZIlw6YDByjrp2GEEKg2gh+dg6VCcNA4ydt5VngRwytIY6FxLhM81wquxGLd3n0689fCyzW+Vy+sEWK/VMGC2PPPPzhz5Qqo/uXi/FD/iuTOjZHz58ky5MnqI+ppUq2aLEOc54hra9PBv+WiCx8fXymI5w4bhhXjxmGFuDZb16mDkfPmga7Zf0XdNAY6x0sE+8n9+kmPIlVOoov2lLdo1CjJ/Znw1pLgpfTQ4fHLF9ggrkf6W5k+YAAu3LyJb87O0utMHxRqlS+PtWJcxHli796gv6XQddBxvuzZ4WBvj1uPH9GhDMfF+acPWkkTJ8auY8eE8H8i/46WizERk5TiAxh9oJDGkdykSpoMVHZY586RLMFmEREIEJ7s+/NnyZvv+2PfP0REVI7zmUBYBJyFh/1cxza43L87/FxdwjKJN2mxIODiLjtXdw/QVF7mtOnkIBpWqoQ7jx+DpoBkQvCmdKFCwTEgiZ2dvCnKh9p1qUGRy2JqjzwWmdKllV4JmhrMlj496OZIHoUgK6BW+XLaqG5PNx8bS0t5TDfVJcLj0qJWbZibmck02tBN5qOY9nsjBCUdK4qC6qXLUDTMcPbqVdjb2iJPtqy6/KJ588JatEMChhJJOHZs2BCKotCh7Otu4RUqX6QI7oupOk/xn3GPZs1kHm1I2OwTXjK1Wk2HkQp1KlTQ1a8tQF7PdKlSykNa2blaeKOa1aih40bsKpcsgTPBIoyeU6xUvASIkywkNk2ESBO7MH8zpUkjp5cpk7xt1EYrwVMrCI8KMVCtVCnKliFr+gzIkTGTjNOmuOCkP11MaWGFZ2IqsGfz5iCBTn0mb1aWdOnwULALy57SqB+0p2BmYoKuTZpg/8kT0FCCCIqigPovovKXxFvT6tWRRAgamSA2zcTxq3fvQR8uaPrQUlwnrWvXFjlBvxnF+PcLT6papcKm/x2U15G9jY2Ob8XixeXjAiTyiSmN4+i5/0Dnm87NQuEdpZpsra1B05l/nzot84yNjUEfBExFvyk/dKgnzrX22qA+GBkZgaY9X7x7CyNxzXRp3FhXhMaoEmPVJYSKFMmTRwp7Sqa/iTPieq5cogQd4uC//6KuaIvqpASqZ1inTvLvmY4jG2qVKxtZU7aLBAHn+3dxslFtvDv8v0hYswkTiDwBlwcPhTe3Pt4fOxT5QnHMkgXcL5ywJdu2Sg/EZDGFMkRMjU4T0zp0o6BnavSrsbUKElaUpihBQkd7s6U0bdB6K2jKqa3wFGkDiTq6CWrt6EaqjWv3duLmqo1TH0THUKpAfm2S3BuLm6GduKGSSKAEEnemJsYUDTO8/vgBaVIGiSR9A2qfRCBNN5EnhRZw6Odr465iupa8Hdpj7V5RghhojyPa2+jx09pS37VxP+FpUzQa+SoPLTPabz90GF++fRMoNFKMZc+YQVtE7lMnTy73YW3Iq0ieypfCq0de1WqlS6O2EM703Jmvry9evn2HQrly6YomTWSvi1NErYrcnxJN0Q0W3kXqrzaQOKapZ6onrJBLeFL10wsJz6/2nFM6iSb9BRPkYUufKhVl6QKdFxJR9DoTV3d36F8/OqPgCIl0uma0/aM9TV/T9UTTsPlz5MDo7t2xft9+NB88GPX79AEJZiqeOlkyTBOetM1CBFJePeEZ/PvkKcoKM1haWIRI147Dy9sHdO3qZyqKgiziA45+mn68rfASkhCmKexbjx7DTXixSwuPJHmGncTU91+ZMumbw8zUVH64CpEYwQF9uIrAhLMjQ0D8/b7euwNXBvSGcM9HpkSQDW+ZwK8QENfZvTkzcWvCyKC3AvxK2ThgG7m7ThwYSEx0kRYZ0Cf6An/lgDaQ14Bu+L/TfsokSWSxHXPnYo+YmtQPJQsUkHmR2SiKEEgikEdP3548SfRcloXwtuinhxdPkdgBb4O9dfo2dNNOLqYOTYQ3hW7i2ulUfRuKWwpPHXkoKR7ZQDfZyNpq7chLQ/EB7dr9wI0YKooCEivkJSI7baBnorTx0HtFUdCwUmVsOXwIa4V3r2XNWtILSDfsL2JK74vjN6T5iQAMXV94x+RtoqlQ6qd+IEEUXplHL56HyLotvL6KIs55iNTvB+amZqBp1u8pENOSLnJaMrGdHayEaKLrQj9fP55CTC0mFt47/f5p49mCBVSR3LlB07/kXZ0iplDpWUxaeEL15BBCadusWaA8Of25aydIQFFeZAP1kZ47k0I1uBBdz4/0nscMTtbtaMo7R8aMoA9Ux8+fA3lMFUUBMbcS1+ZjMZULvR9ajKMVjHrJuqi73vN0ukSORAmBh0vn49HypVFSF1fCBCIi8FnMoJzr1CreiThVRAPn/CACdHNyF5/oOzdqhGbVa+gC3bxoIcLTV6+DDH9hW6ZwYZAoevzypa4UiY4m/QfA3SPyS6MVRUGTqtWwes8ekJdMWxktHiDPVbpQ3hhtfuh9mcKFQKv+Pn39psuicZPHpnCw94mmRPUf4Pb28UXTgQPx3/Xr+CtDBvFhOhBbDh7Ulf/s6IgGfftKr5hQRCDZ4ePjo8v/+1T43hmdUagITYPVFFNZy7ZtD5HTd+o0bD98WKaVE1O6JKz1VyweOnNG5oW3oTov3bwFb9E/S3MzaZZTeL+mrViBfEK0m5uZybQ/2djb2skFIvp19Jk8GfScm36afnzLoe9TAP7+/li8ZSvKiGtHUYimvmVQvEDOv7BVlKFnJ4NSIKYQTyOZ+MCQIXVqUHASHqmjeq/B+fDlKxoITxpNHbcRU6vfnJxA3jpt+ZOXLskFLSSo1gvPGy0yoTxFUZAzc2aQsKe/D2JOC3G0eTSNS+eLFglQWmRDJjGlSx88RosPNtoypy5f1kbD3dcoXUY+70Y8KxYrrrOrIqaAQ5//lTt3wtLcXNqQYFQUBeRhlgli81/wdLyI8m8UEniydiXe/B3x86JR2CRXxQTg+e49LvTtFq9EHAu4SF7Yc9avR/F8+UCf8vWL0H/8ucQN7Oy1q/rJkYorioIJvXtjxLx56DpunNzTKtLGVavAyjLk1FJEFbauW0c+B9V66FCMmD8fbYYNA61QXDhiBOh5n4jKUz492zSkQ0d0GTcWnceKMGYMSFyM69lT9zzVLDFlRq91aDFkCAbOmIHWw4bKdksINiYmJpg1ZDC2CRFFU260WpJW7pUqWACKokCtUiG78JC0HzUK4xYvBk3N0U0av/HTpVFjmJiaoPmgQZi0bJkUFy/evkGNMkHP+FUX+8K5c6PT6DFyBWcbMUVNzxWqlPAveTqXJGDI20heG+pWs2rV8OLdO9QuW44O/zgsHTNavlqmheA4bskSwW8YSDAWzZMn3Lpp+rOl4E0LSFqJ82tpYY5+rVuHa9+2bl3k/vLT5AAAEABJREFUEtdk2xHD5QIU4nzg5ElMFZ4yKkRT4tMFt8VbtoDOBa0o7TFhvPxQolap5HONXRo3Qbfx49F36lR5nudv3IgODRrI81hLiGdaQELXyGQhbmks1EcSciXz55eromklMq3Qpf6Sx5Tyqe3IBvKMzR4yFPSak4biA0CT/v2xX4whX/bsP62ijPgQQtc7TZemTfF9yrxtvXpy8U1TMb07ZM4cUJ/pNTXkIdRWSM9/0nVLK1Sp3yS2tXm8jxoCn/49gVc7t8Wrm2jUkOFaYoKA++PHeLJ6SUw0FUYbUZ8U/t0s6tuK0zXSA88D2rYNcwxDO3dG7fLlZd44IXZKFSgo47ShqTxaCRjey0vp+aZVEyagTrnyoJsfPQzeSO9he1rll0l4I6gubWhesyb6tWmjPdTtZ4mbMq1GzJs1G9qLmy2thNXeOOnmSisydcbhREoWyA9apVenXDn50Detji3w1186a3puaJkQmz2bNQOJNhKg1CbdcMkoc9q0WD9lKpoKL2UZwWHu0KHo3/p7X+n5KGKUI2MmjOrWDYPatwfx0QqmKeJGnSdLVqpKF0iU9Q/FnuxpheSQDh3ka126NWmC7eLGTAsuqCD5poZ07IjxvXqChBy1Q/1cJsRpcuGJIpvQgbyhtNpxthCh2rz0wmNFaXn1hAOtQu4kPLFaG9rTQ/4DxZQuxUkI0+pjiqvUajk+8n7RMXmq6Hz3bN4CucRU41DR/0WjR0tPLOWHFdoL8UErNAvk+AsD2rYDnR9FoRECFYoWBYlq/XKKomB4ly6Y2LsPiglhSMKLVoVqrwWyzSnappXGTapUQfVSpUAreZtUr0ZZMtQuXw4LhdAuV6gQqpYsBepzqYJB1zVNw9IK6L6tWkmv6wTxIYRWnFJBmnKm6dOhnTohdfIUGNejB7bOnCk9dJS/bPw4uSiG4mNFXsGcOSmqC4tGjoR2mjZlUgfsEOeUppxpJew88aGEVqjaWVnr7ENHFEWRz/eRgNfPo+tlkhCCY0SbhcT13KN5c9CKZvr71NqtmTgRQ8U1Q+J3srAd1rEDaE/5tBiJrlOtx47SOPwaAV9nR9ydMxOa4PcA/lpptmYCUUPg5a5dcH10P2oqi+VaVLHcfpxpPoWDg1yZF1aH6WFrmiqiPLpJ6v8nrygKUiVNKlfUUX5YgcrS9F3NsmWRKlky6eXQ2pEYIGGhPaa9bM/OjqIhAoko8nA1FTfi8mIKUStmyIhuVDQGiv8sKIoCEji1hSCtVa4caDyKEiQWtOXIU1WyQAE0FDf/HBkz6m7O2nx7WxtULVUS9SpVRNqUKUOMh/qYO2tWIfCqgVZf0tiIj7YstU0iUXtMexoHMaK4fiAxlF/cjFvUqgVaLWtuaqqfLZn/JTxRjYUgziPaJHviaWQU/opYyrcNJRAojcpqKyf+iWxttYdyT0y0fSRbLWsiR+OjaURpKDbkxSWh3Ej0K5foFzEQyeH+ErPUyZOjQeVKKJIndwixR4sAiFnowtRe9owZQG2UFdOtxDC0DX2oIKFD55rGGDqf+l2/cmVUKVlCfnsCjUVrQ6xzZckCyqfzSGPW5tF4cmTMiGbiOsySPj3IA6fNozppPHRM1xbVQ3FtoH7QtUoLSsjD+8+FC7JtYu4rpo9ppW/pQkFCUltGf0/vO6TnMIvnyaOfLOPUR/ogQ69PKSWuXzpnMiN4Q/0smCuXvK7TieuWzlOyxIllLglA/b7LxDi2ie3u3pkyAYE+PrHdDW6fCeDaiCEI8Pr+zsi4iiROCLhXu7bgYveOONWoNk7Wq45/alXGv03r4VzH1ni6bmVcZc/9ZgJMIBwCNA1aS0xb03Nq9Lzd4q1b0F1M6ZYS4i2xnd0PpWiBCr03btyixaDXrNB0/g9GnBBrBBxvXoXT3Tux1j43zAT0Cfh7eODd4bj/HKZBC7jnm9bjtBBtj1ethNuL5/B3d0eAtzc04pO4r4sLPN+9xYttW/BPzUq4NX6U/vnhuMER4A79KgF6PnBk1666KcdfLR/X7csXLYLZQ4eiSO7csDK3AE2jD+3QMcxhkahrVbs2pg7oD1rAEqYRJ8YagUcrlvLUaazR54bDIvB4zSr4uf/4tXxh2RpqmsEKuLvTJ+LZpnUCsHuE7DQBAfh84Rwu9ugIjSYwQns2YAJxgQBN6RXPly/ElGlc6HdU9jFj6tRoIKZxaRECTYOHVzdN29LzdJlCPS8anj2nxxwBz7ev4fHq+0r7mGuZW4o3BKJhIBrhCPp25VI01BxzVRqkgCPx9uHUyV+m4Pb8OS737io9dL9cmAswASbABJhAlBN4vGYFNAH8wTrKwXKFf0zgyfpVcXpFtMEJuIeL5+F3xJv2TLo+fYpbE8doD3nPBJgAE/hTAlz+Dwi4Pnr4B6UjXzRNg0bIP28him/cilzjJ8NGb+V45Gthy4REwPvjJ3h9+RRnh2xwAu7DyRM/hVn5yClQ+JnRl0sX4Ovk+DMTzmMCTIAJMIFoJhDg7QVfZ+dobgXIOWIU8kydDZusORDo549UNWqj+KadsMubV7ZtZGmJimcuIu+U6fL4Tzf2BQrJ+lTGxn9aFZcPRcChdClU/PcCFFXMyBPP169D9SDuHMYMoUjyeLl9I/w9In7mLTLVPV6xKDJmccOGe8kEmAATiIMEnG5cFdOnAdHacxJRaVu0w9u9O/Bvzcq41KE1ztStCkWtRuauvYLaVhSYJUsBEzu7oONQWyMrS0QkGIzo5epK0Mt0VKYmsj4EH4eq7odD6ovKxPiHdG2CWtRNdWqPo3KvGBlBZRbyFUsqU1OoLczDbYb6qg5VJlzjn2QY29oA4Qgx4k3jDl1cLfpmmjQ5IssWf/jjdPvGH9YQe8VVsdf0jy2/P/Fz79uPJcJP+XDqFAJ8vMM34BwmwASYABOIVgLf7tyM1vqpcrlwLTBQ3O9VUFQKJcHr/QecrlYO1/p0g2X69Ch78JhMdyhbCeWPnYJ5yhRBxyVLodyRE6h69R6q33mMgouWwjT43X9kQNOx2QcPRdG1m1D1+gOkrFIVWXr2Qv7pcygb5Q7/g1K79st46E2xDVuQd+p05Bo9VtR/B9VuPETeaTNB4klra50lC0rvOYhqou5qNx+h8Io1UJuZyUD9LLz8+2uyCs5fFNz3lLK4SSJ7lD96CqkbNpLH+pt0rVqjxNadyNi+I6rfeoQy+47IbLW5OYqu2QhKo/5Q2+Ypg+ojA0WtQp7J00F5VUV/Cy5ahkydu6Lkjj2ULdlQv7J07S6PaaMyMZX9si9YgA5loParXLqJKpfviLHfReZuPSBOEOiHhGPOUeNQ5cptVLt2H+XEGBxKlaIsySr/vOXiPKoE2xOyXkUIcZkZTRvnxw+iqebor1YV/U1EvgU/V5fIG0fC0s/FORJWbKJP4L9nFjj3/Ne+xku/PMeZABNgAloC9PonbTy69hr/AHw48jdS1WuEUrv/RprGTWGeKhW8P30G5fl7eODz6ZOyee+P7/Hp1En4e3qBPFOFlq+D14f3uNazE+5PGY8kJcog98Qp0pY25qnSIGO7LiCR8nj+LHi8fQu3x4/hdPMGZePzv6fx5b8zMh56Q2VT1W0Mm1x58WTxPDheu4zU9ZsgVe260tQseXIhpjZDUatwc3Af3B0zFHa584mp3+2g12UBChzKVAR5qiB+EhcrBYt0GWGXL584AlJUqQaL9Bnh8fSpPNbfmNjawS5fIWQSHsjnq5fj7f7dUJmYSLFolzsv7o4bgRt9uwkvnAVK7fobxtbWsnjucZORplEzfDh2CI9mT4VpoiTI1n8ILFKnk/mKEFPUB5NEieQxbUg0U5razJwOkaJGTTGlPR4fjx/B1W7t8HrbRmTtMwjpmjWX+WkbNUW6Fm3wbPliXO3eHj6O34SwnSvzXO7dhePlC4BGg8/inNG5orjMjKaNx9s30VRz9FdrUAIuqt+MHBgQva776D89f97CtJUrce5G0H82kalt1w0b7Lsp3N6RMWYbJhAhATZIyAR8v8bMs8g3hwzEg+kToaiNkHvCNJQ/cQ75ps+GsY0NfL58wYNZ0+RpcHt0H/enToSfszOEPsLNAT1wpVsnfDzxD15u3ogv/55EsvKVQdOyCP4h0XexTTM8WbIQJDA+Hj+Gl1s3ytz70ybh0bzZMh7WhsTX1a7t8WzVClxs2wLkVLDLm0+apm/RGkZWVrgg6n53YD9e79yBG0LIWWfNIfMfL5wDRVFBMTaSdkY2tvD59BEZWrSV+UnLVoSfmyucheiRCaE21PaVLm3wcM4MPF26CPb58sEyQyb8W6sSXm3bgvdHDuN8i4Ywtk8E89Rp5DRrqroN8WbnFtzo3zuoz+2aw/PNrz0jlnPUeDjfuobbo4cLsXwKD2ZMxbdL55CyZh3ZQ7MUKRDo54sv587g0+lTuNy+FchbSplv9uzGqy3rhGbT4P70yfJcRfdXr/k5uVDTcTKoDKnXgf7+Udodej9clFYYXJlGfDoIFC774EO58xd9DwiVJjOCNwFCTFK54MPf2vn5+ckLO7zC1EbovM+OjvD09Ayd/MfH9FYAv4Cg6YqwKgvUAP6BYeV8T/P1/7E8lQsI/DH9e6mQMZ9QdYhTA6ojpNX3o9D233OCYlSW6gg6CtpSGUoPOuItE2ACkSUQ3Tdf/X48X7MKZ2pXxanKpfFu706krF0f+Wct0DcJEdf4+cNTTLXmnTwNNBVafMNWWAqPFlRqqM3NdLYu9+7gd+8lXu/ewNc5WCCI/1j8heAysrCUddvmzCU8YJagacaaj16BQtHVm0FTrBbp0+KTEJVQFNBD/ZnatZdfQ/Z02XzYFy4GerbMKktWfBKeMo2498gKQ20CPD3gfPuOLjV5xUqg+iqeuSLbovYqX7gJEnpWWTLDJnNm2TZ5FRH8E+jrh6/nw/YwBpv8sDOytIJ9gSKo+fAlqA0K5Nm0yZFL2r7esQ2+jt9Qas8hVL5wAzlHjYF5ytQyLzY2MXmNRvX4VFFd4Z/UF5mHJo9XKw8KkWlHbWaGyNhF1qbftGk4e+0amg4YiJHz58ti7kIcTVy6DPX79EEDEVbs3Al/4dKXmWLjK0TXvI0bUbdXL5HfF3+fOo2l27bh4OnTIhc4du4cpq9eLePazaa//8b2w4e1h/j49SsGzZwp22jUrx92HD2qyyMhuVMcN+rfX7YxasECuLgHLQQZs3AhHr98iY2ivn5Tp+LD5y+6cr8bCQgEZp9IgiLTMqDw1AzosyM5XLzUuuo8fFWYcTwJSszIgCJTM6LnthT45hGULzQdWq9LhZffjNFoZRpZh6OnGjuu22LuycRYe8EO5eakR/EZ6bHyP/twhdikww7YccMW/XclQ1HRj7brU8HNRyXK26PM7PQoJtIO3LbW9Yki/z21QNWF6aR9pXnpcPKRJSXL8MrRWPZz9w1rFBJ9HnEgmUz/6q5GK9Ffqo/Cuot2oPHLTN4wASYQIQGTRHYR2vypgdQl/XUAABAASURBVFnSpGL6tD5MkzrIqrzENOet4YPx/uAe2OXJK9PC2hhZWqLkzgMwE+Lh1ZaNwkt0AaZJgurQtw8M+H3Hgkb8/69fl36chIPP188437zuD8H7w0cE+PhI4Zi5U0+kad4Wb3ZtxqsdO4T3yg92efODpmg//nNcv8oQcapfP4EcJCREw2rv69kzoHyy1/c+ymMTU9qFDIqedFBCfeAW/9G/3bPthzFdah80herx4gVOli+Ji60a4Z2Y2k1SspyYxj0gPIHRf62EHETQEYnhoFjc2+qdhdjvPM23R2UvjMwsorI6PHv9Git27ET/tm3Qpk4dkMdr3OLFUKtVWDNpEhaPGo1bjx5h3sYNsl0SV0u2bsX9p08xa/BgzB8xHGevX8MZIQK/BX8qc3R1wZsPH6S9dvPp2zd8EZ4zOiaBOHzuXNAb6bcIETepb1/sO3ECW//3P8rG5du3QQJu+oAB2DJrFjy9vDBl+QqIvyHULFsWSeztUShXLjSsUgW21layzJ9sxv0vKS69MMOWju9xcsAr0J9uty0pdMJm2tEkuPLSDOvbvcc//V6BvGyt1qYKalJ06sF7E7RckxpV/3LHOmFjaRKIz25qbLlkg2dfTLC32xtMb/AZq/6zw7EHYff3hRCAs48lQs3c7jje7zW8fBXUXZoWt96a4VCv1+hZwQnj/nbAW2dj2e6VV+YYKMRe88IuONH/FdqXdMbwfUlx8YW5zPf2U3DhmTnWCwG5vNUHNCnoAl/hXay3NA3ypvbBmUEvsbb9B2y6aIstV2LnPxnZUd4wgThGwDJt0LNT0dlt02TJkG/aHGRo1xH0jBa1RasozZImR4CPNx3KZ6ooYpwoCe1kSN+yFcj7dLVbR7zYuB6PxRSpz7evMi94E/4u2CVvnjJ5+DYR5DjeuCY8aXbCG+UCp+s3ZTC2sYftX7kQ6OMrxdv7A7thl78QTMQ058tNG0HeNu/3b5F7/GQoigKXu7ciaOV79rvD/wONFxpFtkVt+rt7wKFkGQR4+8Dt8ROQ1y5FtepQjIxkQZqCdihVVsZpo+VpmTEzHcqQpn59uddu/FydYZ+nAFzuPZDtON+8jWRiulcrDFOJe2f2AYPw7epV3J86CVe7dYDK1AxJS5WWVZDXT1EUkRaGcETU/1joLeKI+tqjt0ZV9Fb/a7U7FC0aYYHKR05F+B44qiRxwYLyuQGKR2WYMWggiufLhxyZMuHExUsgsTWsUyc4JEqE1MmTYWDbdrh8546c6nwthBmJtcWjRiF7xoxIK+b+pwgPmluwhywy/dr7zz9InSwZejRvDhsrK+QQ9Yzq2hXHz5+Xxe89fwYzU1OkSZ4cNpaWmD1kCKb06wsSVkXz5EEiW1vkyJABpQUPC3NzWeZ3Ny5eKhy8bYUFTT4iWzIfJLIIwNzGH/HqmxEefw76Y2tWyAUrWn4IyrcMwLT6n+AoPFn6bdbN54bOJZ2QL7U3TI00MkslrsQJtT8jsShTPqsHymf3xPVX36cxpJHeJmMSX1TK5gEHK39MqUdtqDCx9idYmwWibVFnJLXxx0fXoP+EZhxLjF7lHdGumLOsv2VhFwyv9hVTj3z/z9xYrcGBHm9QOK0X8ot+Lfk3MRJbBWJQxa+yzpzJvTGqxlch8myh0esHR5kAEwifQCIxTRh+btTkuIj/b7/89y8ydeyOsoeOi2nTuSh//AwSFyuFj0f+Jxvx9/AAPctmn68gSmzcCtvcufDu0EEp7PJNn4MkpUuhyPLVsMqURdpHtPENFnpl9h9D0bUbIzIPM//FhrXw/vQRpff+T04jFlq4FIWXr0OK6nV19g/nzpRxEqY+YiaGDpyEE8A8ZRq43L0J71+YVXF78AAu9++gxLZ9yDd9FvJMnIJSew8jTdPWIG8dhff/O4DkVWuhzP5DyDVmLModOSlFJrVLwc/FVbbrULocSmzZgUKLliHH8PGUpQvX+nSFeboMKCPGRSt2yxw4goxdesEsadDKX5NEDsjUtZcsn7FDR+Sfu1AISC+8PxR0rpzE+YQQcFUu3ULZA4ehFX66BqI4YiumoqO4yhirTtw2Y6ytCBvK0qkH6EKN0DASBn/1GxIJq183sbKw0BW6+fABnFxc0F4ItLYjRoDC2CWLpRfsjXCBf3VyQiIbGxjrvezRSK2GtZWVro6IIk9evcL9Z89k3VQ/hSkrVsBV/IdEZZtWrwEfX18xPdsHU1auBHn7/vRZO6o3rHD2qRU0Qr20EdOKVRekA4XqYlrSN0CFu++DBFz2ZL6gKdI5Ypp1uphKvfjSQued09ZZPaebNqrb50rlAxWpzuAUG9MAePuFf3nmS+sTbAnYmolOiSNTo6C9iMJIFA0U072U8lx49siTRunakD25r07gUZqlqTCmSHDYd9NKCtNqYnw0TgqTDifBVyFGtVPCwabRt+OamUAcJ5C4UAnQzRjR/HO5Uzs8WTwHKjHr4lCmAqjNW8MG4J7w8CD452z9GvB49QIWGTJLT5PX23d4PG8GbPPkQ/6ZC+Hn7IQXa5fLVamaYA+b9+dP8BX/jwdXodu5PX2CW8P7w9fVFaYOyXTp+hGfz5+FwPqknySOP+vqCxDer/NN68Pt8SOkqt0A9oWK4u3ubbjQsrGujM+Xr3IRgcutm/AP/uD/ckvQytmX2zbr7EJH/Nzc4P0x5MyOJiAQ5xrXw9czJ+EgPGLJKleH85VL+LdqWeHxC/r/9PaoYXi+eilMEjsgRY16+HjsCF5v3xSienrPnvuTx7DKnA02OXPjdK0K8Hr/TleH881buN67M1TiXpmhbWcY29njRv/ueC88gFTRi3WrcW/iGFikSY/MXXtDURnhTJ3KoP5Rvp/gfX/iSPiK86Gyshb3HPpfnHKiJ9jnLhA9FcdAreI2FwOt/EITiQsV+ak1Pf9G4WdG9CJAM4ekPzOJkrxA8UdeRHi5Fo4YCW1YPHIUtsycBfLGhdcIibjw8mQ6qSQZoQ+IGpQrXERXP7WzZPQYrJ00WVpYCa/a9tmzsWL8eKROlgwTli6VYo+md6VBFG4Cgv+OdnR6g+2dv4d/+r1E3TxBoqzvzuQYuicZbM0D8FcKXxy6Y/VDD9R6Qu2HzGhIoG7ri0NqQnaBMuhABHks9tpfGmvLYq4hxrmryxucHvgSiS0CtGa8ZwJM4CcEaArORMwC/MQkyrIeL5iPk2WL4ViRvDhRphje7tsTom5fRyecrloe/5QqDPdnL2Tek2VL8E/JQjheLD9uDBmIh3Nm4WS54jqxdL5ZQ9ybMFbaht683bMHJ0oXwZlaVUJnyePzzRviQpvmMq7dUNq9SeO0hyCv2jkh4o4VzYfjxQvg1oihujyKaMSn0FOVSuO/JnXpUAZamEB9fLtrpzwOa/Nywzr8W7PyD1n0DNylzu1B46VwoV1L+Ht4hrB7MGOaLv/OuFFQmZiGyCcv3L+1KkvOJ8uXhNerNzhZvgQcxZSo1vDTqVM4Wa6EtCHeH44c0WbJ/ctNG+R5oHGfrlYenqIOmRG8ebFpk2R7qkIp0LRxcHK07KzEDFW0VBwDlf5MwMVA8z82kX/8FFilT/9jRiRTyINXbueBSFr/mVmurFnw7M0bWFtaiOlNSxnUahW8vL2gUqmQyM4OzuITWqD4I9S2RMKKvHbaY0vxidFR2GiPaU8rR2lPIVOaNPgqPonYWAXVT3uVUCOKCJRPz8q9Fd6+lEmTyufyts+ZI9r3xhdnZ8qWIVBPEFLC73roSmX0pOLwDVTBzjxQBlsxZfnNwwjGRhq5WOG/J+bY0vEtOpZwQu1crhhWNZLPlMiao35Dwix9Yj/c/2ASonLyEtI0a4hEvYMauTxw4ZmFHKN2rP4BVJtCH+71LDnKBJjAzwjQNyD8LJ/zmEBsEVDE7JhFytSx1fwft6v64xqioYLiS9fA+jdUsaJSoeL+I1CZhLxZR0MXZZU1y5SBlYU5ZqxZA1pt6h8QIDxgS7B461aZnzF1auTJlg2dx46Fp7c3/P39MVJ8StQoisynTckC+UHPxN24f58OQc+83Xv6VMZp07haNdAU6qpdu0DCy8PTE53GjMGy7dspG5du30avKZNl3ZRw8tJl2RdbKys6hKXw0B04fRrfnJzl1K63jw9oJev+kydlflgbWhl6+ZU59MMbJ2MktvJHmSye6Lo5BVy81bLopCMO6L4lBWhEiSwDYCmmM9dftJN59Mxck5Wx/8cxoJKjfN5Nu/L0v2eWGLY3KQZWdpT9DGszrMoXfHBWY/l/9nIK2MdPAU0db7xoG5Y5pzEBJhCCwPeD7F26fT/gGBMwIALZOnQG9O7HiGM/BingCGjRhStA76WJLE+1ECoV9h2GdvVMZMv9iZ2iKJg1eAhev3+Phn37okHv3jA3Ncfo7t111Q7v3BlJ7O3RtH9/+RqQbOkzIKPeqhdaZNC1cROMWbQIdXr2lKtYqwZ/rQhVQgJs3rBh+Fe4p+uK/GaDBqFc4cIY2K4dZcuVpk2qVpV1U/6izZuwdvJk0Q9TmT+0Y0d4eHmJadXh+PD1K9RqtRCdFrCzsZH5YW2uvTRFl40pQoQdV4OEy7wmH5E+iR/KzUqHglMy4tYbM2zu8E5WQyJuQ7t32HbVRubVXJQWi5qFfA5DGsbwplQmD8xo+AnD9iRFgckZ0X9HUkyo8wXlsniE2xNxanG07ytsu2yLwtMyotiMDCiT1RM9yoUv+sKtjDOYQAImYJszD8yTJ0/ABOL20O9OGIPjYpo5bo8i7N4nLVsh7Iw4kqoy1H6SECu6aCXKbt+LFOXLh9vNJIUKoczmnaiw91C0e97+XrJETJdahuiLuakpFo0ahV3z5mHX/PkY17OHmE400tnQAoZpAwaIvAXYs2AB2tevD1/hidMZiEit8uWwV+TtFHWM7dEDvVu2RC8RRJb8TZUsGdZPnQrKpzq6NW0qNC7JJch9i1q1sG/hQuyYOxe7RR9oRSyCf6wsLbF20iTsFwIxk5iONTYywropU1BWcAs2CbGb1+gjbo56/kMYWDloKlQlmp3b8CMuDnuB80NeYGfnN3IlqLaSTEl8cXnoC5wb/AL/DnyJgmm9cXVE0PMmJIoo/lcKH6253Pcq64jVrd7LuHYzovpXIbI+aw9D7Ml2aHB/KMPB2l/210RM49IxhYM9X6NIei+KylA5u5gSHfoS54a8xAWxr5076Jk9ysyWzFe+XoTi+sFGTA+f6C/KiLFcEuMdVkUIYDF+fRuOMwEmEDGBjC1aRmzEFoZJgJ4VDvUYjmF29Nd6laZ2bZgmSvxrhQzM2mAFnJaTia0dcg0dg4oHjqDs1t0otW4LSq7ZhNIbt6OCmC7NP2kmTBMn0ZrHyl5RFJiKaVsTY+Mw26d7vqmJcQhhF9rQSAgrU2NjKchC59GxKrgNEmB0HDqQZ436oCjUWshcRVGk5w3BP4ryo01wVqR3tOKTQlhVUZqZsQZqVaSrixFDtUoDc+NAGIl9ZBsFdFNcAAAQAElEQVRUCVTmYiwmavpfLLKl2I4JMAF9Aimr1EJMvBNOv02OM4GfEcjUplN42XEm3cBuseFzU5mYypcZmidPAYuUqWDmkBS02jT8EpzDBJgAE2AChkIgz/DREJ9QwT9MILYJ5BkxGsbW4T9GFNv9i2z7cUbARXZAccFu6ZgxaFO3TlzoKveRCTCBmCYQT9uzypAJmdsEPbsbT4fIw4oDBByKFkXSUuXiQE8j7iILuIgZRbmFSqUSH0TF3FyU18wVMgEmwAQMl0CG5m2QrFzcfnDccOlyzyIiYJo0KfKOngR6Y0VEtnEhXxUXOsl9jFEC3BgTYAJMINoI5Oo/BEmKFI22+rliJhAWARN7O5RYsgq0QDKs/LiYxgIuLp417jMTYAJMII4SUJmaIu/I8UhVtXocHQF3O3wChpljkzULSq7cCCMra8Ps4G/2igXcb4LjYkyACTABJvB7BEjE/SU8cdm69QRUfBv6PYpcKkICioLUNWqh6IIVQrxZRWge1wz4LyeunTHuLxNgAuES4Iy4RSBtvUYovmQF7HPljlsd594aPAGzFClQYNI05OgzEPH1hwVcfD2zPC4mwASYQBwgYJU+EwrNWoC8Y8bDNnuOONBj7qIhEzBPmRLZe/ZB6bVbkLhgEUPu6h/3jQXcHyPUr4DjTIAJMAEm8DsEkpYogyLzlojprqVIXasOLNOl+51quEwCJGCWLBmSl68oPG5TUWrNZqSpXT9BUGABlyBOMw+SCTABJhA3CNhkzY4cvfqjxPJ1KL9zPwpMnoasXbsjbcNGSFWtBlJVjaeBxxXpc5umXgNk7tBJem3LbNyG0uu3IffQUUhcqFjcuMijqJcs4KIIJFfDBJgAE2ACUUvAyNpGTIMVRbr6TZCtc0/81W8w/urPIaEzyN6tNzI0aQny2po6JIvaiy4O1cYCLg6dLO4qE4hGAlw1E2ACTIAJxCECLODi0MnirjIBJsAEmAATYAJMgAgYjoCj3nBgAkyACTABJsAEmAATiJAAC7gIEbEBE2ACTIAJGDIB7hsTSIgEWMAlxLPOY2YCTIAJMAEmwATiNAEWcHH69HHnDYMA94IJMAEmwASYQMwSYAEXs7y5NSbABJgAE2ACTIAJBBH4gy0LuD+Ax0WZABNgAkyACTABJhAbBFjAxQZ1bpMJMAEmYBgEuBdMgAnEUQIs4OLoieNuMwEmwASYABNgAgmXAAu4hHvuDWPk3AsmwASYABNgAkzglwmwgPtlZFyACTABJsAEmAATiG0CCb19FnAJ/Qrg8TMBJsAEmAATYAJxjgALuDh3yrjDTIAJGAYB7gUTYAJMIPYIsICLPfbcMhNgAkyACTABJsAEfosAC7jfwmYYhbgXTIAJMAEmwASYQMIkwAIuYZ53HnUMEggMDMShs2cRIPYx2Cw3xQSYABMIjwCnxwMCLOB+8STSTXj/yZOYtWYNpq5Yga3/+x8+f/v2i7WweUIiEBAQgCVbtoD2CWncPFYmwASYABOIPgIs4H6BrbObG3pOnIhTly8hVfLkSJsyJe49fYo+U6bg5sOHv1DTr5vO37gR248c+fWCXCLaCVy5exejFiyIsnb+9++/mLt+Q5TVZ5AVcaeYABNgAkzgjwiwgPsFfBOXLkV6IdpmDR6C5jVqoGWtWpjUty8qFSuOWWvXwl94WvSro6kzf39//ST4+Pr9dCrNx9cXGo0mRBk6cHZzhZuHB0V/CJ5eXj+khZdAdfv6+YWXHWY69SnMDJFIY/7V+kSxSP2GbjdQcPHy8flp2dBlfmocRiads5+NJ6z6vUWfvjk7h1Hbz5OoLeIX2spDnE8636HT6Zjap3IUDysQo7DqDMuW05gAE2ACTCDuEkioAu6XzxjdpJ+8fIluzZrBSK0OUb5l7VrImi4d3Nzd8frDBwydPRsnL11C4/79MWTWbGnrKvKGz52Lhn37oG7PnpixenWIKbWHz5+jr/DkUZlG/fph1a7d0AqJIaK+K3fu4th//6HHhAlwcnGRdT568RIdRo1CkwEDUK93b+w+dixM8UfG1P/lO3agsbBtKEQneQ0fvXhBWT8EEkm9Jk/G7ceP0XnMGNHnvhgwfTqcXF11tjSVvGTrVpnXoE8fDJo5E5+Cp5LnbtiAfSdO6Gwv3b4tx6ZLEBGy/+zoKGIhf0kIkweq37Rpsm5n0SaJku2HD8vjxoJNl3Hj8PzNmxAFD585i8b9+kubIbNm4fajx5IVGRFH4qbf3ttPnzBwxgzKloGE9qLNm1G3Vy/QeCiP2paZYnPt3j10GTsWdG5aDBmCExcvilRgv5hOX7FzJ96I805trN27V6b/bOPu6Ynpq1bJvtYX522EuC4+fPkii9A5InbUHtWnbYcEIo2Lzl090ce569eDxLgsJDbkGSZuTfsPwMj580UK/zIBJsAEmEB8JsACLpJnlwSBqakp7KytfyhhbmaGMT16wN7WVoouEmM7xHTnyK5d0bNFC+F188VgISqSJ06CTUI0rJs8BW+EgJiyYoW8Cfv7B2D8kiUoli8vtgq7aeImfO7Gdez95x/ZVsuatZDE3h7ZM2ZEx4YNYWlhgU9fv2LonNloXLUq9i1ciJkDB2HroUM4c/WqLBN6s37fPtwS07xThQDaMWcOcmTKhMnLlyMsb44mMBAv374FTduO6NIVG4V48xOexNnCy6itd/GWLXj6+jXmDx+O7bPnIEPq1BglhIO/sMueIQPO6vVj099/470QKCRCqDwJqsdCDFuZm9NhiPBRjGvNnj0omb8A5om6LYTNITGleOTsWUzq0xd7xFRl1ZIlJU/yRlHhu0+eYNmO7ejRsjl2zJmLisWLY/rqVVJMUz4JHRLW1Dc6pkB9ePPxI0VBAnH17j249+wZFo4cKeqYg0xp0qC7EMvUBjGaJgRX46rVsFuMsWuTJliwaROor4Vy5kSZggVhIa4BOjflCheWdf5sQ57cb0KEU1tbhPA1F2OcILy71M9KwptLdaZNkUKe61xZssDT2xtDxTlLnyoVNovrZ8X4CXj8+hWmrVqpa4bGt0+I5hFdOqNLo0a6dI4wASYQ1QS4PiZgGARYwEXyPNx/9hRJEyeOlDV5p0Z07oICf/2FTGnTCG/QI3iJm3DfNq2lAEySyB7zhg4FPTtF3i6VWoVB7TugWfUasBQ38yzp06F2+fLCA/ZItpc3ezYhkFLJZ+4KCsFgYmyM1bt3I3+OHKheujSMjIxAZbo2boI14XiA6laogHHCc5NFeApJcHYSQtDZzQ1aESMbCrVZMnq0bNfexgZdGjcGPedH03PkmTp+/jyGdOgAEhWWFubo3qwZaIr3gfAk5hBCkwQbVUfTgR+FeCOhuX7/PkrCPxcuyHIkzmRCqE2FokWFMK2CzGnTSi8lebgGibZyZs4EGnuDypWliD1344YsOXbRInRr0hTlCxeBhbkZSOCVzJ9f5kVm883JCUf+OyvFG43HQpyDHs2by7YdhdDyFwKbBF+yJIlhLFiXLVQI24VXNHmSJEiVLJkU1omFwKZzQ0I2ojaJ1TjhhU2dPDmsLS0lx7dCTJLApeuF0h0SJQLVl0xcc5du3YJapUIP0Sdb8QEiuUMSzBkyFOeu34C/EMza9saKDxH55TWXVpvEeybABJgAE4inBFTxdFxRPqy0KVLqpi4jqtzExESIrRQ6s6ti+o3EUqthw6ANbYWnhzxdJOxUiiIETUo5HTddTK0u375denc8vbx1dYSOXL57FzTNpq2P9mv37QWJEfIahbYn8fnq3XvQtCdNU5JHi8QQia7QtnSsEoKBxArFKSQSIo72tJLy7pOn0nM4UHgLqV0KbYS3jMQoebHSCGFCgufF23egaUvyTNYQQvPfK1dlub3CU9SsenWqLsyQXnjztBkkBMkDRt5KaodCa8GRpqvJ20heKxKVJfLn0xaR+8K5csl9ZDYuYnqbPIztxDmh+rWBxvPw+QuYmBijYrFiIKHYffx4kEfxq7NzZKoO04b4XBPnb56YaqapUBoHTcvTNHdYBW49eiSvB22/aE9T22Trp/fcJYlBSuPABJgAE2AC8Z8AC7hInuN8wgtGooGeXwpdhEQN3dS1eUooA5VKQdJEibFszJgQYavw4iQS064kHrqOGwfyXpUuUBAZ0qQGrW4NVU2IQwUKWtetG6K+FUJcbBN1mgoBGcJYHMzbuBHLxTRjMjGNW1pM+b0TXrHwBIMw/+mvIsZDBktHhxwPTe81qFQJarUaFYsWw2Hh1SKhWEd4E83EFCMJMRJbjs7OoKlBqiOsoOglKkrQ0ZJQbdG07rCOnXSW5PXUHYhI6GORFOKXhJ82QVEUWAlP2A/nRwhUYkV2fVq1ws65c9Gmbj08efVKrkYmjyTl/WroO20adhw9iizp0qNonry4I6aA6RoIrx66fjIKURuif2PHgs61mYnp92JiHN8POMYEmAATYALxmcBvCLj4jCP8sSWys5PPodGD4vo3fypBCxYOnj4tpz/pOHQokjsPvH28Qc9JWVlYgAJ5XLQPrp++fBnGYlp0eOfOIE9SlRIlkU3c3EPWo4DEjzatuPA43bj/QNZF9VGg+sijp7XR39PzbzR117BKZSEa8qB2uXL62b8Uz5M1K8hDR4saqF0KZqamePjiBdQqtayrbJHCuHH/PmiqtUaZMnLhx1+ZMsnpUxJX9ByfNIxgkyppUlmWRBO1Q4GmmUk8GRmpoSgKSLD+e+VKiJpo4YQ2gdhSv8jTpk2j59e0cVsrK3iLKW46pvq14aGYDlYJsert44N/xJSxSrRF52e8mIoumjs3rgovGpVRFAUkTikemfDh82eM6tYNNcuWkee7WqlSPxSjDwXaxPzZc8jpaf3rh/pCi0ZE01qzEHvygIa+TkMY8AETYAJMgAnEaQKqON37GO78mJ49QashaZqTXt5LIoBWHS7esgVdmzaVYiKsLuUWgoeeO6PVgfRMFU2ndhYet7V79sgyebNlh7uHh3wmjlarHjt3Tr5rTr+ulA4OuHL7tlw4QJ4+eibtwfOn2HP8OEiYkHgbPHMmHgvvkH45bTylQ1Ic/e8/uZKUbvxTli+XbWvzf2VPU3UkysYtXoQXb9/K9lfs2AHioFYHXVKpkyUD9YlsVaqgtA4NGkib6qVLCaEXlBZRuyTO+rZpg5lrVkuvJPGhcdDUIz37R+UXiOlbOg80Feni5obj587jzLVrlCUDiZ0s6dJi44EDIPa0+ILKy0yxoQUidSpWQPtRo+QzgcRz/uZNmLZypRTN1IflO3fi71OnpJCiMd9/9gy0qEQUR2LhRX0vRNm/l6/8sDqW8kMHEoj/E4Kf+krlZq5ZE+JcUH9IDJMAfvfpE4rlywdaaEELHWgF8jfhwewwejTWhfO8Iwm3NmKa+YDob+i2+ZgJxCoBbpwJMIEoIxC5u2iUNRe3K8qQKhW2z5mDr05O8hUV9OqGy3fuYP7wEShfpIgcHIkF8pTIg+ANedsWf+CkmgAAEABJREFUCXFAD/R3EjfejiJOXix6hxyZJE2cCLSyccaqVWg/ciQu3LqFHi1awMzUhLJloHfOkddqmGifnluj1bCrJkzETjEV137ECPSeNAmdGzdBeA/vj+3VU67K7CTa7jt1Kro1bYZEwquoVoVxCQi3jhyD2MvGxYZEmEwTcfrtJgRrEeGFoteBdBDtP3z5UnAYTlky0MP2JHByZ8smj2mTOV066aVsUi3859/MxPSvVphRGQrEtlXt2hizcCHaibY2HzqEZWIKkfIoJBfidkSXLlgkhHR7we/vf09jWKdOlKULo7t3l88HdhD5k5YtwzDh7SRRrTVoX68+yhQogH6CDfG89/gJNgtBTM8JKoqCFUJw7ztxAm2FWKQVxa3r1EEpYU/laUVv85o1sXDLZtDzfZQWIojy+uyWiqn0U8JjSH2lumh1LXkBiTGVo0UcJNomr1ghRT09i0grVum66yiuH3qdSfG8eTGxTx8yl4HqD5pshhSDSRMnBi2yAP8wASbABJhAvCSgipejisZB0c101uDB2DV/vnylBN2M06VKqWsxY5o08rUbuoTgCHlxFgjxQa/BoFdRDG7fXk5DBmejVrly2DlvnqyTVhNWLl4cU/sP0GaDVkZS+V3CJoUQLJSRWAgweu0I1Un9oSk5Sg8rkDBaJkTI7gULsG3WLOTOmgXrp0yRrxMJbU9iYNvs2SAxqs1LIaYyd8ydK6crtWk0JUtjoTrJC2YjpiK1ebQnToPataOoDGqVSgpgWtUqE8LYkKitUqLEDzm0KpfaorFuFCKLVmnqGxXLmxc7hLilfOJE49XPJ0G5fPx4UP46MW56VQeNX2ujKAp6t2ol+ZMNPU9I50ybTwsx1opylEfnoGqoac8WQsBR+sB27bRFdHu6ZogdiUFKpHO5cdo02Rd6bjBVsqTy9TIpBWPKpzCoXTtQffUqVqRDKXzpQwC1Txz6tm4t07Ub+mChz58YFM2TR5vNeybABJgAE4hnBFjAxbMTysNhAkyACTABJsAEopqA4dXHAs7wzgn3iAkwASbABJgAE2ACPyXAAu6neDgzrhKghSN/L1kSV7vP/WYCPxDgBCbABJiAPgEWcPo0OB6vCCiK9rH+eDUsHgwTYAJMgAkwAbCA44sgkgTYjAkwASbABJgAEzAUAizgDOVMcD+YABNgAkyACcRHAjymaCHAAi5asHKlTIAJMAEmwASYABOIPgIs4KKPLdfMBJiAYRDgXjABJsAE4h0BFnDx7pTygJgAE2ACTIAJMIH4ToAFXEycYW6DCTABJsAEmAATYAJRSIAFXBTC5KqYABNgAkyACUQlAa6LCYRHgAVceGQ4nQkwASbABJgAE2ACBkqABZyBnhjuFhMwDALcCybABJgAEzBEAizgDPGscJ+YABNgAkyACTABJvATAgYv4H7Sd85iAkyACTABJsAEmECCJMACLkGedh40E2ACTCDeE+ABMoF4TYAFXLw+vTw4JsAEmAATYAJMID4S+HMBpyjxkQuPiQn8OQGugQkwASbABJhANOmkPxZwirEJnxwmwASYABNgAkyACTCBMAgoaqMwUn+eFJncPxZwKnOzyLTDNkyACTABJsAEmAATSHAEFBPjaBnzHws4xcwcUKujpXNcKRNgAkyACcQGAW6TCTCBqCCgGBkhumYq/1jA0QBVpuyFIw4cmAATYAJMgAkwASagJaCyttFGo3wfJQLOKEmSKO8YV5iwCfDomQATYAJMgAnEdQJqGwMXcDSFqrazj+ucuf9MgAkwASbABJhA3CZgML03SpoMUEWJnyzMMUVZzWo7OyhmPJUaJmVOZAJMgAkwASbABBIMAZWVFVSWltE63igTcFAUGCdPziIuWk8XV84EmIDBE+AOMgEmkKAJkHAzSuIQ7QyiTsBRVxWVFHGqaJzzBf8wASbABJgAE2ACTMAACajt7WHkkBTk1EI0/0StgKPOChFnlDgJjFOmhGLCL/klJDEcuDkmwASYABNgAkwgBgko5uYwTpUaaloPIGYkY6LpqBdwwb1WTM3kYGhARokSgwanROPDfMHN8o4JMAEmwASYABP4LQJcKLIEFLUaioUFpMMqdRox+5gixp1W0SbgtBDIC6eytZWDM06XHiYZMnJgBnwN8DXA1wBfA3wN8DUQZ68B47TpYJwsOeiRMcU4er5pQaujwttHu4ALr2FOZwJMgAmEJsDHTIAJMAEmEDkCLOAix4mtmAATYAJMgAkwASZgMARYwIU4FXzABJgAE2ACTIAJMAHDJ8ACzvDPEfeQCTABJsAEDJ0A948JxDABFnAxDJybYwJMgAkwASbABJjAnxJgAfenBLk8EzAMAtwLJsAEmAATSEAEWMAloJPNQ2UCTIAJMAEmwATiB4GoE3DxgwePggkwASbABJgAE2ACBk+ABZzBnyLuIBNgAkwgfhPg0TEBJvDrBFjA/TozLsEEmAATYAJMgAkwgVglwAIuVvFz44ZBgHvBBJgAE2ACTCBuEWABF7fOF/eWCTABJsAEmAATMBQCsdgPFnCxCJ+bZgJMgAkwASbABJjA7xBgAfc71LgME2ACTMAwCHAvmAATSKAEWMAl0BPPw2YCTIAJMAEmwATiLgEWcHH33BlGz7kXTIAJMAEmwASYQIwTYAEX48i5QSbABJgAE2ACTIAJ/BkBFnB/xo9LMwEmwASYABNgAkwgxgmwgItx5NwgE2AChkGAe8EEmAATiLsEWMDF3XPHPWcCTIAJMAEmwAQSKAEWcLF44rlpJsAEmAATYAJMgAn8DgEWcL9DjcswASbABJgAE4g9AtwyEwALOL4ImAATYAJMgAkwASYQxwhEi4DTaDTw8fGBm5srnF2cOTADvgbi2zXA4+Frmq8Bvgb4GtBdA27ubvDx9YlRCRjlAs5dDOLDx/diUE7w9/eHoigcmAFfA3wN8DXA1wBfA3wNxNtrwM/PD05Ojvjw8QM8PT1jRMhFmYALDAzEl6+f4SE6niSxA5IlTQ57+0SwtbGNjsB1Mle+Bvga4GuArwG+BvgaMIhrIJHQO8mTpRC6xx6ubi5wdPwGmo2MTiUXZQLu67evMFIbCeGWDCYmJtHZZ66bCTABJsAEmMBvEuBiTCD6CJiZmoGEXEBgAJycHaOvIVFzlAg4V1dXUZVGKM9EYs+/TIAJMAEmwASYABNIuAQckiSVawE8vaJvOjVKBJy7hxvs7Vi8JdxLlUf+KwTYlgkwASbABOI/AdJFLi4u0TbQPxZwXt5eMDIygrGxcbR1kitmAkyACTABJsAEmEBcImBmZia6q4Gvr6/YR8lviEr+WMB5CwFnZmYeolI+YAJMgAkwASbABJhAQidAawL8/AxUwPn7B8jFCwn9JPH4mQATYALxngAPkAkwgV8ioFKpERAY+EtlImv8xx64yDbEdkyACTABJsAEmAATYAJRQ4AFXNRw5FpihgC3wgSYABNgAkyACQgCLOAEBP5lAkyACTABJsAE4jOB+Dc2FnDx75zyiJgAE2ACTIAJMIF4ToAFXDw/wTw8JsAEDIMA94IJMAEmEJUEWMBFJU2uiwkwASbABJgAE2ACMUCABVwMQDaMJrgXTIAJMAEmwASYQHwhwAIuvpxJHgcTYAJMgAkwgeggwHUaJAEWcAZ5WrhTTIAJMAEmwASYABMInwALuPDZcA4TYAKGQYB7wQSYABNgAqEIsIALBYQPmQATYAJMgAkwASZg6ARYwEXmDLENE2ACTIAJMAEmwAQMiAALOAM6GdwVJsAEmAATiF8EeDRMILoIsICLLrJcLxNgAkyACTABJsAEookAC7hoAsvVMgHDIMC9YAJMgAkwgfhIgAVcfDyrPCYmwASYABNgAkwgXhOIdgEXr+nx4JgAE2ACTIAJMAEmEAsEWMDFAnRukgkwASbABCIkwAZMgAn8hAALuJ/A4SwmwASYABNgAkyACRgiAYMUcBqNxhBZcZ8SGgEeLxNgAkyACTABAyVgUALu1u07GDF6PLr06IPFy1bCw8NDYrt2/QaWrVwj49rNjVu3pQ0dv3v/HmMnTsHdew/oUBfef/go0y9dvirTtu/cLY+/fP0mj7WbU/+eCUr/8lWbBNKQ8xcuxbhJ00T8u6CkPlFb2rB6zXo8f/5Slpu3cAkOHT0u47R59/4Dxk+ehs969VI6BybABJgAE2ACTCD+EoiJkRmMgHNzd8c8IZgqli+H4YMH4KsQWQuXrJAMXN088EGIMXkQvHEX9u+FQKJDHx9fvHr1BstDibzN23bIdKqb7EhIkd3lK0GCjtICAwOxd/9Baefn70dJMnh5e+GmEJQvX74SQtJTptEmQNhTHUUKFkDpksURKBInT5+Fp8+ei+MS2LP3AFxcXED1rtuwGRbmFkjqkERY8S8TYAJMgAkwASbABKKGgMEIuDt37kGtVqNUyWLImDEDBvXvg3p1a4Xwfv1syCqVCu7CY+fv768ze/niFUxNTXTHFEmUyB5nz13Q1fvk6TMEBARQVohw9+59WFiYI3vWLNi4eWuIPDooU7oUKlUoj84d2iJrlsx4+OgxChbIh5w5smPNuk24e/8BXr95gz49u5E5BybABJhADBLgppgAE4jvBAxGwBUvVkQKph59B+LM2XNQG6mleFIUJVLnwNTEBLY21jhx8rS0v3P3Hsij5pAkpPercKECcHJyxvMXQdOeFy9fQTYh0mSh4A09g7du42bUrlENnTq2xaUr1+Dn9907R2YkFP2EWPTy8sanT59gY21NyWjZvAnu3LuPBYuWobIQeKEFpDTiDRNgAkyACTABJsAE/oCAwQg4RVGwYM4MtGzaGNt27kH3Xv1x8NCRSA+NnlLr06s7tu7YLacvN27ZjqaNG0JRKSHrEIaFCubHhYuXpSg7c/Y8qlSqGMLGydkZNC1btUolJLK3l57BL19CPjfXf/BwdO7WG91790emjBlRpnRJWUfSpA6oLzyHNIXaqGE9mZYQNzxmJsAEmAATYAJMIPoIGIyA0w6xQvmyWDx/FoYN6odde/bjm6MjzM1MQR4vrQ3tvb19pLCiuDakT5cWNJXq7eMD8rIVElOa2jz9PT27duHSFdy8dQcpkidD+nRp9LNx7vxFOa3aSQi0zt37yPjy1WtD2MybNQ1tWjaT7bVv2zJEnr29HdKkThUijQ+YABNgAkyACTCBCAmwQSQJGIyA27R5O7r06Cu9YoqiIFmyZHIIJNwypE+HDx8/4eu3IC8YTXGePXceObJnkzbaDYm33Dn/wpDhY5A4cSLY2tpqs0Lss4kpU0sLC6xauwEFhTdOP9PfPwD7DhxE86aNsGDuDBlmTp2IV69ew9Pz+2IGtVqN8uXKIIPo287d+/Sr4DgTYAJMgAkwASbABKKVgMEIuKZNGsgFB/0GDcfAISMwZMQY0PNqSR0ckDRpUjHNWR4jRo1H/8Ej0KvfYHh6eKFRg7o/wOnWpQPoVR8d27X+IU+boCgKSpQoCinUg2oAABAASURBVF9fX1SuUE6bLPefPn8WXjU1KlcsDxJ5FBwcksBMeAEfPHosbbQbRVHQqUNb/Hv2HGgxhDad90yACcRhAtx1JsAEmEAcIGAwAs7Y2Bizpk3C4P69Ua9OLYwePhjdOneAoigiAE0aNcDkCWPQrHED0PTqpPGjQGWIcWoxXTlu1DCKwtzcHFMmjkGmjBnkMa0CLV60iIy3at4UNatXkfHqVSph+uTxsLKyEsLRVJQZCxKLieztMGncKCHiQqIZP2YEMqZPDytLS2lraWkB+qEp2OlTxiOZEJl0TKFA/nzo1aMLRTkwASbABJgAE2ACTCDKCYRUKVFe/a9VaGpqivRiSrJ0qRJIkyZ1iGfcaHqUPGFFixSSeWZmZrrKTYT4S548me44RfLkOgFGq1C1YoueTbOxsZF21FbSpA4yrigKUqZIDiMjIykAkyVLitA/yYRAo/LUD7KlvdaG2rCxCVqFSmkWQkRSGsV/I3ARJsAEmAATYAJMgAn8lIBBCbif9pQzmQATYAJMgAkwgZ8Q4KyERIAFXEI62zxWJsAEmAATYAJMIF4QYAEXL04jD4IJGAYB7gUTYAJMgAnEDAEWcDHDmVthAkyACTABJsAEmECUEYhnAi7KuHBFTIAJMAEmwASYABMwWAIs4Az21HDHmAATYAJMIMYIcENMII4RYAEXx04Yd5cJMAEmwASYABNgAizg+BpgAoZBgHvBBJgAE2ACTCDSBFjARRoVGzIBJsAEmAATYAJMwDAIfBdwhtEf7gUTYAJMgAkwASbABJhABARYwEUAiLOZABNgAkzg5wQ4lwkwgZgnwAIu5plzi0yACTABJsAEmAAT+CMCLOD+CB8XNgwC3AsmwASYABNgAgmLAAu4hHW+ebRMgAkwASbABJiAlkAc3rOAi8Mnj7vOBJgAE2ACTIAJJEwCLOAS5nnnUTMBJmAYBLgXTIAJMIHfIsAC7rewcSEmwASYABNgAkyACcQeARZwscfeMFrmXjABJsAEmAATYAJxjgALuDh3yrjDTIAJMAEmwARinwD3IHYJsICLXf7cOhNgAkyACTABJsAEfpkAC7hfRsYFmAATMAwC3AsmwASYQMIlwAIu4Z57HjkTYAJMgAkwASYQRwmwgPuDE8dFmQATYAJMgAkwASYQGwRYwMUGdW6TCTABJsAEEjIBHjsT+GMCLOD+GCFXwASYABNgAkyACTCBmCXAAi5meXNrTMAwCHAvmAATYAJMIE4TYAEXp08fd54JMAEmwASYABNIiARiS8AlRNY8ZibABJgAE2ACTIAJRAkBFnBRgpErYQJMgAkwgZghwK0wASZABFjAEQUOTIAJMAEmwASYABOIQwRYwMWhk8VdNQwC3AsmwASYABNgArFNgAVcbJ8Bbp8JMAEmwASYABNICASidIzxTsBpNBrcuXMHAQEBEtS7d+9w5coVGf/TjYuLi6zL39//T6vi8kyACTABJsAEmAAT+G0CBiXgHjx4gJs3b4YZ3NzcIjXI48ePo3bt2rhx44a037p1Kxo3bozAwEB5/Cebm6JvVBcJuT+ph8syASbABGKFADfKBJhAvCFgUAKue/fuaNKkCdq0afNDuH//fqSgly1bFkWLFkW2bNkiZc9GTIAJMAEmwASYABOIawQMSsARvNatW+P27ds/BBJllB9RMDU1xfbt22FtbR2RKefHPAFukQkwASbABJgAE4gCAgYn4CIaEz3j5uTkhPPnz+O///6Do6PjD0Uo7WdTpvR83Js3b3Dw4EFcunQJYU3PatuhKdmrV6/Cw8MDiqL80BYnMAEmwASYABNgAtFNgOsPTSBOCTgSVWPHjkWBAgXQoUMHdOrUCQULFkTHjh1DjIvSSMSFSAw+IPHWqFEjlCtXDoMHD5ZTtblz58a2bduCLQBqZ/78+cifPz969uyJli1bIleuXPj06ZPOhiNMgAkwASbABJgAE4gtAqrYavhn7ZKACh3I/vLly9iwYQNWrlyJhw8fykDTpSdOnMDHjx/JJMIwZMgQ3Lt3T3reaNHEo0ePMHz4cIwcORLu7u6yPOXPmzcPkyZNwuPHj0E25IkbOnSozOcNE2ACCY8Aj5gJMAEmYEgEDE7ArVmzBlmzZg0RWrRoIZkVLlxYirZKlSrJY9rky5ePdjhy5Ijc/2xD06qHDh3CxIkTkSRJEp0p1U+eudWrV8u08ePHI2nSpGjVqpU8pk3mzJlRpUoVinJgAkyACTABJsAEmECsEjA4AUevADl8+DD0w6xZsyQklUoln0Oj6c4uXbqgR48e2L17t8z79u2b3P9sQ540Ly8vTJgwQU6P0hQphdKlS8tiL168kK8boWfeihQpItP0N1WrVtU/jOE4N8cEmAATYAJMgAkwgSACqqCd4WwdHBxA3i79kCpVKtnBp0+fgoTV5MmTkSxZMqRNmxbksZOZkdj4+vpKq9GjR2Pt2rW6sG7dOuzbtw/9+/eXAo6mb62srKSt/oZXturT4DgTYAJMgAnECQLcyXhJwOAE3M8ok+ctUaJE8iW9NA06bNgw7Nmz52dFQuSRKFSr1TAzMwNNvYYO6dKlg5GRETJlyiRXuIYoLA7oOTix418mwASYABNgAkyACcQqgTgl4GxtbUFfY0UiS0tty5Yt2miEe0tLS5QoUQIzZ84M8eoQmq7NkyePbhEDLWr48OEDaCpVW6mzszMOHDigPeQ9E2ACkSfAlkyACTABJhDFBOKUgKtevTo+f/6MUqVKoX379qBjWpX6K0xmzJghRSC9RoS+9aFBgwbo168faK+dNqU8aqNZs2aoVauWzKPjrl27/kpTbMsEmAATYAJMgAkwgWghYFACjqZF6btGwxspTYH+888/8r1vtEq0Xbt2OHbsGJYvX446deroii1btgw2NjbyuG7dulgu8hVFkccpUqSQCyQGDhyIDBkyoFixYvLVJPR+OWkgNuTho2frqF6aZqXn7jZt2iTbpTR+Fk5A4l8mwASYABNgAkwg1ggYlICj1aDZs2f/KYw0adJI79v06dPRtGlT0LQorQ7NkiWLrhwdm5iYyGNKp2NFCRJwlEjP0dGrQ6gOei8cfU2XonzPJxt6Vq5ixYryXXD0rF2+fPnk13NRXdq6yY4DE2ACTIAJxF8CPDImYKgEDErAGSok7hcTYAJMgAkwASbABAyJAAs4Qzob3Bcm8AMBTmACTIAJMAEm8CMBFnA/MuEUJsAEmAATYAJMgAkYNIEIBZxB9547xwSYABNgAkyACTCBBEiABVwCPOk8ZCbABJhADBDgJpgAE4hGAizgohEuV80EmAATYAJMgAkwgeggwAIuOqhynYZBgHvBBJgAE2ACTCCeEmABF09PLA+LCTABJsAEmAAT+D0CcaEUC7goOksfHP3w/KNPFNXG1USGwPv37+Hi4hIZU7ZhAkyACTABJhCvCBiUgPMP0ODcA3dM2fUJ/7vmii8u/iFg+/hp8O89d0wT+Udv/JgfwjiGD0Zu+YDak5/HcKt/3tw3R0dcuXIFa9etw40bN/D169c/rzSGahgxahQO/P33T1vz8vLCg4cP4O7h8VM7Q80MDAzEq1evQOPQ9tHb2xs3bt7Aug3r8fzFC5CNNi8ye3d3d7wQ5bS2Go0GL0Ub27Zvw/F//sHHjx+1WeHuHcV1c/7CBWzfsR0vX75EQEBACFs6vnX7NlatWY0rV6+C2gxhIA4cnZzkuaHzQ+HZ8+f49u0bqD8iW/6+fvMGDx8+DJEmM4I3T54+lXVQe8FJ8WTHw2ACTIAJ/JyAQQm4SqOfovrEZ1h27CvazH+FrD3v4/5rbzkCfyHuakx4hjpTnmOJyG8x9yXy9H/4g8iTxvFk03rOK0zeEfHN9HeGSzfJo8eOoVWb1li8dAkeP36EmbNnoXXbNjh3/vzvVBnpMo8fP0avPr1/WXhEugE9w+07dqBvv37Yu3evXqphRAcNGYwPHz+E2xkfHx/MnTcPnbt2wUshksiQ0pq3bIHZc+fiuRA8AwcNxOIlS8IVOFRGG+icP3jwAE2bN8OMWTO1yTh48CC69+iO/86dx9atW9G2fTs8fvJEl+/r66uLU+TGzZtoJa6TtevW4ubNmxg4eBBGjRmNgGARR4Kyb/9+GDd+HF6+eIn58+ejUdMmP4i406dPYcDAgZg4aZIMI0eNlG0vWbpUd20sXrIYffr1xdn//qOmQwRqZ8DAAfL86gvcEEZ8wASYABOIpwQMRsBdeeKJKy88sb5POrxekRNPl/wFCxMVFvzvi0S//5ILLj71wLqeQfk3ZmeHq1cA+q18K/Mj2gRqfm4hnBAIbRKpMqEL/byZMHMDwmno1itPPP0U8uaprSCcItrsCPd37tzBgkULsXDefKxbsxZTp0zFlk2bMXHCREyYOAFubm4/1EE3TP1EEgSh0/TzKU42tNcPnsIrRiJOP00bJ3sK2uPQ+5/lhbal4/MXzqNMmTLCs3Q8UiKHyoQOEY0xtH3o4/D6/FR4j3x9wj6/xL9VmzZ4/vJFiOpu3boFtVqNTes3YMK48di1YycOHzkcqankXbt3Y/DQIShWtJiuTg/hmVy4eBEWzl+ARQsWYM3q1ahWrRqmTZ8mbZydnVGnXl2QN40S/Pz8pDDr2L4DVi5fIa+b9evWga6njRs3kgk+fvooBeeeXbsxaeJEbBLpVpaWOHnqlMzX36ROnVped3TtbduyFatXrsL/Dh8Stid1ZokTJ8batWt1x9rIIWFnZmYORVG0SbxnAkyACSQYAgYj4MyFWBvbOAWq5reR8O2t1CiQyRzXn3vK46wpTTGzdSrUL2Erj9M6mCBTEhPceuMlj0NvFgvhV2/yM7z67Id8fR/CusUtNJn+Aq6e36d6puz8iFGb3mPPeWfYt7yNMZuCvCFuXoFoMu2FLGPX4jZWHKVpnZAtrDn+DUna3Ebi1rexWsTVeiQ/O/uD2qZ6taVoOpjSnn/6/pyco7s/Sg19DBvRdtpO93D6jrsQGYCHd6As/+yzL3acd5LxE7eCBJWLRwDqCy8kjSdDl6Ay2jZ+Zb985Qo0qFcfmTNnDlGsUMGCSJYsOfbu2yfTR48dgy9fvmDgoEGoVqO6nOKijP/OnUO9BvVl2rARw0NM8ZFg2X/gAOrWr4/qNWtg8pQpOu8M1Ttc2FMdQ4YNxSEhPihOZdauXyftqZ014oZNaZRHgUTUqtWr8H/2zgMwymJdw+8m2U1vECCEEgjSEoICAh7KRQX1iEf6QVQQRSkiIEhThAMB6SpVQpHQq4AURQFFiKjXcjgWQMpBAiRAQksiBNLgzjewm910JMndLC9mZqf/M8//4775vpmfJ578O9p17ID9yt3rbA1dGmULJ0+d0u7HIa8PRnJyMg4cOGBpEXfmDMYqC5GlQCUuKPfd22NGq9StH7n+1GnT9Br79uuHU2q8GTNnKJfdYd1gxcoVEBGhM7ejadOn49tvv9U5sZaJZUrm3KFzJxw6dEiXizt1sukAAAAQAElEQVRR1p6SkoLJSihln4c0EgHXrdszmPX+DMlawslTJ+Hre+vvgBQ6KzFndDFCriX5/ELmjUx8tG49mjdrZmlmcjVhfESEzXPwxONPIDY2FiLWPDw84OXjA28vL93no40bEBAQgM6dOum8RF6eXnh71Cjs/GKXZOHj7YM3R4y0EVbh4eH44ccfdH1+UYUKFdC0cRN9f83tGj/YGAnnE9TfDdvflpYuW4YhgwfnKDf34ycJkAAJODIBJ3tZXL1gN4zoVB4erllTupCcieDyJj3F8Gru6N82QKclylAu1ZiL6fD3cJFsjnAk9jp2HbiC+kN+h7P6BT0syA2f/pyMcCXm0jJufRH8evIaIndcQI85J/FAsDtMaqgrSjyF9D2I7b8ko0UtD3i5OWHI0liMWXXGco3pG+MxMCoWJjVw85qeGKzSH32baKm/nn5DX/v0+TRLWWr6TV2WosShFGaq+dfsfwj/OXUN7Rv64mpqJp6adBzLdl9EpjIHHjydKs10kHSiEm6yZpnbD8dTMLFbRTQO8dB9jsZd1+0KG2VmZkL2Dj3x+OO5dlmuLCov9Oih63799Vf0UeIlMDBQf9G7u7vjy692K1E2EUOHvKEFgclkQt9X+0FElnQS8bVq9SpEjBuHlctX4PCRw3i+R3epQkj16miivqAl87eH/obgqsGS1EImOjoac2bPweIPF2PP3j2YNHmyrpNo/sIFEJfv5ImTIGHqtKkWMSn1uYV169bh4Ycfhqey/jT7WzN8uftLS7NrSjz9pqyQlgKVSL1+HbJeldQ/r/TpjR9/+hGzlZWyd+/eeEO5K3d+8QWSbx+cOBETAzlIAas/h34/hPO39xE+1/15ZGZkYONHGzDqzTd1fxGJRqMRMh/pVrdOXQsPyZtDUFAQOnfsZM5aPls/2lpfM/m2hVRETLoSZmKlsjTKI9Gt6zOQ+2ddLeLvISuLnNSJddRHiTaZp9zbDWvXISQkRKoQo9Zct25dnbaOgioGQax1UualxF6LFi0kaQnHjx+HrNVSkE9C9uCJCDQ38fb2Qrly5SB79MxlIq5FCNepXdtcxE8SIAESyI+Aw9VlqSU7W1r0wSv4TYmbbs39cp3ZN4evaqHz7otBudabCzcMr45/z6yDH96rjY3DquOCsnqt3nPJXI105Ys8NjcUeybXxBgliv6lhNpNw02cWVwPOyJqIjaqHt7uVAEzlEXv3OV03e/dbQl4ppk/4paEY9vYGohVbX3cnHVdYaM6A35XFo6bOKfGXz28Gs4vr4/Qym5Y8sVF+Lg749j8UNRQ4rWruo6kOzfzQ4yyyF1Xwm9k+woY3L481o2sjj1qjtUquOZ62YULF+LIkSM56s6ePQtltoBYO3JU5lLwUNMmGK4scPJFLxaZyMhITFEuV3FNijUoYuw47dYz71Nq2KABZs2ciQfuvx9irflgzlxtAZOh71dlHZVlTtIdO3RAWGgoZPP63r17VZ9ZqKksgpUrVcK706Yj+utobdn7r/ry3759O5YtWYpGykIofZYsjoJYsGScvMIvv/6CNq1b6+pHHnkEe9Q15ItfFxQQiTA7ffo0xL1cp04dPKiuK+69G0r8FtBVV8vcxIr2yiu94e3trUVa1OLF8Pfzg6urKzq0bw9hKZ9PtW2r+xQmKlOmDMaNHYsu/+yirZWr16zGWuX6dnFRv30UZoBCtFm2fBmGvvFGri3l8IK4PbNX+ql1ZSixGh8fn70KwlwOxzypXLPZK2U8OaggQSyUYvGNjYvFM127ZjW9Cf3LwiarfYwfzJuHsLAwLc6zGjJFAiRAAvcOAbsUcFeUlarnrJN4SFm3Ojzkl+NunL6Qho5T/9AWqKa1PXPUWxeIG9ac/3sjH5T1dMGPf1wzF6FWoBuCyhot+TXRlxHoZ4SPR5Yge6tLIJydDPjuSAoOnrqOK6k30KtNGagi3c9XtW0Zmv88dEOrSITk04184a3EmhTLWP87tRb2Tq4l2VxDSKArHrrPA6PXncV9yno3PCoO1ZTIM7koE2MuPcSltWPXzhw1YpGSQhEZ8llQePyxxy1N4uLitBibNWc2Xhs4UIcBgwZp64vZRdlACTgnJ2fIF+5aZQWLORljsc5ZBrJK7Pv6a517S7nhzGNGTJig9yT+duAA5Jrly5fXgkc3VJGHcu1ltyapYsvPf37+GSIO6ofX12WNGjaE0WiCWPl0QQHRvn37IJYkCeamIlZFkJrz+X3K/Lr+sysGDhqIfv1f1adlA5Vr2lm5PPPrV1Dd/v37MeGdd7BuzVpt/Rz99mh98KSoXqfy7vvvadenuC1zm4u7mxtEmGavM7tw/fxt/76KeBNL5GOPPQZ/f//s3fRYr/R+BRJkf55JWXPFapu9bY0aNXRb83U+3/G5FnU5BrTnAs6NBEiABIqQgFMRjlUkQ51PSscDQw5DGcawZmg1LZysBz52JhVNRhxFeV8XbP9XDeuqXNNG5ea0rnA3GZCurFjmMmvxo37Rx3XlXnXJ1kf2SIvASlFuzutp0gpwdbFF527l+jWPbf15U8sR6xKgrLet1cRZLmLbxCYn1Z+PvQ/RE2riqQY+WLbnIkL6H8ScT24d9EC2P2I96t/v1Wyl0F+kHh6e+O3AbznqpOA/P/+MU6dPSVIHcaXphIqup95y7Q58bQAGDcgKYpHr0rmzagHMVuKuT98+OB17GuJWXbhokS7PK0pNS0XFwIo248nYc2bOQqhy12VmZijxlSWyzeN4KledOZ39c+369chU1rLOylL1j3ZPo12H9khKSlRu1KzN8dn7WOcNTk66v3XZnaZf7tVLWw2f/PuT+FRZEGUecgjhTsexbj9x8iT0eqmXvociLv+nZUvtFv1qz1fWzf5Set78SOzcuVNbHV3ysOiJBVD2x2W/QGJiop6Hq8nVUiX3vrd6DkS0DhowUAtDS+XtRJUqVfHZp9t1+GTrNoxRglSE8u1qy4eHEuzidp6hLLuXLl9CWlqadqtaGjBBAiRAAvcYAVsV8v+8eHGb1h98GJ5uBvw4vTbKKZFmPaXtPyWj+aijqBpgxPdTatvsl7NuZ50+e+mW21PKTsSnIS4xHXUqZn3JSLk5iB3r0XreuPhnhrlIf3596IoWfU1reSIs2BUiCvf9fkXXSXRTabr9x1MkqYOr8RbWeKv32P0aY7tPTcTapu8TkWElJvvOO4152y/oMSQywIC0jBuS1CE55QbkNG6tSm6Y1bsyzi4NR5CvEeM/Oqfrs0fyBW/1RWxT3Va57TZs2GhTJhn5YpTXOSQlJkk2RwgODoZYSXx8fVC7dm1LEBeauGRlX9L2zz7D3Nlz8PrAQXju2WcxIWJ8jnGsC8LrhSP+fALEymIes2bNmhArjKwhIKCcPkhh3Sc9PR0XzucuXKXdsaNHMGH8eKxYvsISxo+LwL/3/1u7ZYWLjCFtzcFsQZR8q1atdDtZj+QlnD13zuY9eSajEdeuZ91XGc/sQhTLU0xMjBYZ7du1wwLldm6nPqdMmypDWYJ6dCzpghIyZmbmjRxi1kmJTWdn218GChrLuj5TCV255598+qm27Mn+N3P9aeVG7tSlM35S3KSsTes2+Omnn7RVVPLmsOnjTQgOrmbOanY9Xuypn5Ulyt0tIs5SaZVwUr+VSJ0Eg8FgVZMz2bdPH+z7Zh/eeWciOnbomINDzh4sIQESIAHHJeBkL0v77vBVtJv8hxI0gIio2Z8k6BOio1eeQWr6TS1cnp0RA1dlHWtZxxPTP47X9QW9J61NxH8xa1sCIpUwekKlXdQXRtcWtm4eawaTXwjCpSuZaDz0MFbtuYTxa89C3j3XsJq7dle6KXHWQKXHqvI3PozFuq8v47Fx/8WRs7csUzKWCM8g5YaN+uoi5KTru5sS8MLsGKmyhC0jQ5B0PRNdppzA1h+S8PLsk1iz7xJSrQRbJeXa3fnLnxi5JA479v+JpKsZ6Dn3JFqPOYrPlJhdvvsSEpTYbKV4WAYuZKJb166QE43itjqvhJCIg2PHjmmXqFhZ5NRgbkO5KBegfIlPnDTJcohg9+7deOnlXriceFlbYUTg7f06WneXl86OeOtNnTZH5j1Ucrjh0uXLaNq0KYKVJea999+HtJd28mqL0WPGSBJ169RBlcpVMHLUW/q0ZboSb+/PnAHk8YW/a9cuSJuGDRrC38/PEpo0aQIRhSIwZVO87NlavmI55I/sCxQLlKQllC9XDuK27fdaf3y+Y4c+lTt02FB9wlLqJVSvHoJvvvkGcjBBrE0rV620WO1ECL+q+i5a/KE01ZZI2ePVuHFjnZfIzdVNCRLV//ahBynLLxgMBnTq2BGyR80sFOXFu+Iqbvzgg7pr1JIoDHp9kN53pgsKiK5du4aXlTCSfYaTlDBKUM/CkaNHIUGEnTBo1LARqlSqrEeS5yK0bigmTZmMxMREXbZ56xbsjY7GgP79dT4hIUEfWgmpVh2DlIiXlw3LeHKQQTf4i5Ec1EjLyMCBgwdgPmTzF4diNxIggTsiwMb2SMBuBNzlKze0lSsl/QYWfnlRHxqQgwMSxOV5WYmqDOVXvZSSichdWfWRO7MsVrkBHtauAiLWn8OwFXFIV+7RbW+FoHKAKbemuqxWJVfsjqiJM5cz0GfBaUzdkgDZi7cz4j6YXasfqzEeDvXGAjXPXvNOoYynC3q0KqP7S6Q0ItYOqwaD+m/ipnhM2xqP+b2rSJUlNA/1xIK+VbH38BWIMF37XSIGti2P19qWs7SZ2jMIfu7OmKvWePZyGqqUM+GTUTUQcz4NXd47gUFRsWgV6oWlg6tZ+hQ2IVaWpVFL9Ab753u+gKfbt8Ogwa8rK1gIxGKS3zgDletULGWyt6lj504Q4SMb6/39/CGWlPHK4rZ69Wp06NQRXbs9gy6dOtsMF1C2LFq2bInBQ4ZAToqKBWnqlCk4ceIPiLWnnXJ3itgZO3as7mdUlq7xERFIVGJPxpTXk5iMJtQPD9f12aPNW7YoC02HHBYauc5jbdogOnqv3vweoSxyq9es1fPsP3AAxo0dZzPUogUL0bJFC6xSaxFxK25iEbdQQkoaygEEeQ1Ljxd66DEuXrwEOfAgdXJQQQ5v7FDiT9b01NP/gMy5X5++Uq3DSy+9hNWrV2nxqwsKET3/3HNo3qw5uivr1lPKNTwvcp4+7RsYGKh7f/vdd2itrGQGg0HnC4pEMJ+Ji8VlxXbEyBF6z57s25OQkpKiD1y8PWqUzYGX8epeiCX22e7PQ9zC65W7evq06ahVq5a+XFJysn5p7/c/fK/FpIwlYWQ2Ia8b30EkVtOePXrAzc3NZj/kHQzBpiRAAiTgMATsRsC1fdAbV9fcn2vwcnPCi63L5FoX+2G9fG+G9DsbFY6jc0NxZF4oWoZ5WdqvHVYd30699aVjKVSJprU8cHJRGI7MCcWJ+WH4bGwNyHvqVJX+8fN0xtbRIfgjMkyHtcOrYX6/Kjg4p66ul6hRDQ/EvdoOnwAAB8BJREFULAzDYTVGzIIw/LOlv55/PWW9k3oJz7XyR+yiejg0u64+9Tqxe0WYrA4khAe76znHq/m/2LqsdMEj4V6IWxyO42otclJ286gQeLn/tdsoe43+NXoMPtm8BVEfLobsQXpzxEgb4bPl482oV8+WsYi0kcNHYP3adVgwfwHWrFqtT1nqCapITp9u27JV10kbeV3J59s/UzVZP7LXafOmjyFuMSmVuUTOi8TypcuwJCoKkR/MQ6WgIKnSQdershXLlmONEj1DBg/WJ1V7dO+u662jD+bO1fvErMvM6Z4v9MSsmbN0tomyhm3etAkLIudjvRJyDR54ADJvXamipKQkvNLrZaxYtgwjhg9H1apVkZiUCC8vT1ULLW4mKLG6asVKPe9hQ4fqV46Iy1Qa1KhRQx80WLRwoWb17vTpNsJDuAjfjR9tkOa5BhcXF+z8fAfMr+4Q9rL27Vu3YYm6Z/Ky3KZNmuq+WoydOaMEXjOdzyt69NFHNV+pF4ukjJ9bkNOz0iZ7cHd3x4hhw7F54ya9bnkJb72wMEszOUmc23jy0mFLI5Xo1LETRCSrZJ4/UydPgbzCxdzg+Wefw1b1vBoMBl0kQlmu5ZXPfkjdkBEJkAAJOBiBv/bNX8oguBoNEHekyUocFbQEsbZVDjDqwxJ5ta3g5wIJYnHLrY1ct4oawyOfAw6eSpwGK8uanGTNbQwZ2yubQHNSdy3Q32hzUja3voUtM5lM2l0o4qCwfaSdiKryytVoNBolaxNkrArly2triU2FVUY2potVzFxkMBj0a0fKlikL63JzvZQFBATA18fXXHTXn2LNkb17ua2h36uvYsXKlRBXq1woaskS+cB9Ne7TnxIZDAaIVc7Pz0+yOYLBYICsJy8xJNcV/jk6FlAg/cS9aTDcEjLSXP75q27PdNMMJV/cQcSTrL24r8PxSYAESIAEchJwylnEkpwEWHIvEpgyeTLkn6nq2Lmzdu3uid6Lme/P0JY3e+QhLmXuDbPHO8M5kQAJkEDRE3BYATejd2UkrqiPvCxbRY+SIzoaAdnPJu9bmz9vHuYr9+6yqCWoWLGioy2T6yEBEihOAhybBIqJgMMKOGflezTegcu0mPhyWAcgUKlSJe1iNhiy3JUOsCwugQRIgARIoBQTcFgBV4rvCadOAkVJgGORAAmQAAk4IAEKOAe8qVwSCZAACZAACZCAYxMofgHn2Py4OhIgARIgARIgARIocQIUcCWOnBckARIgARIoDAG2IQESyJsABVzebFhDAiRAAiRAAiRAAnZJgALOLm8LJ2UfBDgLEiABEiABErBPAhRw9nlfOCsSIAESIAESIIHSSqAE5k0BVwKQeQkSIAESIAESIAESKEoCFHBFSZNjkQAJkIB9EOAsSIAEHJwABZyD32AujwRIgARIgARIwPEIUMA53j21jxVxFiRAAiRAAiRAAsVGgAKu2NByYBIgARIgARIggTslwPaFI0ABVzhObEUCJEACJEACJEACdkOAAs5ubgUnQgIkYB8EOAsSIAESsH8CFHD2f484QxIgARIgARIgARKwIUABZ4PDPjKcBQmQAAmQAAmQAAnkR4ACLj86rCMBEiABEiCB0kOAM72HCFDA3UM3m0slARIgARIgARJwDAIUcI5xH7kKErAPApwFCZAACZBAiRCggCsRzLwICZAACZAACZAACRQdAUcTcEVHhiORAAmQAAmQAAmQgJ0SoICz0xvDaZEACZAACZQkAV6LBEoXAQq40nW/OFsSIAESIAESIAESAAUcHwISsBMCnAYJkAAJkAAJFJYABVxhSbEdCZAACZAACZAACdgJASsBZycz4jRIgARIgARIgARIgATyJUABly8eVpIACZAACRRIgA1IgARKnAAFXIkj5wVJgARIgARIgARI4O4IUMDdHT/2tg8CnAUJkAAJkAAJ3FME7lrAGe4pXFwsCZAACZAACZCA4xAo7pXcRHHppLsWcM5GF6RnpBc3AY5PAiRAAiRAAiRAAqWKQGZmJpycnYtlznct4Nzd3HHtWkqxTI6DkgAJkICjE+D6SIAEHJdAWloaTEZTsSzwrgWcm6sbbt68idS01GKZIAclARIgARIgARIggdJG4GrKVTg7u8BoNBbL1O9awMmsfLx9cenSRUkylDoCnDAJkAAJkAAJkEBRE0hKSoSfr19RD2sZr0gEnKenpzYRJpyPtwzMBAmQAAmQAAmQgAMT4NLyJHAu/iw8Pb3g6uqaZ5u7rSgSASeTKFOmLFxcjIg7E8s9cQKEgQRIgARIgARI4J4icOXqFa2DPDw84evjW6xrLzIBZzAYUMa/DAICyiEpOUkvQBRofMI5MJABnwE+A8XwDPD/Lfz/K58BPgN28QyI3hEDVkrKVZQvVwE+3j7FKt5k8CITcDKYBFeTKwIrVNShjH9Z+Pn6M5ABnwE+A3wG+AzwGeAz4LDPgOgd0T4i3orr0IJoLOtQ5ALOPLizszNMJpP2/4oP2CGD8m1zXa68x3wO+AzwGeAzwGfgnn4GRO+I7kEJ/ik2AVeCa+ClSIAESIAESKBUEeBkSeBuCVDA3S1B9icBEiABEiABEiCBEiZAAVfCwHk5ErAPApwFCZAACZBAaSZAAVea7x7nTgIkQAIkQAIkcE8S+D8AAAD//2aIxuMAAAAGSURBVAMAN68igq2+FQcAAAAASUVORK5CYII=" /></p>
<p>Which of the 22 products failed? Who the f— knows. Google isn’t saying.</p>
<p>What? Did you think that clicking on the “22 products” link would tell you something useful about the failure? Nope. It just lists all 22 products that were in the failed attempt. What about the “Learn more” link? It just takes you to the generic help for Takeout failures, which again boils down to “try again.”</p>
<p>If you want to figure out which products you can’t get your data from, you’ll have to do it the old fashioned way: Binary Search.</p>
<p>I know, I know. It’s absolutely, mind bogglingly absurd that you should have to waste days making repeated Takeout attempts to identify what products are failing you. All because Google’s leadership doesn’t prioritize Takeout—or users—enough to make sure that Takeout actually works reliably.</p>
<p>(Note that I am criticizing Google’s <em>leadership</em>, not the heroic folks within Google that do yeoman’s work on Takeout, despite the lack of prioritization.)</p>
<p>Fortunately, there is a trick to make the binary search slightly easier. If you click the red “Start new request” button on this particular error screen, the UI for starting a new request will be limited to just the products that you tried to include in the failed attempt. (As far as I can tell, this semi-helpful feature is completely undocumented.) That means you can run the binary search as follows:</p>
<ol type="1">
<li>When a Takeout request fails, go to <a href="https://takeout.google.com/manage">takeout.google.com/manage</a>, find the failed attempt, and click on it. You will see a screen like the one above.</li>
<li>Now, right click the “Start new request” button and select “Open Link in New Tab” in your web browser. In that new tab, configure a new Takeout request but, crucially, <em>uncheck all but the <strong>first</strong> half of the listed products</em>. Submit the request and close the tab.</li>
<li>That will take you back to the previous tab. Click the “Start new request” button again. This time, <em>uncheck all but the <strong>second</strong> half of the listed products</em>. Submit the request.</li>
<li>Now wait. Hours. Maybe days.</li>
<li>If all the Takeout requests succeed, great, you’re done.</li>
<li>Otherwise, for each failing attempt, go back to Step 1 and split that failed attempt into two half-sized attempts by repeating the procedure above.</li>
<li>Eventually, you will narrow the failures down to the individual products that you can’t get your data from. For these products, you can try changing the Takeout settings (if offered) or try to escalate to someone you know within Google who might help. If you’re famous, you can try the Twitter route.</li>
</ol>
<p>Good luck!</p>
</div>
]]></summary>
</entry>
<entry>
    <title>Sampling with SQL</title>
    <link href="http://blog.moertel.com/posts/2024-08-23-sampling-with-sql.html" />
    <id>http://blog.moertel.com/posts/2024-08-23-sampling-with-sql.html</id>
    <published>2024-08-23T00:00:00Z</published>
    <updated>2024-08-23T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2024-08-23">August 23, 2024</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;sampling&#39;." href="/tags/sampling.html" rel="tag">sampling</a>, <a title="All pages tagged &#39;sql&#39;." href="/tags/sql.html" rel="tag">sql</a>, <a title="All pages tagged &#39;probability&#39;." href="/tags/probability.html" rel="tag">probability</a>, <a title="All pages tagged &#39;poisson process&#39;." href="/tags/poisson%20process.html" rel="tag">poisson process</a>, <a title="All pages tagged &#39;exponential distribution&#39;." href="/tags/exponential%20distribution.html" rel="tag">exponential distribution</a>, <a title="All pages tagged &#39;statistics&#39;." href="/tags/statistics.html" rel="tag">statistics</a></span></div>

<div itemprop="articleBody">
<p>Sampling is one of the most powerful tools you can wield to extract meaning from large datasets.
It lets you reduce a massive pile of data into a small yet representative dataset that’s fast and easy to use.</p>
<p>If you know how to take samples using SQL, the ubiquitous query language, you’ll be able to take samples anywhere.
No dataset will be beyond your reach!</p>
<p>In this post, we’ll look at some clever algorithms for taking samples.
These algorithms are fast and easily translated into SQL.</p>
<p>First, however, I’ll note that many database systems have some built-in support for taking samples.
For example, some SQL dialects support a <code>TABLESAMPLE</code> clause.
If your system has built-in support—and it does what you need—using it will usually be your best option.</p>
<p>Often, though, the built-in support is limited to simple cases.
Let’s consider some realistic scenarios that are more challenging:</p>
<ul>
<li>We want to be able to take samples <em>with</em> and <em>without</em> replacement.</li>
<li>We want to take <em>weighted</em> samples in which each item in the input dataset is selected with probability in proportion to its corresponding weight.</li>
<li>We want to support the full range of weights we might expect to see in a FAANG-sized dataset, say between <span class="math inline">\(0\)</span> to <span class="math inline">\(10^{20}\)</span> for frequency distributions (e.g., clicks or impressions or RPC events) and between <span class="math inline">\(0\)</span> to <span class="math inline">\(1\)</span> with values as small as <span class="math inline">\(10^{-20}\)</span> for normalized probability distributions. In other words, weights are non-negative numbers, possibly very large or very small.</li>
<li>We want to take deterministic samples. This property lets us take repeatable samples and, in some cases, helps query planners produce faster queries.</li>
</ul>
<h2 id="sampling-without-replacement-the-a-es-algorithm-in-sql">Sampling without replacement: the A-ES algorithm in SQL</h2>
<p>In 2006, Pavlos S. Efraimidis and Paul G. Spirakis published a one-pass algorithm for drawing a weighted random sample, without replacement, from a population of weighted items.
It’s quite simple:</p>
<p>Given a population <span class="math inline">\(V\)</span> indexed by <span class="math inline">\(i = 1\ldots{}n\)</span> and having weights <span class="math inline">\(w_i\)</span>:</p>
<ol type="1">
<li>For each <span class="math inline">\(v_i\)</span> in <span class="math inline">\(V,\)</span> let <span class="math inline">\(u_i = \mathrm{random}(0, 1)\)</span> and <span class="math inline">\(k_i = u_i^{1/w_i}\)</span>.</li>
<li>Select the <span class="math inline">\(m\)</span> items with the largest keys <span class="math inline">\(k_i\)</span>.</li>
</ol>
<p>That algorithm has a straightforward implementation in SQL:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> Population</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> weight <span class="op">&gt;</span> <span class="dv">0</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="kw">ORDER</span> <span class="kw">BY</span> <span class="op">-</span><span class="fu">LN</span>(<span class="fl">1.0</span> <span class="op">-</span> <span class="kw">RANDOM</span>()) <span class="op">/</span> weight</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">LIMIT</span> <span class="dv">100</span>  <span class="co">-- Sample size.</span></span></code></pre></div>
<p>You’ll note that we changed the ordering logic a bit.
A straight translation would have been</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">ORDER</span> <span class="kw">BY</span> POW(<span class="kw">RANDOM</span>(), <span class="fl">1.0</span> <span class="op">/</span> weight) <span class="kw">DESC</span></span></code></pre></div>
<p>Our translation</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">ORDER</span> <span class="kw">BY</span> <span class="op">-</span><span class="fu">LN</span>(<span class="fl">1.0</span> <span class="op">-</span> <span class="kw">RANDOM</span>()) <span class="op">/</span> weight</span></code></pre></div>
<p>is more numerically stable and also helps to show the connection between the algorithm and the fascinating theory of Poisson processes.
This connection makes it easier to understand how the algorithm works.
More on that in a moment.</p>
<h2 id="numerical-stability-and-other-tweaks">Numerical stability and other tweaks</h2>
<p>First, the numerical stability claim.
Assume that our SQL system uses <a href="https://en.wikipedia.org/wiki/IEEE_754-1985#Double_precision">IEEE double-precision floating-point values</a> under the hood.
When the weights are large, say on the order of <span class="math inline">\(w_i = 10^{17}\)</span>, it doesn’t matter what the random value <span class="math inline">\(u_i\)</span> is.
The corresponding sort key <span class="math inline">\(k_i = u_i^{1/w_i}\)</span> will almost always be <span class="math inline">\(1.0\)</span>.
Consider the interval <span class="math inline">\(0.01 \le u_i \le 1\)</span>, representing 99% of the possible random values <span class="math inline">\(u_i\)</span>.
This entire interval gets mapped to <span class="math inline">\(1.0\)</span> when <span class="math inline">\(w_i = 10^{17}\)</span>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Python.</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> w_i <span class="op">=</span> <span class="fl">1e17</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> math.<span class="bu">pow</span>(<span class="fl">0.01</span>, <span class="fl">1.0</span><span class="op">/</span>w_i) <span class="op">==</span> math.<span class="bu">pow</span>(<span class="fl">1.0</span>, <span class="fl">1.0</span><span class="op">/</span>w_i) <span class="op">==</span> <span class="fl">1.0</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="va">True</span></span></code></pre></div>
<p>Likewise, when weights are small, say <span class="math inline">\(w_i = 10^{-17}\)</span>, the corresponding sort key will almost always be zero.
Consider the interval <span class="math inline">\(0 \le u_i \le 0.99\)</span>, representing 99% of the possible random values <span class="math inline">\(u_i\)</span>:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> w_i <span class="op">=</span> <span class="fl">1e-17</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> math.<span class="bu">pow</span>(<span class="fl">0.0</span>, <span class="fl">1.0</span><span class="op">/</span>w_i) <span class="op">==</span> math.<span class="bu">pow</span>(<span class="fl">0.99</span>, <span class="fl">1.0</span><span class="op">/</span>w_i) <span class="op">==</span> <span class="fl">0.0</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="va">True</span></span></code></pre></div>
<p>For very large (or small) weights, then, the straightforward implementation doesn’t work.
The wanted sort ordering is destroyed when very large (or small) powers cause what should be distinct sort keys to collapse into indistinguishable fixed points.</p>
<p>Fortunately, logarithms are <a href="https://en.wikipedia.org/wiki/Monotonic_function">order-preserving</a> transformations, so sorting by <span class="math inline">\(\ln(u_i^{1/w_i}) = \ln(u_i) / w_i\)</span> produces the same ordering as sorting by <span class="math inline">\(u_i^{1/w_i}\)</span> when we’re using mathematically pure real numbers.
But the log-transformed version is much more stable when using floating-point numbers.
Distinct random inputs <span class="math inline">\(u_i\)</span> now produce reliably distinct sort keys <span class="math inline">\(k_i\)</span>, even when the input weights <span class="math inline">\(w_i\)</span> are very large or very small:</p>
<pre class="python&gt;"><code>&gt;&gt;&gt; [math.log(u_i) / 1e17 for u_i in (0.01, 0.010001, 0.99, 0.990001)]
[-4.605170185988091e-17, -4.605070190987759e-17,
 -1.005033585350145e-19, -1.0049325753001471e-19]

&gt;&gt;&gt; [math.log(u_i) / 1e-17 for u_i in (0.01, 0.010001, 0.99, 0.990001)]
[-4.605170185988091e+17, -4.605070190987758e+17,
 -1005033585350145.0, -1004932575300147.1]</code></pre>
<!-- ![Graph showing that as the weights w_i reach 10 to the power of 14, a substantial share of the possible random numbers u_i get mapped by our sort-keying function to a single value.](../images/public_html/blog/pix-20240601/deadspace_plot.svg) -->
<p>As a final tweak, we negate the sort keys so that instead of sorting by <span class="math inline">\(u_i^{1/w_i}\)</span> <strong>descending</strong>, as in the original algorithm, we do an equivalent sort by <span class="math inline">\(-\ln(u_i) / w_i\)</span> <strong>ascending</strong>.
Note the leading minus sign.
The rationale for flipping the sign will become apparent when we discuss Poisson processes in the next section.</p>
<p>One last numerical subtlety.
Why do we generate random numbers with the expression <code>1.0 - RANDOM()</code> instead of just <code>RANDOM()</code>?
Since most implementations of <code>RANDOM()</code>, such as the <a href="https://www.pcg-random.org/using-pcg-c-basic.html#generating-doubles">PCG</a> implementation used by DuckDB, return a floating-point value in the semi-closed range <span class="math inline">\([0, 1)\)</span>, they can theoretically return zero.
And we don’t want to take the logarithm of zero.
So we instead use <code>1.0 - RANDOM()</code> to generate a random number in the semi-closed range <span class="math inline">\((0, 1]\)</span>, which excludes zero.</p>
<h2 id="does-this-algorithm-actually-work">Does this algorithm actually work?</h2>
<p>First, what do we mean by <em>work</em>?
In this case, we’ll say that we want the algorithm to produce samples that are equivalent to a succession of random draws, each draw removing an item from the population, and each draw fair with respect to the population that remains <em>at the time of the draw</em>.
Because the population grows slightly smaller with each draw, the draws in the sample are not <a href="https://en.wikipedia.org/wiki/Independent_and_identically_distributed_random_variables">independent and identically distributed</a> (iid).
In practice, however, when your samples are very small compared to your population of interest, and your weights are such that it’s unlikely that iid draws would draw the same item more than once, you can generally pretend that the draws are iid and get away with it.
(When you can’t get away with it, you can use a reweighting scheme to extract unbiased estimates anyway. This subject is worth its own post, so I won’t say more here.)</p>
<p>Anyway, it’s not obvious that assigning a random number <span class="math inline">\(u_i\)</span> to every row <span class="math inline">\(i\)</span>, then sorting rows on <span class="math inline">\(-\ln(u_i)/w_i\)</span>, and finally taking the top <span class="math inline">\(m\)</span> rows is a recipe that would result in a sample that has the wanted properties.
But it does.</p>
<p>The clearest way to understand what’s going on is to first take a detour through the fascinating theory of <a href="https://ocw.mit.edu/courses/6-262-discrete-stochastic-processes-spring-2011/3a19ce0e02d0008877351bfa24f3716a_MIT6_262S11_chap02.pdf">Poisson processes</a>.
In short, <strong>a Poisson process with rate <span class="math inline">\(\lambda\)</span> is a sequence of arrivals such that the times between successive arrivals are all independent, <a href="https://en.wikipedia.org/wiki/Exponential_distribution">exponentially distributed</a> random variables with rate <span class="math inline">\(\lambda\)</span>.</strong>
<!-- For example, say $T_1 < T_2 < T_3 < \cdots$ is a sequence of arrival times, and $X_i = T_{i} - T_{i-1}$ for $i > 1$. Then if all $X_i$ are i.i.d. exponentially distributed with rate $\lambda$, the sequence is a Poisson process with rate $\lambda$. --></p>
<p>Poisson processes have some important (and useful!) properties:</p>
<ol type="1">
<li><em>They are memoryless</em>. No matter what has previously happened, the time until the next arrival from a Poisson process with rate <span class="math inline">\(\lambda\)</span> is exponentially distributed with rate <span class="math inline">\(\lambda\)</span>.</li>
<li><em>They can be merged.</em> If you have two Poisson processes with rates <span class="math inline">\(\lambda_1\)</span> and <span class="math inline">\(\lambda_2\)</span>, the arrivals from both processes form a combined Poisson process with rate <span class="math inline">\(\lambda_1 + \lambda_2\)</span>. This holds for any number of processes.</li>
<li><em>They win races in proportion to their rates.</em> In a race between the very next arrival from a Poisson process with rate <span class="math inline">\(\lambda_1\)</span> and the very next arrival from a Poisson process with rate <span class="math inline">\(\lambda_2\)</span>, the probability that the first process will win the race is <span class="math inline">\(\lambda_1 / (\lambda_1 + \lambda_2)\)</span>.</li>
</ol>
<p>Now that we know the basics of Poisson processes, there’s just one more tidbit we need:</p>
<ul>
<li><em>The uniform–exponential bridge.</em> If <span class="math inline">\(X\)</span> is a random variable having a uniform distribution between zero and one, then <span class="math inline">\(-\ln(X)/\lambda\)</span> has an exponential distribution with rate <span class="math inline">\(\lambda\)</span>.</li>
</ul>
<p>With the uniform–exponential bridge in mind, we can begin to see what the algorithm is doing when it assigns every row a key <span class="math inline">\(k_i = -\ln(u_i)/w_i\)</span> and sorts the population by that key.
It’s running a race over all the rows in the population!
In this race, each row arrives at the finish line at a time that’s an exponentially distributed random variable with a rate corresponding to the row’s weight <span class="math inline">\(w_i\)</span>.
The first <span class="math inline">\(m\)</span> arrivals form the sample.</p>
<p>To prove that this race does the sampling that we want, we will show that it is equivalent to a succession of one-row draws, each draw being fair with respect to the population that remains at the time of the draw.
Let the population’s total weight be <span class="math inline">\(w\)</span>, and consider an arbitrary row <span class="math inline">\(i\)</span> with weight <span class="math inline">\(w_i\)</span>.
The algorithm will assign it an exponentially distributed random variable with rate <span class="math inline">\(w_i\)</span>, which corresponds to the very next arrival from a Poisson process with the same rate.</p>
<p>Now consider all rows except <span class="math inline">\(i\)</span>.
They too correspond to Poisson processes with rates equal to their weights.
And we can merge them into a combined process with rate <span class="math inline">\(\sum_{j \ne i} w_j = w - w_i\)</span>.</p>
<p>Now, using the rule about Poisson races, we know that row <span class="math inline">\(i\)</span>, represented by a process with rate <span class="math inline">\(\lambda_1 = w_i\)</span>, will win the race against those other rows, represented by a combined process with rate <span class="math inline">\(\lambda_2 = w - w_i\)</span>, with probability</p>
<p><span class="math display">\[\frac{\lambda_1}{\lambda_1 + \lambda_2} = \frac{w_i}{w_i + (w - w_i)} = \frac{w_i}{w}.\]</span></p>
<p>And since we chose row <span class="math inline">\(i\)</span> arbitrarily, the same argument applies to all rows.
Thus every row’s probability of being drawn is equal to its weight in proportion to the population’s total weight.
This proves that running a “race of exponentials” lets us perform one fair draw from a population.</p>
<p>But, after we’ve drawn one row, what’s left but a new, slightly smaller population?
And can’t we run a new race on this slightly smaller population to correctly draw another row?</p>
<p>We can.
And, since Poisson processes are memoryless, we do not have to generate new arrival times to run this new race.
We can reuse the existing arrival times because the arrivals that have already happened have no effect on later arrivals.
Thus the next row we draw using the leftover arrival times will be another fair draw.</p>
<p>We can repeat this argument to show that successive rows are chosen fairly in relation to the population that remains at the time of each draw.
Thus algorithm A-ES selects a sample of size <span class="math inline">\(m\)</span> by making <span class="math inline">\(m\)</span> successive draws, each fair with respect to its remaining population.
And that’s the proof.</p>
<h2 id="tricks-for-faster-samples">Tricks for faster samples</h2>
<p>Most large analytical datasets will be stored in a column-oriented storage format, such as Parquet.
When reading from such datasets, you typically only have to pay for the columns you read.
(By “pay”, I mean wait for the query engine to do its work, but if you’re running your query on some tech company’s cloud, you may actually pay in currency too.)</p>
<p>For example, if your dataset contains a table having 100 columns but you need only four of them, the query engine will usually only read those four columns.
In row-oriented data stores, by contrast, you’ll generally have to decode entire rows, even if you only want four out of the 100 values in each row.
Additionally, most column-oriented stores support some kind of filter pushdown, allowing the storage engine to skip rows when a filtering expression evaluates to false.
These two properties—pay for what you read and filter pushdown—are ones we can exploit when taking samples.</p>
<p>Say we have a Population table with billions of rows and around 100 columns.
How can we efficiently take a weighted sample of 1000 rows?</p>
<p>We could use the basic sampling formulation, as discussed earlier:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> Population</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> weight <span class="op">&gt;</span> <span class="dv">0</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">ORDER</span> <span class="kw">BY</span> <span class="op">-</span><span class="fu">LN</span>(<span class="fl">1.0</span> <span class="op">-</span> <span class="kw">RANDOM</span>()) <span class="op">/</span> weight</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a><span class="kw">LIMIT</span> <span class="dv">1000</span>  <span class="co">-- Sample size.</span></span></code></pre></div>
<p>But think about what the query engine must do to execute this query.
It must read and decode all 100 columns for all of those billions of rows so that it may pass those rows into the sort/limit logic (typically implemented as a <code>TOP_N</code> operation) to determine which rows to keep for the sample.
Even though the sample will keep only 0.00001% of those rows, you’ll have to pay to read the entire Population table!</p>
<p>A much faster approach is to only read the columns we need to determine <em>which</em> rows are in the sample.
Say our table has a primary key <code>pk</code> that uniquely identifies each row.
The following variant on our sampling formulation returns only the primary keys needed to identify the rows in the sample:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> pk</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> Population</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="kw">WHERE</span> weight <span class="op">&gt;</span> <span class="dv">0</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">ORDER</span> <span class="kw">BY</span> <span class="op">-</span><span class="fu">LN</span>(<span class="fl">1.0</span> <span class="op">-</span> <span class="kw">RANDOM</span>()) <span class="op">/</span> weight</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a><span class="kw">LIMIT</span> <span class="dv">1000</span>  <span class="co">-- Sample size.</span></span></code></pre></div>
<p>This variant only forces the query engine to read two columns: <code>pk</code> and <code>weight</code>:
Yes, it still must read those two columns for the billions of rows in the table, but those columns contain small values and can be scanned quickly.
After all, that’s what column-oriented stores are designed to do well.
The point is that we’re not paying to read about 100 additional columns whose values we’re just going to throw away 99.99999% of the time.</p>
<p>One we have identified the rows in our sample, we can run a second query to pull in the full set of wanted columns for just those rows.</p>
<h2 id="adding-determinism">Adding determinism</h2>
<p>Our sampling algorithm depends on randomization.
If we run our algorithm twice with the same inputs, we’ll get different results each time.
Often, that nondeterminism is exactly what we want.</p>
<p>But sometimes it isn’t.
Sometimes, it’s useful to be able to <em>control</em> the dice rolls that the algorithm depends on.
For example, sometimes it’s useful to be able to repeat a sample.
Or <em>almost</em> repeat a sample.</p>
<p>To allow us to control the nature of the randomization used when we take samples, we must replace calls to <code>RANDOM</code> with a deterministic pseudorandom function.
One common approach is to hash a primary key and then map the hashed value to a number in the range <span class="math inline">\([0, 1)\)</span>.
The following DuckDB macro <code>pseudorandom_uniform</code> will do exactly that:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Returns a pseudorandom fp64 number in the range [0, 1). The number</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- is determined by the given `key`, `seed` string, and integer `index`.</span></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> MACRO pseudorandom_uniform(<span class="kw">key</span>, seed, <span class="kw">index</span>)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="kw">AS</span> (</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>  (<span class="kw">HASH</span>(<span class="kw">key</span> <span class="op">||</span> seed <span class="op">||</span> <span class="kw">index</span>) <span class="op">&gt;&gt;</span> <span class="dv">11</span>) <span class="op">*</span> POW(<span class="fl">2.0</span>, <span class="op">-</span><span class="dv">53</span>)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<p>We can vary the <code>seed</code> and <code>index</code> parameters to generate independent random values for the same <code>key</code>.
For example, if I fix the <code>seed</code> to “demo-seed-20240601” and generate random numbers for the <code>key</code> “key123” over the <code>index</code> values <span class="math inline">\(1, 2, \ldots, 10\)</span>, I get 10 fresh random numbers:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>  pseudorandom_uniform(<span class="st">&#39;key123&#39;</span>, <span class="st">&#39;demo-seed-20240601&#39;</span>, i) <span class="kw">AS</span> u_key123</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> <span class="kw">RANGE</span>(<span class="dv">1</span>, <span class="dv">11</span>) <span class="kw">AS</span> t(i);</span></code></pre></div>
<table>
<caption>Ten random numbers for the key “key123” and seed “demo-seed-20240601”.</caption>
<thead>
<tr class="header">
<th style="text-align: right;"><em>i</em></th>
<th style="text-align: left;"><em>u_key123</em></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;">1</td>
<td style="text-align: left;">0.9592606495318252</td>
</tr>
<tr class="even">
<td style="text-align: right;">2</td>
<td style="text-align: left;">0.6309411348395693</td>
</tr>
<tr class="odd">
<td style="text-align: right;">3</td>
<td style="text-align: left;">0.5673207749533353</td>
</tr>
<tr class="even">
<td style="text-align: right;">4</td>
<td style="text-align: left;">0.11182926321927167</td>
</tr>
<tr class="odd">
<td style="text-align: right;">5</td>
<td style="text-align: left;">0.3375806483238627</td>
</tr>
<tr class="even">
<td style="text-align: right;">6</td>
<td style="text-align: left;">0.12881607107157678</td>
</tr>
<tr class="odd">
<td style="text-align: right;">7</td>
<td style="text-align: left;">0.6993372364353198</td>
</tr>
<tr class="even">
<td style="text-align: right;">8</td>
<td style="text-align: left;">0.94031652266991</td>
</tr>
<tr class="odd">
<td style="text-align: right;">9</td>
<td style="text-align: left;">0.17893798791559323</td>
</tr>
<tr class="even">
<td style="text-align: right;">10</td>
<td style="text-align: left;">0.6903126337753016</td>
</tr>
</tbody>
</table>
<p>To take deterministic samples, we just replace calls to <code>RANDOM()</code> with calls to our function <code>pseudorandom_uniform()</code>.</p>
<p>Now that we can take deterministic samples, we can do even more useful things!
For example, we can take samples <em>with</em> replacement.</p>
<h2 id="sampling-with-replacement">Sampling with replacement</h2>
<p>Earlier, we proved that the A-ES algorithm allows us to take a sample without replacement as a series of successive draws, each draw removing an item from the population, and each draw fair with respect to the population that remains at the time of the draw.
But what if we wanted to take a sample <em>with replacement</em>?
A sample with replacement requires us to return each item to the population as it is selected so that every selection is fair with respect to the <em>original</em> population, and individual items may be selected more than once.</p>
<p>Can we efficiently implement sampling with replacement in SQL?
Yes!
But it’s a little trickier.
(I haven’t found this algorithm published anywhere; please let me know if you have.
It took me some effort to create, but I wouldn’t be surprised if it’s already known.)</p>
<p>Think back to our correctness proof for the A-ES algorithm.
For each row <span class="math inline">\(i\)</span> having a weight <span class="math inline">\(w_i\)</span>, the algorithm imagined a corresponding Poisson process with rate <span class="math inline">\(\lambda_i = w_i\)</span> and represented the row by the very next arrival from that process.
That arrival would occur at time <span class="math inline">\(k_i = -\ln(u_i) / w_i\)</span>, where <span class="math inline">\(u_i\)</span> is a uniformly distributed random number in the range <span class="math inline">\((0, 1]\)</span>.
Then the algorithm sorted all rows by their <span class="math inline">\(k_i\)</span> values and took the first <span class="math inline">\(m\)</span> arrivals as the sample.</p>
<p>With one minor tweak to this algorithm, we can take a sample with replacement.
That tweak is to consider not just the <em>very next</em> arrival from each row’s Poisson process but <em>all</em> arrivals.
Let <span class="math inline">\(k_{i,j}\)</span> denote the <span class="math inline">\(j\)</span>th arrival from row <span class="math inline">\(i\)</span>’s process.
Since we know that in a Poisson process the times between successive arrivals are exponentially distributed random variables, we can take the running sum over interarrival times to give us the needed arrival times.
That is, <span class="math inline">\(k_{i,j} = \sum_{r=1}^{j} -\ln(u_{i,r}) / w_i\)</span>, where <span class="math inline">\(u_{i,r}\)</span> represents the <span class="math inline">\(r\)</span>th uniformly distributed random variable for row <span class="math inline">\(i\)</span>.</p>
<p>One minor problem with this tweaked algorithm is that a Poisson process generates a theoretically infinite series of arrivals.
Creating an infinite series for each row and then sorting the arrivals from all of these series is intractable.</p>
<p>Fortunately, we can avoid this problem!
Think about how the A-ES algorithm for taking a sample <em>without</em> replacement relates to our proposed intractable algorithm for taking a sample <em>with</em> replacement.
We could describe the <em>without</em> algorithm in terms of the <em>with</em> algorithm like so:
Prepare to take a sample <em>with</em> replacement, but then ignore all arrivals <span class="math inline">\(k_{i,j}\)</span> for <span class="math inline">\(j &gt; 1\)</span>; the remaining arrivals must be of the form <span class="math inline">\(k_{i,1}\)</span>, where <span class="math inline">\(i\)</span> indicates the corresponding row.
Then take the first <span class="math inline">\(m\)</span> of these remaining arrivals as your sample, as before.</p>
<p>Now think about going the other way, from having a <em>without</em>-replacement sample and needing to construct a corresponding <em>with</em>-replacement sample.
Let <span class="math inline">\(S\)</span> be the set of rows sampled <em>without</em> replacement.
We know these rows were represented by a corresponding set of arrival times <span class="math inline">\(k_{i,1}\)</span> for <span class="math inline">\(i\)</span> in <span class="math inline">\(S\)</span>.
We also know that, had the sample been taken <em>with</em> replacement, the race would have included some additional arrival times <span class="math inline">\(k_{i,j}\)</span> for <span class="math inline">\(j &gt; 1\)</span> that could have displaced some of the winning rows in <span class="math inline">\(S\)</span>.
But, crucially, we also know that if <span class="math inline">\(S_{*}\)</span> represents the set of rows in the corresponding sample <em>with</em> replacement, then <span class="math inline">\(S_{*}\)</span> must be contained within <span class="math inline">\(S\)</span>.
This claim follows from the fact that if any arrival <span class="math inline">\(k_{i,j}\)</span> for <span class="math inline">\(j &gt; 1\)</span> does displace a row among the first <span class="math inline">\(m\)</span> arrivals, the <span class="math inline">\(j&gt;1\)</span> requirement implies that the displacing row is a duplicate of some row <span class="math inline">\(i\)</span> that arrived earlier in the sample at time <span class="math inline">\(k_{i,1}\)</span>; thus, displacement cannot introduce a new row from outside of <span class="math inline">\(S\)</span>.</p>
<p>Therefore, if we have a sample <em>without</em> replacement, we can construct a sample <em>with</em> replacement from its rows.
<em>We can ignore all other rows in the population.</em>
This makes the problem much more approachable.</p>
<p>So now we can see an algorithm taking shape for taking a sample <em>with</em> replacement of size <span class="math inline">\(m\)</span>:</p>
<ol type="1">
<li>First, take an <span class="math inline">\(m\)</span>-sized sample <span class="math inline">\(S\)</span> <em>without</em> replacement using the efficient A-ES algorithm.</li>
<li>For each sampled row <span class="math inline">\(i\)</span> in <span class="math inline">\(S\)</span>, generate <span class="math inline">\(m\)</span> arrivals <span class="math inline">\(k_{i,j}\)</span> for <span class="math inline">\(j = 1, 2, \ldots, m\)</span> using the same pseudorandom universe that was used to generate <span class="math inline">\(S\)</span>.</li>
<li>Take the first <span class="math inline">\(m\)</span> arrivals as the sample.</li>
</ol>
<p>You may have noticed that step 2 of this algorithm requires us to create <span class="math inline">\(m\)</span> arrivals for each of the <span class="math inline">\(m\)</span> rows in <span class="math inline">\(S\)</span>.
This step thus requires <span class="math inline">\(O(m^2)\)</span> time.
When <span class="math inline">\(m\)</span> is large, this time can be prohibitive.</p>
<p>Fortunately, we can use probability theory to reduce this cost to <span class="math inline">\(O(m)\)</span>.
The idea is that if row <span class="math inline">\(i\)</span> is expected to occur in the sample <span class="math inline">\(n_i\)</span> times, it is very unlikely to occur more than <span class="math inline">\(c \cdot n_i\)</span> times when <span class="math inline">\(c \ge 2\)</span>.
So we don’t need to generate a full <span class="math inline">\(m\)</span> arrivals for each row <span class="math inline">\(i\)</span> in <span class="math inline">\(S\)</span>; we can get away with generating <span class="math inline">\(m_i = \lceil{c \cdot n_i}\rceil\)</span> arrivals instead, for a suitably large <span class="math inline">\(c\)</span> to assuage our personal level of paranoia.</p>
<p>Here’s a sample implementation as a DuckDB macro:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Takes a weighted sample with replacement from a table.</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Args:</span></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="co">--  population_table: The table to sample from. It must have a `pk` column</span></span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a><span class="co">--    of unique primary keys and a `weight` column of non-negative weights.</span></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a><span class="co">--  seed: A string that determines the pseudorandom universe in which the</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a><span class="co">--    sample is taken. Samples taken with distinct seeds are independent.</span></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a><span class="co">--    If you wish to repeat a sample, reuse the sample&#39;s seed.</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="co">--  sample_size: The number of rows to include in the sample. This value</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a><span class="co">--    may be larger than the number of rows in the `population_table`.</span></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- Returns a sample of rows from the `population_table`.</span></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a><span class="kw">CREATE</span> MACRO sample_with_replacement(population_table, seed, sample_size)</span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a><span class="kw">AS</span> <span class="kw">TABLE</span> (</span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a>  <span class="kw">WITH</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- First, take a sample *without* replacement of the wanted size.</span></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>    SampleWithoutReplacement <span class="kw">AS</span> (</span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="op">*</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span> query_table(population_table:<span class="ch">:varchar</span>)</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>      <span class="kw">WHERE</span> weight <span class="op">&gt;</span> <span class="dv">0</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>      <span class="kw">ORDER</span> <span class="kw">BY</span> <span class="op">-</span><span class="fu">LN</span>(pseudorandom_uniform(pk, seed, <span class="dv">1</span>)) <span class="op">/</span> weight</span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a>      <span class="kw">LIMIT</span> sample_size</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a>    ),</span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- Compute the total weight over the sample.</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true" tabindex="-1"></a>    SampleWithoutReplacementTotals <span class="kw">AS</span> (</span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span> <span class="fu">SUM</span>(weight) <span class="kw">AS</span> weight</span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span> SampleWithoutReplacement</span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true" tabindex="-1"></a>    ),</span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true" tabindex="-1"></a>    <span class="co">-- Generate a series of arrivals for each row in the sample.</span></span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true" tabindex="-1"></a>    SampleWithReplacementArrivals <span class="kw">AS</span> (</span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true" tabindex="-1"></a>      <span class="kw">SELECT</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true" tabindex="-1"></a>        S.<span class="op">*</span>,</span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true" tabindex="-1"></a>        <span class="fu">SUM</span>(<span class="op">-</span><span class="fu">LN</span>(pseudorandom_uniform(pk, seed, trial_index)) <span class="op">/</span> S.weight)</span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true" tabindex="-1"></a>          <span class="kw">OVER</span> (<span class="kw">PARTITION</span> <span class="kw">BY</span> pk <span class="kw">ORDER</span> <span class="kw">BY</span> trial_index)</span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true" tabindex="-1"></a>          <span class="kw">AS</span> rws_sort_key</span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true" tabindex="-1"></a>      <span class="kw">FROM</span> SampleWithoutReplacement <span class="kw">AS</span> S</span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true" tabindex="-1"></a>      <span class="kw">CROSS</span> <span class="kw">JOIN</span> SampleWithoutReplacementTotals <span class="kw">AS</span> T</span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true" tabindex="-1"></a>      <span class="kw">CROSS</span> <span class="kw">JOIN</span></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true" tabindex="-1"></a>        UNNEST(</span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true" tabindex="-1"></a>          <span class="kw">RANGE</span>(<span class="dv">1</span>, <span class="fu">CAST</span>(<span class="fl">2.0</span> <span class="op">*</span> sample_size <span class="op">*</span> S.weight <span class="op">/</span> T.weight <span class="op">+</span> <span class="dv">2</span> <span class="kw">AS</span> <span class="dt">INT</span>)))</span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true" tabindex="-1"></a>        <span class="kw">AS</span> I(trial_index)</span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true" tabindex="-1"></a>    )</span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true" tabindex="-1"></a>  <span class="co">-- Form the sample *with* replacement from the first `sample_size` arrivals.</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true" tabindex="-1"></a>  <span class="kw">SELECT</span> <span class="op">*</span> EXCLUDE (rws_sort_key)</span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true" tabindex="-1"></a>  <span class="kw">FROM</span> SampleWithReplacementArrivals</span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true" tabindex="-1"></a>  <span class="kw">ORDER</span> <span class="kw">BY</span> rws_sort_key</span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true" tabindex="-1"></a>  <span class="kw">LIMIT</span> sample_size</span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true" tabindex="-1"></a>);</span></code></pre></div>
<h3 id="example-of-sampling-with-replacement">Example of sampling with replacement</h3>
<p>As an example of when we might want to sample with replacement instead of without, consider the following population table <code>ThreeToOne</code> that represents the possible outcomes of tossing a biased coin:</p>
<table>
<caption><code>ThreeToOne</code> population table.</caption>
<thead>
<tr class="header">
<th style="text-align: left;"><em>pk</em></th>
<th style="text-align: right;"><em>weight</em></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">heads</td>
<td style="text-align: right;">3</td>
</tr>
<tr class="even">
<td style="text-align: left;">tails</td>
<td style="text-align: right;">1</td>
</tr>
</tbody>
</table>
<p>For this biased coin, “heads” is 3 times as likely as “tails.”
We can simulate flipping this coin 10 times by sampling 10 rows from the <code>ThreeToOne</code> population table with replacement:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">SELECT</span> pk</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">FROM</span> sample_with_replacement(ThreeToOne, <span class="st">&#39;test-seed-20240601&#39;</span>, <span class="dv">10</span>);</span></code></pre></div>
<table>
<caption>Results of drawing a 10-row sample with replacement from <code>ThreeToOne</code>.</caption>
<thead>
<tr class="header">
<th style="text-align: left;"><em>pk</em></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">heads</td>
</tr>
<tr class="even">
<td style="text-align: left;">heads</td>
</tr>
<tr class="odd">
<td style="text-align: left;">heads</td>
</tr>
<tr class="even">
<td style="text-align: left;">tails</td>
</tr>
<tr class="odd">
<td style="text-align: left;">tails</td>
</tr>
<tr class="even">
<td style="text-align: left;">heads</td>
</tr>
<tr class="odd">
<td style="text-align: left;">heads</td>
</tr>
<tr class="even">
<td style="text-align: left;">heads</td>
</tr>
<tr class="odd">
<td style="text-align: left;">tails</td>
</tr>
<tr class="even">
<td style="text-align: left;">heads</td>
</tr>
</tbody>
</table>
<p>In this sample, we got 7 heads and 3 tails.
On average, we would expect about 7.5 heads in each sample of size 10, so our observed sample is close to our expectations.</p>
<p>But maybe we just got lucky.
As a stronger test of our SQL sampling logic, let’s take 10,000 samples of size 40 and look at the count of heads across all of the samples.
We would expect this count to have a Binomial(<em>size</em> = 40, <em>p</em> = 3/4) distribution.
To compare our observed results to the expected distribution, I’ll compute the empirical distribution of the results and plot that over the expected distribution.
As you can see in the figure below, the observed distribution closely matches the expected distribution.</p>
<figure>
<img src="../images/public_html/blog/pix-20240601/observed_samples_vs_expected_three_to_one.svg" alt="When we take 10,000 independent samples of size n = 40 from a 3:1 biased-coin distribution, we find that the count of “heads” over the samples agrees with the expected Binomial(size = 40, p = 3/4) distribution." />
<figcaption aria-hidden="true">When we take 10,000 independent samples of size <span class="math inline">\(n = 40\)</span> from a 3:1 biased-coin distribution, we find that the count of “heads” over the samples agrees with the expected Binomial(<em>size</em> = 40, <em>p</em> = 3/4) distribution.</figcaption>
</figure>
<h2 id="conclusion">Conclusion</h2>
<p>Sampling is a powerful tool.
And with the SQL logic we’ve just discussed, you can take fast, easy samples from virtually any dataset, no matter how large.
And you can take those samples with or without replacement.</p>
<p>What makes it all work is a clever connection to the theory of Poisson processes.
Those processes are memoryless and mergeable, and their arrivals win races in proportion to their rates.
These properties are exactly what we need to run races that let us take samples.</p>
<p>Beyond what we’ve discussed in this article, there are further ways we can exploit these properties.
For example, as a performance optimization, we can predict the arrival time <span class="math inline">\(t\)</span> of the final row in a sample.
Then we can augment our SQL sampling logic with a pushdown filter that eliminates population rows with arrival times greater than <span class="math inline">\(c \cdot t\)</span> for some constant <span class="math inline">\(c\)</span>.
This filtering happens before <code>ORDER/LIMIT</code> processing and can greatly speed queries by eliminating more than 99.99% of rows early on, before they are even fully read on systems that support “late materialization.”</p>
<p>But this article is already too long, so I’ll stop here for now.</p>
<h2 id="references">References</h2>
<p>Pavlos S. Efraimidis and Paul G. Spirakis. Weighted random sampling with a reservoir. <em>Information Processing Letters</em>, 97(5):181–185, 2006.</p>
</div>
]]></summary>
</entry>
<entry>
    <title>Dice Race (part 1)</title>
    <link href="http://blog.moertel.com/posts/2023-06-24-dice-race-1.html" />
    <id>http://blog.moertel.com/posts/2023-06-24-dice-race-1.html</id>
    <published>2023-06-24T00:00:00Z</published>
    <updated>2023-06-24T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2023-06-24">June 24, 2023</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;interview-problems&#39;." href="/tags/interview-problems.html" rel="tag">interview-problems</a>, <a title="All pages tagged &#39;probability&#39;." href="/tags/probability.html" rel="tag">probability</a>, <a title="All pages tagged &#39;dice-race&#39;." href="/tags/dice-race.html" rel="tag">dice-race</a></span></div>

<div itemprop="articleBody">
<p>In a dice race of degree <span class="math inline">\(m\)</span> and length <span class="math inline">\(n\)</span>, each player chooses a sequence of <span class="math inline">\(m\)</span> die rolls.
Then we roll a die <span class="math inline">\(n\)</span> times to generate the race sequence.
The player whose sequence occurs first in the race sequence wins.
If no player’s sequence occurs in the race sequence, the race is a tie.
(If we want to guarantee a winner, we can always set <span class="math inline">\(n = \infty\)</span>.)</p>
<p>For example, say you and I run a race of degree <span class="math inline">\(m=2\)</span> and length <span class="math inline">\(n=20\)</span>.
I might choose 55 as my sequence.
You might choose 23.
Then we roll a die <span class="math inline">\(n=20\)</span> times to generate the race sequence:</p>
<p>6 1 6 6 1 <strong>5 5</strong> 3 1 4 5 <strong>2 3</strong> 3 2 2 6 4 3 4</p>
<p>In this race, I would win since 55 occurred before 23 in the race sequence.</p>
<p>Now consider the following questions:</p>
<ol type="1">
<li>Given a choice between 55 and 23, which should you choose? Why?</li>
<li>What is the expected number of die rolls before 55 occurs? What about for 23?</li>
<li>Write code to run a dice race, given degree <span class="math inline">\(m\)</span>, length <span class="math inline">\(n\)</span>, and the players’ chosen sequences.</li>
<li>Use the code to simulate many races between 55 and 23.</li>
<li>How do the results compare with your answer to question 2?</li>
</ol>
<p>I’ll answer the first two questions in this post and save the rest for a later post.</p>
<p>(Now would be a good time to pause and try to answer the questions yourself.)</p>
<h2 id="question-1-given-a-choice-between-55-and-23-which-should-you-choose-why">Question 1: Given a choice between 55 and 23, which should you choose? Why?</h2>
<p>In the example above, 55 won the race.
Is it the better choice, in general? To answer the question, let’s think about the task of matching the sequence 55 in a series of die rolls.
This task can be modeled as a finite automaton:</p>
<!--

// Graphviz source:
// Automaton to recognize the sequence 55 in a series of die rolls.

digraph G {

  node [fontname="Lato, sans-serif", fillcolor=lightgrey, style=filled]
  edge [fontname="Lato, sans-serif"]

  rankdir=LR

  Start [style=invis]
  S0 [shape=circle]
  S1 [shape=circle]
  S2 [shape=doublecircle]

  Start -> S0

  S0 -> S0 [label = "1 | 2 | 3 | 4 | 6"]
  S0 -> S1 [label = "5"];

  S1 -> S0 [label = "1 | 2 | 3 | 4 | 6"]
  S1 -> S2 [label = "5"]

}

-->
<!-- Generated by graphviz version 2.40.1 (20161225.0304) -->
<svg width="392pt" height="91pt" viewBox="0.00 0.00 392.14 90.80" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 86.8019)">
<title>
Finite automaton for recognizing the sequence 55 in a series of die rolls
</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-86.8019 388.1414,-86.8019 388.1414,4 -4,4"/>
<!-- Start -->
<!-- S0 -->
<g id="node2" class="node">
<title>
S0
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="116.7806" cy="-26.7686" rx="21.4691" ry="21.4691"/>
<text text-anchor="middle" x="116.7806" y="-22.5686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S0</text>
</g>
<!-- Start&#45;&gt;S0 -->
<g id="edge1" class="edge">
<title>
Start-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M58.8995,-26.7686C67.4301,-26.7686 76.7633,-26.7686 85.3965,-26.7686"/>
<polygon fill="#000000" stroke="#000000" points="85.4789,-30.2687 95.4789,-26.7686 85.4788,-23.2687 85.4789,-30.2687"/>
</g>
<!-- S0&#45;&gt;S0 -->
<g id="edge2" class="edge">
<title>
S0-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M109.8661,-46.9549C108.9093,-57.0221 111.2142,-66.0019 116.7806,-66.0019 120.3466,-66.0019 122.574,-62.3166 123.4629,-57.021"/>
<polygon fill="#000000" stroke="#000000" points="126.9634,-57.033 123.6951,-46.9549 119.9653,-56.8715 126.9634,-57.033"/>
<text text-anchor="middle" x="116.7806" y="-70.2019" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">1 | 2 | 3 | 4 | 6</text>
</g>
<!-- S1 -->
<g id="node3" class="node">
<title>
S1
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="269.4415" cy="-26.7686" rx="21.4691" ry="21.4691"/>
<text text-anchor="middle" x="269.4415" y="-22.5686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S1</text>
</g>
<!-- S0&#45;&gt;S1 -->
<g id="edge3" class="edge">
<title>
S0-&gt;S1
</title>
<path fill="none" stroke="#000000" d="M138.3294,-26.7686C164.2422,-26.7686 207.958,-26.7686 237.7253,-26.7686"/>
<polygon fill="#000000" stroke="#000000" points="238.0024,-30.2687 248.0023,-26.7686 238.0023,-23.2687 238.0024,-30.2687"/>
<text text-anchor="middle" x="193.111" y="-30.9686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">5</text>
</g>
<!-- S1&#45;&gt;S0 -->
<g id="edge4" class="edge">
<title>
S1-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M251.4333,-14.8629C245.008,-11.2674 237.5401,-7.7919 230.2082,-5.9686 198.2077,1.9895 188.0144,1.9895 156.0138,-5.9686 151.8897,-6.9942 147.7225,-8.5426 143.722,-10.3411"/>
<polygon fill="#000000" stroke="#000000" points="142.1302,-7.2239 134.7888,-14.8629 145.2916,-13.4693 142.1302,-7.2239"/>
<text text-anchor="middle" x="193.111" y="-9.9686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">1 | 2 | 3 | 4 | 6</text>
</g>
<!-- S2 -->
<g id="node4" class="node">
<title>
S2
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="358.9081" cy="-26.7686" rx="21.4314" ry="21.4314"/>
<ellipse fill="none" stroke="#000000" cx="358.9081" cy="-26.7686" rx="25.4687" ry="25.4687"/>
<text text-anchor="middle" x="358.9081" y="-22.5686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S2</text>
</g>
<!-- S1&#45;&gt;S2 -->
<g id="edge5" class="edge">
<title>
S1-&gt;S2
</title>
<path fill="none" stroke="#000000" d="M291.0989,-26.7686C300.818,-26.7686 312.5384,-26.7686 323.4814,-26.7686"/>
<polygon fill="#000000" stroke="#000000" points="323.6442,-30.2687 333.6442,-26.7686 323.6442,-23.2687 323.6442,-30.2687"/>
<text text-anchor="middle" x="312.1748" y="-30.9686" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">5</text>
</g>
</g>
</svg>
<p>We start in the initial state S0.
If the next die roll is a 5, we advance to state S1; otherwise, we remain at S0.
If we’re at S1 and the next roll is another 5, we advance to S2 and have successfully matched the sequence 55; otherwise, we go all the way back to S0 and start over from the beginning.</p>
<p>Now let’s consider the automaton for the sequence 23:</p>
<!--

// Graphviz source:
// Automaton to recognize the sequence 23 in a series of die rolls.

digraph G {

  node [fontname="Lato, sans-serif", fillcolor=lightgrey, style=filled]
  edge [fontname="Lato, sans-serif"]

  rankdir=LR

  Start [style=invis]
  S0 [shape=circle]
  S1 [shape=circle]
  S2 [shape=doublecircle]

  Start -> S0

  S0 -> S0 [label = "1  | 3 | 4 | 5 | 6"]
  S0 -> S1 [label = "2"];

  S1 -> S0 [label = "1 | 4 | 5 | 6"]
  S1 -> S1 [label = "2"]
  S1 -> S2 [label = "3"]

}

-->
<!-- Generated by graphviz version 2.40.1 (20161225.0304) -->
<svg width="375pt" height="89pt" viewBox="0.00 0.00 375.34 89.45" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 85.4505)">
<title>
Finite automaton to recognize the sequence 23 in a series of die rolls.
</title>
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-85.4505 371.3428,-85.4505 371.3428,4 -4,4"/>
<!-- Start -->
<!-- S0 -->
<g id="node2" class="node">
<title>
S0
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="116.7806" cy="-25.4172" rx="21.4691" ry="21.4691"/>
<text text-anchor="middle" x="116.7806" y="-21.2172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S0</text>
</g>
<!-- Start&#45;&gt;S0 -->
<g id="edge1" class="edge">
<title>
Start-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M58.8995,-25.4172C67.4301,-25.4172 76.7633,-25.4172 85.3965,-25.4172"/>
<polygon fill="#000000" stroke="#000000" points="85.4789,-28.9173 95.4789,-25.4172 85.4788,-21.9173 85.4789,-28.9173"/>
</g>
<!-- S0&#45;&gt;S0 -->
<g id="edge2" class="edge">
<title>
S0-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M109.8661,-45.6035C108.9093,-55.6707 111.2142,-64.6505 116.7806,-64.6505 120.3466,-64.6505 122.574,-60.9652 123.4629,-55.6696"/>
<polygon fill="#000000" stroke="#000000" points="126.9634,-55.6816 123.6951,-45.6035 119.9653,-55.5201 126.9634,-55.6816"/>
<text text-anchor="middle" x="116.7806" y="-68.8505" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">1  | 3 | 4 | 5 | 6</text>
</g>
<!-- S1 -->
<g id="node3" class="node">
<title>
S1
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="252.6429" cy="-25.4172" rx="21.4691" ry="21.4691"/>
<text text-anchor="middle" x="252.6429" y="-21.2172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S1</text>
</g>
<!-- S0&#45;&gt;S1 -->
<g id="edge3" class="edge">
<title>
S0-&gt;S1
</title>
<path fill="none" stroke="#000000" d="M138.3084,-25.4172C160.5683,-25.4172 195.5619,-25.4172 220.9758,-25.4172"/>
<polygon fill="#000000" stroke="#000000" points="221.2159,-28.9173 231.2158,-25.4172 221.2158,-21.9173 221.2159,-28.9173"/>
<text text-anchor="middle" x="184.7117" y="-29.6172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">2</text>
</g>
<!-- S1&#45;&gt;S0 -->
<g id="edge4" class="edge">
<title>
S1-&gt;S0
</title>
<path fill="none" stroke="#000000" d="M234.6347,-13.5116C228.2094,-9.9161 220.7415,-6.4406 213.4096,-4.6172 188.6544,1.5391 180.7691,1.5391 156.0138,-4.6172 151.8897,-5.6429 147.7225,-7.1912 143.722,-8.9897"/>
<polygon fill="#000000" stroke="#000000" points="142.1302,-5.8725 134.7888,-13.5116 145.2916,-12.118 142.1302,-5.8725"/>
<text text-anchor="middle" x="184.7117" y="-8.6172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">1 | 4 | 5 | 6</text>
</g>
<!-- S1&#45;&gt;S1 -->
<g id="edge5" class="edge">
<title>
S1-&gt;S1
</title>
<path fill="none" stroke="#000000" d="M245.0006,-45.6035C243.9431,-55.6707 246.4906,-64.6505 252.6429,-64.6505 256.5843,-64.6505 259.0462,-60.9652 260.0286,-55.6696"/>
<polygon fill="#000000" stroke="#000000" points="263.5291,-55.6895 260.2853,-45.6035 256.5314,-55.511 263.5291,-55.6895"/>
<text text-anchor="middle" x="252.6429" y="-68.8505" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">2</text>
</g>
<!-- S2 -->
<g id="node4" class="node">
<title>
S2
</title>
<ellipse fill="#d3d3d3" stroke="#000000" cx="342.1095" cy="-25.4172" rx="21.4314" ry="21.4314"/>
<ellipse fill="none" stroke="#000000" cx="342.1095" cy="-25.4172" rx="25.4687" ry="25.4687"/>
<text text-anchor="middle" x="342.1095" y="-21.2172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">S2</text>
</g>
<!-- S1&#45;&gt;S2 -->
<g id="edge6" class="edge">
<title>
S1-&gt;S2
</title>
<path fill="none" stroke="#000000" d="M274.3003,-25.4172C284.0194,-25.4172 295.7398,-25.4172 306.6828,-25.4172"/>
<polygon fill="#000000" stroke="#000000" points="306.8456,-28.9173 316.8456,-25.4172 306.8456,-21.9173 306.8456,-28.9173"/>
<text text-anchor="middle" x="295.3762" y="-29.6172" font-family="Lato, sans-serif" font-size="14.00" fill="#000000">3</text>
</g>
</g>
</svg>
<p>It’s similar to the automaton for 55 except that when in state S1, we have a 1-in-6 chance to <em>stay</em> at S1.
Failure to advance does not always force us to start over at S0.
That reduced risk gives the sequence 23 an advantage over 55.</p>
<p>So, given a choice between 55 and 23, you should choose to race with 23.</p>
<h2 id="question-2-what-is-the-expected-number-of-die-rolls-before-55-occurs-what-about-for-23">Question 2: What is the expected number of die rolls before 55 occurs? What about for 23?</h2>
<p>To answer this question, we’ll have to use a little algebra and probability theory.
Let’s start by finding the expected number of rolls needed to win with the sequence 55.</p>
<p>Let <span class="math inline">\(x_i\)</span> be the expected number of die rolls needed to reach state S2 from S<span class="math inline">\(i\)</span>.
We want to find <span class="math inline">\(x_0\)</span>, the expected number of rolls needed to reach the “match” state S2 from the initial state S0.
Referring to the diagram for the 55 automaton, we know that <span class="math inline">\(x_0\)</span> must satisfy the equation</p>
<p><span class="math display">\[ x_0 = 1 + \tfrac{5}{6} x_0 + \tfrac{1}{6} x_1. \]</span></p>
<p>That’s because from S0 we must roll one die for a chance to advance, and, once rolled, we have a 5/6 probability of remaining at S0 and a 1/6 probability of advancing to S1.
If we remain at S0, the expected cost to reach S2 is <span class="math inline">\(x_0\)</span>; and if we advance to S1, the expected cost to reach S2 is <span class="math inline">\(x_1\)</span>.
(While this reasoning is intuitive, it is also justified by the law of total expectation.)</p>
<p>Using similar logic, we can find the equation for <span class="math inline">\(x_1\)</span>:</p>
<p><span class="math display">\[ x_1 = 1 + \tfrac{5}{6} x_0 + \tfrac{1}{6} x_2. \]</span></p>
<p>And the equation for <span class="math inline">\(x_2\)</span> is trivial, since it takes zero rolls to reach S2 from S2:</p>
<p><span class="math display">\[ x_2 = 0. \]</span></p>
<p>Now it’s a matter of solving the system of equations for <span class="math inline">\(x_0\)</span>, <span class="math inline">\(x_1\)</span>, and <span class="math inline">\(x_2\)</span>.
Substituting 0 for <span class="math inline">\(x_2\)</span> in the equation for <span class="math inline">\(x_1\)</span> gives</p>
<p><span class="math display">\[ x_1 = 1 + \tfrac{5}{6} x_0. \]</span></p>
<p>And substituting this expression for <span class="math inline">\(x_1\)</span> in the equation for <span class="math inline">\(x_0\)</span> gives</p>
<p><span class="math display">\[ x_0  = 1 + \tfrac{5}{6} x_0  + \tfrac{1}{6} \left( 1 + \tfrac{5}{6} x_0 \right) = \tfrac{7}{6}  + \tfrac{35}{36} x_0. \]</span></p>
<p>Subtracting <span class="math inline">\(\tfrac{35}{36} x_0\)</span> from both sides gives us</p>
<p><span class="math display">\[ \tfrac{1}{36} x_0 = \tfrac{7}{6}. \]</span></p>
<p>And multiplying both sides by 36 solves the equation:</p>
<p><span class="math display">\[ x_0 = \tfrac{7}{6}(36) = (7)(6) = 42. \]</span></p>
<p>So, on average, you need 42 rolls to find your sequence when you choose 55.</p>
<p>Now let’s consider the case when you choose 23 as your sequence.
Referring to the diagram for the 23 automaton, the corresponding equations are:</p>
<p><span class="math display">\[\begin{align}
x_0 &amp; = 1 + \tfrac{5}{6} x_0 + \tfrac{1}{6} x_1 \\
x_1 &amp; = 1 + \tfrac{4}{6} x_0 + \tfrac{1}{6} x_1 + \tfrac{1}{6} x_2 \\
x_2 &amp; = 0
\end{align}\]</span></p>
<p>Solving this system of equations (I’ll skip the algebra), we find that <span class="math inline">\(x_0 = 36\)</span>.</p>
<p>So, on average, you need 36 die rolls to find your sequence when you choose 23.
That’s notably faster than 42 rolls when you choose 55.</p>
</div>
]]></summary>
</entry>
<entry>
    <title>A Great Old-Timey Game-Programming Hack</title>
    <link href="http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html" />
    <id>http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html</id>
    <published>2013-12-14T00:00:00Z</published>
    <updated>2013-12-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-12-14">December 14, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;assembly&#39;." href="/tags/assembly.html" rel="tag">assembly</a>, <a title="All pages tagged &#39;6809&#39;." href="/tags/6809.html" rel="tag">6809</a>, <a title="All pages tagged &#39;games&#39;." href="/tags/games.html" rel="tag">games</a>, <a title="All pages tagged &#39;hacks&#39;." href="/tags/hacks.html" rel="tag">hacks</a></span></div>

<div itemprop="articleBody">
<p>A long time ago, when I was a college undergrad, I spent some time working on computer video games.
This was in the 8-bit PC era, when the gaming hardware was almost impossibly slow by today’s standards.</p>
<p>It might not surprise you, then, to learn that game programmers of yore did all sorts of crazy things to make their games run at playable speeds.
Crazy, crazy things.</p>
<p>This is a story about one of those things.</p>
<p>While I’ve done my best to recall the important details, I may have gotten some things wrong.
If I have, please forgive me.
It was a long time ago.</p>
<p>(<em>Note: This post contains some small images as inline-data URLs that some feed readers apparently don’t handle well. If you can’t see the images in your feed, click through to the original article to see them.</em>)</p>
<p><em>Update 2013-12-16: There have been lots of great comments about this story on <a href="https://news.ycombinator.com/item?id=6913467">Hacker News</a> and <a href="http://www.reddit.com/r/programming/comments/1t05uy/a_great_oldtimey_gameprogramming_hack/">Proggit</a>, as well as <a href="http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html#disqus_thread">here on the blog</a>. Thanks for sharing, everyone!</em></p>
<h3 id="the-set-up">The set-up</h3>
<p>A friend of mine, a gifted programmer, was nearly finished with a new game.
Somehow, he had squeezed into a 1980’s-era PC, pretty faithfully, what was at the time a graphically impressive coin-op game popular at the arcades.</p>
<p>The only problem was that his version of the game was unplayable.
It was too slow, and the choppy motion broke the player’s immersion.
It was after all a side-scroller.</p>
<p>My friend, who had been working on the game while also taking a full load of college courses, was starting to seem a little frazzled.
Fearing that he had missed some easy optimization, he asked me to take a look at the code.</p>
<p>I did. But there was no easy optimization to be had.</p>
<p>The code was <em>tight</em>.
Everywhere I looked, he had already done all the things I could think of.
Loops had been unrolled.
Unneeded draws had been eliminated.
All evidence of waste had vanished.</p>
<p>And, with them, our hopes of an easy fix.</p>
<p>But what about a hard fix?
A crazy fix?</p>
<p>Well, that was always a possibility.</p>
<p>Before I get to the crazy stuff, however, I should back up and explain how graphics hardware worked back then.</p>
<h3 id="how-graphics-hardware-worked-back-then">How graphics hardware worked back then</h3>
<p>Here’s the quick version:
The graphics hardware didn’t do jack squat.</p>
<p>On the PC in question, if you wanted to draw something onto the screen, you had to do that yourself, byte by byte.
No texture mappers, no blitters.
Just bytes.
Bytes that you had to move yourself.</p>
<p>Fun.</p>
<p>My friend’s game spent most of its time redrawing the background.
(Again: side-scroller.)
For every frame, it had to draw nearly a screen’s worth of background tiles, shifted for the player’s position.</p>
<p>If my memory serves me, each tile was 28 by 28 pixels.
Each pixel was one of 16 colors, taking half a byte to represent.
Therefore, tiles were represented in memory as 28 contiguous rows of 14 bytes each.
The first 14 bytes represented the first row, the second 14 bytes the second row, and so on.</p>
<p>The screen, however, was 320 pixels wide by 240 pixels high.
In memory, then, a screen buffer was laid out as 240 contiguous rows of 160 bytes each.</p>
<p>So when copying a tile at address <em>X</em> onto a screen buffer location starting at address <em>Y</em>, you had to copy 28 rows.
To copy each row, you had to copy 14 bytes.
Fortunately, the processor for this game was a 6809, which had a few 16-bit index registers and delightful “auto-increment” addressing modes (sort of like applying the postfix <code>++</code> operator to pointers in C).
That meant you could copy 4 pixels at a time while advancing both the <em>X</em> and <em>Y</em> registers in passing:</p>
<pre><code>    LDU ,X++     ; read a 2-byte word (= 4 pixels) from source tile
    STU ,Y++     ; write it to screen buffer</code></pre>
<p>To copy a full row, you had to do that seven times, so you might sandwich those lines within a 7-count loop:</p>
<pre><code>    LDB #7       ; remaining words &lt;- tile width in words
@LOOP
    LDU ,X++     ; read a 2-byte word (= 4 pixels) from source tile
    STU ,Y++     ; write it to screen buffer
    DECB         ; reduce remaining-word count
    BNE @LOOP    ; loop while words remain</code></pre>
<p>When you were done copying the row, you needed to advance the destination pointer <em>Y</em> so that it pointed to the starting address for the next row you would draw into the screen buffer.
Since the screen buffer was 160 bytes wide and a tile was only 14 bytes wide, that meant you had to add their difference to <em>Y</em>:</p>
<pre><code>    LEAY 160-14,Y</code></pre>
<p>And, just like that, you have copied a row onto the screen.</p>
<p>That’s one.
To copy a full tile, you need to do the same thing 28 times.
So, in turn, you sandwich <em>that</em> code within a 28-count loop.</p>
<p>Putting it all together, and giving names to the important numbers, you might end up with a subroutine like this:</p>
<pre><code>;;; important constants

SCRW = 160          ; screen-buffer width in bytes (= 320 4-bit pixels)
TILW =  14          ; background-tile width in bytes (= 28 4-bit pixels)
TILH =  28          ; background-tile height in rows
WOFF = SCRW - TILW  ; s-b offset from end of one tile row to start of next


COPYTILE
;;;
;;; Copy a 28x28 background tile into a screen buffer.
;;; Arguments:
;;;   X = starting address of background tile
;;;   Y = starting address of destination in screen buffer
;;;
    LDA #TILH               ; remaining rows &lt;- tile height
@COPYROW
    LDB #TILW/2             ; remaining words &lt;- tile width in words
@LOOP
    LDU ,X++                ; read a word (= 4 pixels) from source tile
    STU ,Y++                ; write it to screen buffer
    DECB                    ; reduce remaining-word count
    BNE @LOOP               ; loop while words remain
    ;;
    LEAY WOFF,Y             ; advance dst ptr to start of next dst row
    DECA                    ; reduce remaining-row count
    BNE @COPYROW            ; loop while rows remain
    ;;
    RTS                     ; done! return to caller</code></pre>
<p>And that code would be fine.</p>
<p>If you didn’t care about speed.</p>
<h3 id="caring-about-speed">Caring about speed</h3>
<p>Knowing that the game is probably going to spend most of its time running that code, you do what any good programmer would: start counting cycles.
Here’s the inner loop again, with setup and finishing, annotated with cycle counts:</p>
<pre><code>    LDB #TILW/2             ; 2 cycles (set-up)
@LOOP
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    DECB                    ; 2
    BNE @LOOP               ; 3
    ;;
    LEAY WOFF,Y             ; 8 (finishing)</code></pre>
<p>Looking at those counts within the loop, you’re not likely to miss that you’re burning 21 cycles to copy just 4 pixels.
To copy a full row, then, works out to 2 cycles + (7 iterations) * (21 cycles/iteration) + 8 cycles = 157 cycles.
Ouch.</p>
<p>But this isn’t your first time at the keyboard.
You know what to do.
Unroll that loop!</p>
<pre><code>    LDU ,X++                ; 8 cycles
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LDU ,X++                ; 8
    STU ,Y++                ; 8
    LEAY WOFF,Y             ; 8 (finishing)</code></pre>
<p>Now, with the loop overhead reduced to zero – you’ve even eliminated the set-up – each row takes only 7 * (8 + 8) + 8 = 120 cycles.
That’s a 30-percent speed-up.
Pretty good.</p>
<p>And that’s where most programmers probably would have left it.</p>
<p>But not my friend.</p>
<p>He knew that those <code>++</code> operations were costly, 3 cycles apiece.
And, with the loop unrolled, he also knew exactly where each word to be read or written was located with respect to <em>X</em> or <em>Y</em>.
So he cleverly replaced those 3-cycle post-increments with exact offsets.
They cost only 1 cycle apiece, and the 0 offset is actually free:</p>
<pre><code>    LDU  ,X                 ; 5 cycles
    STU  ,Y                 ; 5
    LDU 2,X                 ; 6
    STU 2,Y                 ; 6
    LDU 4,X                 ; 6
    STU 4,Y                 ; 6
    LDU 6,X                 ; 6
    STU 6,Y                 ; 6
    LDU 8,X                 ; 6
    STU 8,Y                 ; 6
    LDU 10,X                ; 6
    STU 10,Y                ; 6
    LDU 12,X                ; 6
    STU 12,Y                ; 6
    LEAX TILW,X             ; 8 (finishing)
    LEAY SCRW,Y             ; 8 (finishing)</code></pre>
<p>With his optimizations, the cycle count per row had been reduced to (5 + 5) + 6 * (6 + 6) + (8 + 8) = 98 cycles.
Compared to the original code, that’s 60 percent faster:</p>
<pre><code>original_speed  = (1*row) / (157*cycle)
optimized_speed = (1*row) /  (98*cycle)

speed_up  =  optimized_speed / original_speed - 1  =  157 / 98 - 1  =  0.60.</code></pre>
<p>Putting it all together – and, again, I’m going by memory so the code might have been slightly different – the copy-tile subroutine looked something like this, and it copied a full tile, all 28 rows, in a lean 2893 cycles:</p>
<pre><code>COPYTILE2
;;;
;;; Copy a 28x28 screen tile into a screen buffer.
;;; Arguments:
;;;   X = starting address of background tile
;;;   Y = starting address of destination in screen buffer
;;; Execution time:
;;;   4 + 28 * (82 + 8 + 8 + 2 + 3) + 5 = 2893 cycles
;;;
    LDA #TILH      ; initialize row count (4 cycles)
    ;;
@COPY1
    ;; unroll inner loop (copies one row of 28 pixels in 82 cycles)
    LDU ,X         ; (1) read 4 pixels (5 cycles)
    STU ,Y         ;     write 4 pixels (5 cycles)
    LDU 2,X        ; (2) (6 cycles)
    STU 2,Y        ;     (6 cycles)
    LDU 4,X        ; (3) ...
    STU 4,Y        ;     ...
    LDU 6,X        ; (4)
    STU 6,Y        ;
    LDU 8,X        ; (5)
    STU 8,Y        ;
    LDU 10,X       ; (6)
    STU 10,Y       ;
    LDU 12,X       ; (7)
    STU 12,Y       ;
    ;;
    LEAX TILW,X    ; advance src to start of next row (8 cycles)
    LEAY SCRW,Y    ; advance dst to start of next row (8 cycles)
    DECA           ; reduce remaining count by one (2 cycles)
    BNE @COPY1     ; loop while rows remain (3 cycles)
    ;;
    RTS            ; done!  return to caller (5 cycles)</code></pre>
<p>This code, all in all, was 60% faster than the naive <code>COPYTILE</code> code we started out with.</p>
<p>But that wasn’t fast enough.
Not nearly.</p>
<p>So when my friend showed me his code and asked if I could make it faster, I really wanted to help him.
I really wanted to be able to answer yes.</p>
<p>But I had to answer no.
I hated giving that answer.
But, studying the code, I couldn’t see any way to speed it up.</p>
<p>And yet, the hook was set.</p>
<p>Later, I couldn’t get the problem out of my head.
Maybe I had missed something.
I had grown up on Apple II computers and their 6502 processors.
My friend’s code, however, was for the 6809.
Maybe it afforded optimizations that I didn’t know about.</p>
<p>With renewing optimism, I dialed into the university’s library to access the card catalog.
(These were the days before the World Wide Web.)
Through a VT220 terminal emulator, I searched for books about the 6809.</p>
<p>There was one.
A 6809 microprocessor manual.
It was in the engineering library.
Luckily, I was an engineering student and had sign-out privileges.</p>
<p>Just like that, I was off to the library.</p>
<h3 id="a-crazy-idea">A crazy idea</h3>
<p>When I got to the engineering library, I found the book right where it was supposed to be, looking a little beat up:</p>
<p><a href="https://archive.org/details/bitsavers_motorola68_13419254/mode/2up"><em>The MC6809-MC6809E Microprocessor Programming Manual</em></a>.</p>
<p>Not bothering to find a chair, I flipped through the pages standing, looking for some oddball, 6809-specific instruction that might throw a lot of bytes and throw them fast.
Page after page, though, turned up nothing.</p>
<p>Then I came upon <a href="https://archive.org/details/bitsavers_motorola68_13419254/page/n99/mode/2up?q=pshs">PSHS</a>.
“Push registers on the hardware stack.”</p>
<p>On my beloved 6502, if you wanted to save registers on the stack, you had to do it one register at a time and, even then, by transferring them through the accumulator.
It was slow and expensive.
So I had learned to avoid the stack when speed mattered.</p>
<p>But on the 6809 you could save <em>all</em> of the registers – or any subset of them – with <em>a single instruction</em>.
And, amazingly, it cost a mere 5 cycles, plus 1 cycle more per byte pushed.</p>
<p>Since the processor had three 16-bit general-purpose registers – <em>D</em>, <em>X</em>, and <em>Y</em> – I could load them up and then use a single <code>PSHS</code> instruction to write 6 bytes in just 11 cycles.
The corresponding pull instruction, <a href="https://archive.org/details/bitsavers_motorola68_13419254/page/n101/mode/2up?q=puls"><code>PULS</code></a>, had the same low cost.</p>
<p>Further, the 6809 had <em>two</em> stack registers, <em>S</em> and <em>U</em>.
I could use one as a source pointer and the other as a destination pointer.
In theory, with a single <code>PULS</code>/<code>PSHU</code> pair, I could copy 6 bytes in 22 cycles.</p>
<p>That’s crazy, crazy fast.</p>
<p>Excitement mounting, I headed for the front desk and reached for my student ID.
I was going to sign out that wonderful little book for further study.</p>
<h3 id="a-crazy-plan">A crazy plan</h3>
<p>Walking back to the dorms, I formed my plan.</p>
<p>I would save the <em>S</em> and <em>U</em> registers somewhere, and then point <em>S</em> at the background tile and <em>U</em> at the screen buffer.
Then I would pull from <em>S</em> and push to <em>U</em>, copying 6 bytes at a time, using <em>D</em>, <em>X</em>, and <em>Y</em> as go-betweens.
To copy the 14 bytes that make up a row would require three such iterations, which unrolled would be about 60 cycles.</p>
<p>When I reached my room, I found a piece of paper and sketched it out:</p>
<pre><code>    PULS D,X,Y    ; first 6 bytes    11 cycles
    PSHU D,X,Y    ;                  11
    PULS D,X,Y    ; second 6 bytes   11
    PSHU D,X,Y    ;                  11
    PULS D        ; final 2 bytes     7
    PSHU D        ;                   7
    LEAU -WOFF,U  ; advance dst ptr   8</code></pre>
<p>Just 66 cycles, including the after-row adjustment to <em>U</em> that prepares it for the next row.
(Note that the adjustment is now negative.)
For comparison, the naive row-copy loop that we looked at earlier took 157 cycles to do the same thing.
And my friend’s optimized code took 98.
Already, this crazy idea was looking like a big win.</p>
<p>Still, that last <code>PULS</code>/<code>PSHU</code> pair!
What a clunker.
It was needed to handle the final two bytes per row, since the rows were 28 pixels = 14 bytes wide, and 6 doesn’t divide 14 evenly.</p>
<p><em>That darn remainder of 2 bytes!</em></p>
<p>If only the game had used 24-by-24 tiles instead…
But it hadn’t, so I pored through the manual, looking for a way to lower the cost of that inevitable last pair.</p>
<p>And then, by surprise, I struck gold!
It was another 6809 oddity, the <em>DP</em> register.</p>
<p>On the 6502 and most 8-bit processors of the era, the lowest 256 bytes of memory was called the <em>zero page</em>.
The zero page was special because its memory locations had single-byte addresses and could be accessed with shorter and usually faster instructions.</p>
<p>The 6809’s designers took this idea one step further.
They let you use the <em>DP</em> register to designate <em>any</em> page as the zero page, which they called the “direct page.”</p>
<p>But none of my byte-slinging instructions needed to use the direct page.
That meant I could use the <em>DP</em> register as an additional one-byte go-between.
Now I could copy 7 bytes per pull-push pair!</p>
<p>And 14 <em>is</em> evenly divisible by 7.</p>
<p>With this change, I could copy a whole 28-pixel row and advance to the next in just 5 instructions:</p>
<pre><code>    PULS D,X,Y,DP  ; first 7 bytes    12 cycles
    PSHU D,X,Y,DP  ;                  12
    PULS D,X,Y,DP  ; second 7 bytes   12
    PSHU D,X,Y,DP  ;                  12
    LEAU -WOFF,U   ; advance dst ptr   8</code></pre>
<p>56 cycles!
Fifty. Six. Cycles.</p>
<p>That bit of code made me feel just <em>awesome</em>.
I had managed to harness every single available register on the machine for byte-slinging!
<em>D</em>, <em>X</em>, <em>Y</em>, <em>U</em>, <em>S</em>, and even the oddball <em>DP</em> – they were all fully engaged.</p>
<p>I was feeling great about this solution.</p>
<p>Except for just one thing…</p>
<h3 id="ill-have-a-little-more-crazy-please">I’ll have a little more crazy, please</h3>
<p>If you’re acquainted with stacks, you may have noticed a subtle flaw in my brilliant plan:</p>
<p><em>Pushes and pulls work in opposite directions.</em></p>
<p>See, I lied about that little block of code I just showed you.
It didn’t <em>actually</em> copy one row from a background tile onto the screen.
What it actually did was break the row into two 7-byte blocks – I’ll call them “septets” – and then draw them onto the screen <em>swapped</em>.</p>
<p>Recall that tile rows were laid out sensibly in memory as 14 contiguous bytes, like this:</p>
<pre><code>+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 0   1   2   3   4   5   6   7   8   9   A   B   C   D |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+</code></pre>
<p>So when you pulled-and-pushed a row onto the screen in 7-byte septets, it would get horizontally split like this:</p>
<pre><code>+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
| 7   8   9   A   B   C   D | 0   1   2   3   4   5   6 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+</code></pre>
<p>The first septet was now second, and the second now first.
Note, however, that the bytes within each septet were unchanged; they retained their original ordering.</p>
<p>Further, if you ran the row-copy code multiple times, the vertical stack of rows you copied would end up being upside down.
That’s because the code uses pushes to write the rows onto the screen.
Pushes move the stack pointer toward lower addresses, and lower addresses correspond to screen lines higher up on the display.</p>
<p>To visualize the havoc that this row-reversal and septet-swapping would wreak, let’s say that you had the following 28-by-28 tile, representing a key:</p>
<p><img style="image-rendering: pixelated; border: solid 1px black; width: 50%; height: 50%;" src="data:image/gif;base64,R0lGODlhHAAcAIQQAE88FHZNAH19crB7ApCAT5+BNL6bN8+iIN2sEMqwavTGIfDNTfbbcPflmPbsvPz43v///////////////////////////////////////////////////////////////yH5BAEKABAALAAAAAAcABwAAAXOICSOZGmeaKqupeK6iMGiytI4TcMshjCTisZjSGzwfqLg0JEoJBwPY+KnYCwNBULB8GQcpiwFlDkYEATbHOIwUywThsOBABjkFogZ4uHA5eQEdg54en05OQxrCGpsLIs6hwwuDH8yjjoMmZkLlEYGBI6aopl3cz4qB5ScozsLBwWnKakNCK0Lt7cHWLEoswi4CGXCWSypiQvCA0gjA5kwysvMmQjP0SLNiS8DAdbNeM/c0QOKwWXh4tQKBwEAANYiAenr7yMBA3Lb9Pr7PyEAOw==" alt="A pixel-art image of a key."/></p>
<p>If you had used 28 applications of my row-copy code to draw it onto the screen, you would have ended up with this not-a-key:</p>
<p><img style="image-rendering: pixelated; border: solid 1px black; width: 50%; height: 50%;" src="data:image/gif;base64,R0lGODlhHAAcAIQQAE88FHZNAH19crB7ApCAT5+BNL6bN8+iIN2sEMqwavTGIfDNTfbbcPflmPbsvPz43v///////////////////////////////////////////////////////////////yH5BAEKABAALAAAAAAcABwAAAXQICSOZGmeaKquZTAcxxCwaoAoyjHT6HDnAQCAZ/IdEIiBckccDRiLX5LZhDwZP4VMNKhepV1IUqksEFZXXFK0aLsPhoJAdWBgF2S7Hro4yOkMDQhue3YNDX0Ecyl1glCFC4GIBmeAiIaHDDiScCwIeoeZCEeHozQIDQwOoTAEAw0OUaeHDgkGrQCviAinDr4JSooFBqUHpw8OyHEEwwkODAcJNAoP1cgJBc4PiNLTyQ3W1pNECgwPCguwmQsGizwKDRA48wgGVSIK9/r7/P0sIQA7" alt="A distorted pixel-art image of a key; the original image has been reflected across its horizontal axis, cut in half from top to bottom, and had its left and right halves swapped."/></p>
<p>So . . . <em>that</em> was a problem.</p>
<p>But this problem, too, had an elegant solution!</p>
<p>To review:</p>
<ul>
<li>the rows were upside down</li>
<li>the septets within each row were swapped</li>
<li>but the bytes within each septet were unchanged</li>
</ul>
<p>The breakthrough was to see “upside down” and “swapped” as two instances of the same thing. <em>Reversal.</em></p>
<p>Reversal has this handy property: it’s an <a href="http://en.wikipedia.org/wiki/Involution_(mathematics)"><em>involution</em></a>.
Reverse something twice, and you get back the original.
With this in mind, I reasoned that if the tiles were pre-processed to reverse their rows and then the septets within the rows, the tiles would end up looking fine when they hit the screen.
The mangling that occurred during copying and pre-processing would, in effect, undo each other.</p>
<p>Working it out on paper, I also discovered that the pre-processing step could ignore the rows and just treat the tiles as one long, linear sequence of septets.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
To see why this is so, let’s consider a small tile of 2 rows of 2 septets each:</p>
<pre><code>+---+---+
| a   b |
+---+---+
| c   d |
+---+---+</code></pre>
<p>In memory, it would be laid out in row-major order, that is, as 4 sequential septets:</p>
<pre><code>+---+---+---+---+
| a   b | c   d |
+---+---+---+---+</code></pre>
<p>So, reversing the rows and then swapping the septets within each row is the same as just reversing the septet order in memory:</p>
<pre><code>+---+---+                  +---+---+                  +---+---+
| a   b |                  | c   d |                  | d   c |
+---+---+        =======&gt;  +---+---+        =======&gt;  +---+---+
| c   d |        reverse   | a   b |        swap      | b   a |
+---+---+        rows      +---+---+        septets   +---+---+

+---+---+---+---+          +---+---+---+---+          +---+---+---+---+
| a   b | c   d |          | c   d | a   b |          | d   c | b   a |
+---+---+---+---+          +---+---+---+---+          +---+---+---+---+</code></pre>
<p>So the solution to the mangling problem turned out to be a simple, one-time pre-processing step:
Just break each tile into septets and reverse their order.</p>
<p>Knowing that the mangling problem could be solved, I was feeling good about my overall idea.
I couldn’t see any other problems, so I sketched out a new copy-tile subroutine to present to my friend.
Since the row-copy logic was now just 5 instructions, I used it 4 times, unrolling the sole remaining loop a bit.
Now, instead of copying 28 single rows, I copied 7 quad-rows.</p>
<p>The code looked something like this:</p>
<pre><code>COPYTILE3
;;;
;;; Copy a 28x28 screen tile into a screen buffer.
;;; Arguments:
;;;   X = starting address of *septet-reversed* background tile
;;;   Y = starting address of destination in screen buffer
;;; Execution time:
;;;   34 + 7 * (224 + 7 + 3) + 7 + 10 = 1689 cycles
;;;
    ;; setup:  34 cycles
    PSHS U,DP      ; save U and DP (8 cycles)
    STS &gt;SSAVE     ; save S (7 cycles)
    ;;
    LDA #TILH/4    ; initial quad-row count (2 cycles)
    STA &gt;ROWCT     ; (5 cycles)
    ;;
    LEAS ,X                    ; initialize src ptr (4 cycles)
    LEAU (TILH-1)*SCRW+TILW,Y  ; initialize dst ptr (8 cycles)
    ;;
@COPY1
    ;; copy four rows of 28 pixels in 4 * (48 + 8) = 224 cycles
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    LEAU -WOFF,U
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    LEAU -WOFF,U
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    LEAU -WOFF,U
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    PULS X,Y,D,DP
    PSHU X,Y,D,DP
    LEAU -WOFF,U
    ;;
    DEC &gt;ROWCT     ; reduce remaining quad-row count by one (7 cycles)
    BNE @COPY1     ; loop while quad-rows remain (3 cycles)
    ;;
    LDS  &gt;SSAVE    ; restore S (7 cycles)
    PULS U,DP,PC   ; restore regs and return to caller (10 cycles)

SSAVE ZMD  1       ; stash for saving S while drawing
ROWCT ZMB  1       ; var: remaining rows to copy</code></pre>
<p>Adding up the cycles, the total was just 1689.
I had shaved almost 1200 cycles off of my friend’s code.
That’s a 70 percent speed-up!</p>
<p>Beaming, I went to show my friend.</p>
<h3 id="the-acid-test">The acid test</h3>
<p>When I caught up with my friend and said I’d figured out how to make the copy-tile routine 70% faster, his face lit up.
When I explained about the whole septets-and-mangling thing, though, his face unlit, doubts rising.
But when I showed him the code, he got it.
It clicked.</p>
<p>“Let’s try it out!” he said.</p>
<p>In about a half hour’s work, he had the code integrated into the game.
After a rebuild and reboot, the game was loading.</p>
<p>The title screen came up.</p>
<p>He was into the game.</p>
<p>And . . .</p>
<p><em>Holy crap!</em></p>
<p>The game seemed amazingly fast.
In truth, it was probably only a third to a half faster, but that was enough.
Some important perceptual threshold had been crossed.
The game-play was now smooth, natural.
You could feel the difference.</p>
<p>We just sat there, playing the game and grinning.
It was a good day.</p>
<p>But it would not last.</p>
<h3 id="in-for-a-penny-.-.-.">In for a penny . . .</h3>
<p>A few days after the speed problem was behind us – or so we thought – the game’s finishing touches were applied.
One of those finishing touches was sampled sound effects.
This required feeding byte-sized morsels to the audio-output DAC a few thousand times each second.
To schedule the feedings, my friend had turned on a hardware-clocked interrupt.</p>
<p>Worked like a charm.
The sounds sounded great, and everything was perfect.</p>
<p>Except for one thing.</p>
<p>After playing into the game one night, we noticed that some of the tiles were getting corrupted.
The more we played, the more corruption we saw.</p>
<p><em>Oh, no.</em></p>
<p>Something very bad was happening.</p>
<p>And then it hit us.</p>
<p>What happens if an interrupt goes off during the copy-tile routine?</p>
<p>The processor, to prepare for calling the interrupt handler, would push its current state onto the system stack.
But, during the copy-tile routine, <em>there was no system stack</em>.
The system-stack register <em>S</em> had been commandeered.
And where was it pointing?
Right into the memory buffer that held the reference tiles!</p>
<p>Oops.</p>
<p>We slumped.
After all that effort, to think that our all-important speed-up was causing memory corruption…</p>
<p>Needing a break, we walked to an all-night diner near campus to eat and think.
Over pancakes and bacon, scrapple and grilled stickies, we talked through the problem.</p>
<p>There were only two stack registers, and without commandeering both of them, the copy-tile routine wouldn’t be nearly as fast.
There was no way, then, to return the <em>S</em> register to the system without losing our hard-won speed.
But there was also no way that we could get reliable sound without using interrupts.</p>
<p>One way or another, then, interrupts were going to be triggered.
And, when they were, if copy-tile was running, whatever <em>S</em> was pointing to was going to get hammered.</p>
<p>“How can we prevent the corruption?” I asked.</p>
<p>We sat there, ignoring our food, the question hanging in the air.</p>
<p>Suddenly, my friend slapped the table.
He had it.</p>
<p>“Don’t prevent it!” he said.</p>
<p>“What?” I asked.</p>
<p>“Don’t prevent the corruption,” he explained.
“Let it happen.
Just not to the reference tiles.”</p>
<p>It was simple, really.
He continued:</p>
<p>“Just swap <em>S</em> and <em>U</em> in the copy-tile routine.
<em>U</em> will point at the reference tiles, and <em>S</em> at the screen buffer.
If an interrupt goes off, the corruption will happen where <em>S</em> is pointing – <em>on the screen.</em>
The corruption will last only until we redraw the next frame.”</p>
<p>“That’s brilliant!” I said.</p>
<p>Eager to try his solution, we quickly finished our meal.</p>
<h3 id="in-for-a-pound">. . . In for a pound</h3>
<p>Walking back to the dorms, though, it bothered us that players might see screen glitches, even if for just a frame.
We both felt that there had to be some way to make the hack perfect, if only we could find it.</p>
<p>Later that night, we found it.</p>
<p>Again, it was simple once we saw it.
All we had to do was change the tile ordering.
Instead of placing the tiles onto the screen from top to bottom, left to right, we would go right to left, bottom to top.
In other words, from high addresses to low addresses.</p>
<p>That way, when an interrupt went off and corrupted the memory locations immediately before the tile we were currently drawing, the corruption would be fixed when the very next tile was drawn.
And since tile-drawing took place in a buffer that wasn’t displayed until it was fully drawn (and the vertical refresh had occurred), nobody would ever see the corruption.<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<p>It was the perfect hack!</p>
<h3 id="to-the-old-days">To the old days!</h3>
<p>And that’s the way things were.
The challenge wasn’t overwhelming complexity, as it is today.
The challenge was cramming your ideas into machines so slow, so limited that most ideas didn’t fit.</p>
<p>You had to bang your ideas around, twist them, turn them, searching for something, <em>anything</em> that would help you squeeze them into the machine.
Sometimes you found it, and you got one step closer to realizing your ideas.
Sometimes you didn’t.</p>
<p>But the search was always instructive.</p>
<p>In this case, the search yielded several small victories that, together, solved the problem.
But when you consider all the things we had to do to make that darn game fast enough, it does seem crazy.</p>
<p>We started with a tile-copying subroutine whose core was a hand-tuned, unrolled loop of machine instructions.
Then, to buy a 70-percent speed-up:</p>
<ol type="1">
<li>We replaced this subroutine with a very special manifestation of insanity that commandeered both stack pointers and used pulls and pushes, and every single available register, to draw tiles <em>upside down and horizontally broken</em>.</li>
<li>Then we pre-processed the tiles so that drawing them would actually <em>fix</em> them.</li>
<li>But then – <em>dammit!</em> – interrupts that occurred during drawing could corrupt the reference tiles.</li>
<li>So, to protect the reference tiles, we corrupted the screen buffer instead.</li>
<li>But that corruption would be visible.</li>
<li>So we changed the tile-placement order to repair – <em>on the fly</em> – any corruption that might have occurred, before it could ever be displayed.</li>
<li>And it all worked!</li>
</ol>
<p>We did <em>that.</em>
For 70 percent.</p>
<p>And it was <em>so</em> worth it.</p>
<h3 id="tell-em-if-you-got-em">Tell ’em if you got ’em</h3>
<p>Anyway, I wanted to share that story with you for two reasons.</p>
<p>The first is that it’s a fun story.
It’s one my earliest memories of struggling with a messy computing problem and, through dogged persistence, zeroing in on a solution that was both effective and elegant.
The result was powerfully satisfying.</p>
<p>The struggle, I learned, is worth it.</p>
<p>The second reason is to encourage you to tell your stories.
I know that, “back in the day,” most video games probably gave rise to many stories like this one.
I’d love to hear them.
But too many of them are lost, having faded out of memory before anyone thought to preserve them.</p>
<p>If you have a story, please don’t wait.
Tell it.
Every day you wait, it gets harder.</p>
<p>Tell it.</p>
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>Exercise: Prove that for all finite sequences of finite sequences, applying (<em>reverse</em> ⋅ <em>concat</em>) is the same as applying (<em>concat</em> ⋅ <em>reverse</em> ⋅ <em>map</em> <em>reverse</em>).<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2"><p>We also had to make sure that nothing valuable was stored in the memory locations just before a screen buffer.
They could, in theory, also be corrupted if an interrupt occurred while placing the top-left septet of the top-left corner tile.
This septet’s address corresponded to the start of the buffer.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
]]></summary>
</entry>
<entry>
    <title>Tricks of the trade: Recursion to Iteration, Part 4: The Trampoline</title>
    <link href="http://blog.moertel.com/posts/2013-06-12-recursion-to-iteration-4-trampolines.html" />
    <id>http://blog.moertel.com/posts/2013-06-12-recursion-to-iteration-4-trampolines.html</id>
    <published>2013-06-12T00:00:00Z</published>
    <updated>2013-06-12T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-06-12">June 12, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;programming&#39;." href="/tags/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;recursion&#39;." href="/tags/recursion.html" rel="tag">recursion</a>, <a title="All pages tagged &#39;iteration&#39;." href="/tags/iteration.html" rel="tag">iteration</a>, <a title="All pages tagged &#39;python&#39;." href="/tags/python.html" rel="tag">python</a>, <a title="All pages tagged &#39;recursion-to-iteration series&#39;." href="/tags/recursion-to-iteration%20series.html" rel="tag">recursion-to-iteration series</a>, <a title="All pages tagged &#39;tail calls&#39;." href="/tags/tail%20calls.html" rel="tag">tail calls</a>, <a title="All pages tagged &#39;data structures&#39;." href="/tags/data%20structures.html" rel="tag">data structures</a>, <a title="All pages tagged &#39;trampolines&#39;." href="/tags/trampolines.html" rel="tag">trampolines</a></span></div>

<div itemprop="articleBody">
<p>This is the fourth article in <a href="http://blog.moertel.com/tags/recursion-to-iteration%20series.html">a series on converting recursive algorithms into iterative algorithms</a>.
If you haven’t read the earlier articles first, you may want to do so before continuing.</p>
<p>In <a href="http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html">the first article of our series</a>, we showed that if you can convert an algorithm’s recursive calls into tail calls, you can eliminate those tail calls to create an iterative version of the algorithm using The Simple Method.
In this article, we’ll look at another way to eliminate tail calls: the <em>trampoline</em>.</p>
<p>The idea behind the trampoline is this: before making a tail call, manually remove the current execution frame from the stack, eliminating stack build-up.</p>
<h3 id="execution-frames-and-the-stack">Execution frames and the stack</h3>
<p>To understand why we might want to manually remove an execution frame, let’s think about what happens when we call a function.
The language runtime needs some place to store housekeeping information and any local variables the function may use, so it allocates a new execution frame on the stack.
Then it turns control over to the function.
When the function is done, it executes a <code>return</code> statement.
This statement tells the runtime to remove the execution frame from the stack and to give control (and any result) back to the caller.</p>
<p>But what if the function doesn’t return right away?
What if it makes another function call instead?
In that case, the runtime must create a new execution frame for <em>that</em> call and push it onto the stack, on top of the current frame.
If the function ends up calling itself many times recursively, each call will add another frame to the stack, and pretty soon we will have eaten up a lot of stack space.</p>
<h3 id="eliminating-stack-build-up">Eliminating stack build-up</h3>
<p>To avoid this problem, some programming languages guarantee that they will recycle the current execution frame whenever a function makes a tail call.
That is, if the function calls some other function (or itself recursively) and just returns that function’s result verbatim, that’s a tail call.
In that case, the runtime will recycle the current function’s execution frame before transferring control to the other function, making it so that the other function will return its result directly to the original function’s caller.
This process is called <em>tail-call elimination</em>.</p>
<p>But in languages like Python that don’t offer tail-call elimination, every call, even if it’s a tail call, pushes a new frame onto the stack.
So if we want to prevent stack build-up, we must somehow eliminate the current frame from the stack ourselves, before making a tail call.</p>
<p>But how?
The only obvious way to eliminate the current frame is to <code>return</code> to our caller.
If we’re to make this work, then, the caller must be willing to help us out.
That’s where the trampoline comes in.
It’s our co-conspirator in the plot to eliminate stack build-up.</p>
<h3 id="the-trampoline">The trampoline</h3>
<p>Here’s what the trampoline does:</p>
<ol type="1">
<li>It calls our function <code>f</code>, making itself the current caller.</li>
<li>When <code>f</code> wants to make a recursive tail call to itself, it returns the instruction <code>call(f)(*args, **kwds)</code>.
The language runtime dutifully removes the current execution frame from the stack and returns control to the trampoline, passing it the instruction.</li>
<li>The trampoline interprets the instruction and calls <code>f</code> back, giving it the supplied arguments, and again making itself the caller.</li>
<li>This process repeats until <code>f</code> wants to return a final result <code>z</code>; then it returns the new instruction <code>result(z)</code> instead.
As before, the runtime removes the current execution frame from the stack and returns control to the trampoline.</li>
<li>But now when the trampoline interprets the new instruction it will return <code>z</code> to <em>its</em> caller, ending the trampoline dance.</li>
</ol>
<p>Now you can see how the trampoline got its name.
When our function uses a <code>return</code> statement to remove its own execution frame from the stack, the trampoline bounces control back to it with new arguments.</p>
<p>Here’s a simple implementation.
First, we will encode our instructions to the trampoline as triples.
We’ll let <code>call(f)(*args, **kwds)</code> be the triple <code>(f, args, kwds)</code>,
and <code>result(z)</code> be the triple <code>(None, z, None)</code>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> call(f):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Instruct trampoline to call f with the args that follow.&quot;&quot;&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> g(<span class="op">*</span>args, <span class="op">**</span>kwds):</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> f, args, kwds</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> g</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> result(value):</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Instruct trampoline to stop iterating and return a value.&quot;&quot;&quot;</span></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> <span class="va">None</span>, value, <span class="va">None</span></span></code></pre></div>
<p>Now we’ll create a decorator to wrap a function with a trampoline that will interpret the instructions that the function returns:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> functools</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> with_trampoline(f):</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Wrap a trampoline around a function that expects a trampoline.&quot;&quot;&quot;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="at">@functools.wraps</span>(f)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> g(<span class="op">*</span>args, <span class="op">**</span>kwds):</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>        h <span class="op">=</span> f</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>        <span class="co"># the trampoline</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> h <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>            h, args, kwds <span class="op">=</span> h(<span class="op">*</span>args, <span class="op">**</span>kwds)</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> args</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> g</span></code></pre></div>
<p>Note that the trampoline boils down to three lines:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="cf">while</span> h <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    h, args, kwds <span class="op">=</span> h(<span class="op">*</span>args, <span class="op">**</span>kwds)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> args</span></code></pre></div>
<p>Basically, the trampoline keeps calling whatever function is in <code>h</code> until that function returns a <code>result(z)</code> instruction, at which time the loop exits and <code>z</code> is returned.
The original recursive tail calls have been boiled down to a <code>while</code> loop.
Recursion has become iteration.</p>
<h3 id="example-factorial">Example: factorial</h3>
<p>To see how we might use this implementation, let’s return to the factorial example from <a href="http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html">the first article in our series</a>:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n):</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>Step one, as before, is to tail-convert the lone recursive call:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">def</span> factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>     <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>         <span class="cf">return</span> acc</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>     <span class="cf">return</span> factorial(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span></code></pre></div>
<p>Now we can create an equivalent function that uses trampoline idioms:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> trampoline_factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> result(acc)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> call(trampoline_factorial)(n <span class="op">-</span> <span class="dv">1</span>, n <span class="op">*</span> acc)</span></code></pre></div>
<p>Note how the <code>return</code> statements have been transformed.</p>
<p>Finally, we can wrap this function with a trampoline to get a callable version that we can use just like the original:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>factorial <span class="op">=</span> with_trampoline(trampoline_factorial)</span></code></pre></div>
<p>Let’s take it for a spin:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> factorial(<span class="dv">5</span>)</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="dv">120</span></span></code></pre></div>
<p>To really see what’s going on, be sure to use the Online Python Tutor’s visualizer to step through the original, tail-recursive, and trampoline versions of the function.
Just open this link: <a href="http://www.pythontutor.com/visualize.html#code=%23+our+trampoline+library%0A%0Aimport+functools%0A%0Adef+call(f)%3A%0A++++%22%22%22Instruct+trampoline+to+call+f+with+the+args+that+follow.%22%22%22%0A++++def+g(*args,+**kwds)%3A%0A++++++++return+f,+args,+kwds%0A++++return+g%0A%0Adef+result(value)%3A%0A++++%22%22%22Instruct+trampoline+to+stop+iterating+and+return+a+value.%22%22%22%0A++++return+None,+value,+None%0A%0Adef+with_trampoline(f)%3A%0A++++%22%22%22Wrap+a+trampoline+around+a+function+that+expects+a+trampoline.%22%22%22%0A++++%40functools.wraps(f)%0A++++def+g(*args,+**kwds)%3A%0A++++++++h+%3D+f%0A++++++++%23+the+trampoline%0A++++++++while+h+is+not+None%3A%0A++++++++++++h,+args,+kwds+%3D+h(*args,+**kwds)%0A++++++++return+args%0A++++return+g%0A%0A%0A%23+original+recursive+version+of+factorial+function%0A%0Adef+factorial(n)%3A%0A++++if+n+%3C+2%3A%0A++++++++return+1%0A++++return+n+*+factorial(n+-+1)%0A%0Aprint+factorial(5)%0A%0A%0A%23+tail-call+recursive+version%0A%0Adef+factorial(n,+acc%3D1)%3A%0A+++++if+n+%3C+2%3A%0A+++++++++return+acc%0A+++++return+factorial(n+-+1,+acc+*+n)%0A%0Aprint+factorial(5)%0A%0A%0A%23+trampoline-based+tail-call+version+(%3D+iterative)%0A%0Adef+trampoline_factorial(n,+acc%3D1)%3A%0A++++if+n+%3C+2%3A%0A++++++++return+result(acc)%0A++++return+call(trampoline_factorial)(n+-+1,+n+*+acc)%0A%0Afactorial+%3D+with_trampoline(trampoline_factorial)%0A%0Aprint+factorial(5)%0A&amp;mode=display&amp;cumulative=false&amp;heapPrimitives=false&amp;drawParentPointers=false&amp;textReferences=false&amp;showOnlyOutputs=false&amp;py=2&amp;curInstr=0">Visualize the execution</a>.
(ProTip: use a new tab.)</p>
<h3 id="why-use-the-trampoline">Why use the trampoline?</h3>
<p>As I mentioned at the beginning of this article, if you can convert a function’s recursive calls into tail calls – which you must do to use a trampoline – you can also use the Simple Method to convert the function’s recursion into iteration, eliminating the calls altogether.
For example, here’s what the Simple Method does to our original <code>factorial</code> function:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> n <span class="op">&gt;</span> <span class="dv">1</span>:</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        (n, acc) <span class="op">=</span> (n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> acc</span></code></pre></div>
<p>This version is simpler and more efficient than the trampoline version.
So why not use the Simple Method always?</p>
<p>The answer is that the Simple Method is tricky to apply to functions that make tail calls from within loops.
Recall that it introduces a loop around a function’s body and replaces recursive tail calls with <code>continue</code> statements.
But if the function already has its own loops, replacing a tail call within one of them with a <code>continue</code> statement will restart that inner loop instead of the whole-body loop, as desired.
In that case, you must add condition flags to make sure the right loop gets restarted, and that gets old fast.
Then, using a trampoline may be a win.</p>
<p>That said, I almost never use trampolines.
Getting a function into tail-call form is nine tenths of the battle.
If I’ve gone that far already, I’ll usually go the rest of the way to get a tight, iterative version.</p>
<p>Why, then, did we make this effort to understand the trampoline?
Two reasons.
First, it’s semi-common in programming lore, so it’s best to know about it.
Second, it’s a stepping stone to a more-general, more-powerful technique: <em>continuation-passing-style expressions</em>.
That’s our subject for next time.</p>
<p>In the meantime, if you want another take on trampolines in Python, Kyle Miller wrote a nice article on the subject: <a href="http://web.mit.edu/kmill/www/programming/tailcall.html">Tail call recursion in Python</a>.</p>
<p>Thanks for reading!
As always, if you have questions or comments, please leave a comment on the blog or hit me at <a href="https://twitter.com/tmoertel">@tmoertel</a>.</p>
</div>
]]></summary>
</entry>
<entry>
    <title>Tricks of the trade: Recursion to Iteration, Part 3: Recursive Data Structures</title>
    <link href="http://blog.moertel.com/posts/2013-06-03-recursion-to-iteration-3.html" />
    <id>http://blog.moertel.com/posts/2013-06-03-recursion-to-iteration-3.html</id>
    <published>2013-06-03T00:00:00Z</published>
    <updated>2013-06-03T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-06-03">June  3, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;programming&#39;." href="/tags/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;recursion&#39;." href="/tags/recursion.html" rel="tag">recursion</a>, <a title="All pages tagged &#39;iteration&#39;." href="/tags/iteration.html" rel="tag">iteration</a>, <a title="All pages tagged &#39;python&#39;." href="/tags/python.html" rel="tag">python</a>, <a title="All pages tagged &#39;recursion-to-iteration series&#39;." href="/tags/recursion-to-iteration%20series.html" rel="tag">recursion-to-iteration series</a>, <a title="All pages tagged &#39;tail calls&#39;." href="/tags/tail%20calls.html" rel="tag">tail calls</a>, <a title="All pages tagged &#39;data structures&#39;." href="/tags/data%20structures.html" rel="tag">data structures</a></span></div>

<div itemprop="articleBody">
<p>This is the third article in <a href="http://blog.moertel.com/tags/recursion-to-iteration%20series.html">a series on converting recursive algorithms into iterative algorithms</a>.
If any of what follows seems confusing, you may want to read the earlier articles first.</p>
<p>This is an extra article that I hadn’t planned.
I’m writing it because in a comment on the previous article a reader asked me to show a less mathematical example and suggested tree traversal.
So that’s the subject of this article:
We’ll take a binary tree and flatten it into a list, first recursively, then iteratively.</p>
<h3 id="the-challenge">The challenge</h3>
<p>First, let’s define a binary tree to be either empty or given by a node having three parts: (1) a value, (2) a left subtree, and (3) a right subtree, where both of the subtrees are themselves binary trees.
In Haskell, we might define it like so:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">BinaryTree</span> a <span class="ot">=</span> <span class="dt">Empty</span> <span class="op">|</span> <span class="dt">Node</span> a (<span class="dt">BinaryTree</span> a) (<span class="dt">BinaryTree</span> a)</span></code></pre></div>
<p>In Python, which we’ll use for the rest of this article, we’ll say that <code>None</code> represents an empty tree and that the following class represents a node:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> collections</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>Node <span class="op">=</span> collections.namedtuple(<span class="st">&#39;Node&#39;</span>, <span class="st">&#39;val left right&#39;</span>)</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co"># some sample trees having various node counts</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>tree0 <span class="op">=</span> <span class="va">None</span>  <span class="co"># empty tree</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>tree1 <span class="op">=</span> Node(<span class="dv">5</span>, <span class="va">None</span>, <span class="va">None</span>)</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a>tree2 <span class="op">=</span> Node(<span class="dv">7</span>, tree1, <span class="va">None</span>)</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a>tree3 <span class="op">=</span> Node(<span class="dv">7</span>, tree1, Node(<span class="dv">9</span>, <span class="va">None</span>, <span class="va">None</span>))</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a>tree4 <span class="op">=</span> Node(<span class="dv">2</span>, <span class="va">None</span>, tree3)</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a>tree5 <span class="op">=</span> Node(<span class="dv">2</span>, Node(<span class="dv">1</span>, <span class="va">None</span>, <span class="va">None</span>), tree3)</span></code></pre></div>
<p>Let us now define a function to flatten a tree using an <a href="http://en.wikipedia.org/wiki/Tree_traversal#In-order">in-order traversal</a>.
The recursive definition is absurdly simple, the data type having only two cases to consider:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="co"># empty case</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    <span class="co"># node case</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> flatten(bst.left) <span class="op">+</span> [bst.val] <span class="op">+</span> flatten(bst.right)</span></code></pre></div>
<p>A few tests to check that it does what we expect:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> check_flattener(f):</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree0) <span class="op">==</span> []</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree1) <span class="op">==</span> [<span class="dv">5</span>]</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree2) <span class="op">==</span> [<span class="dv">5</span>, <span class="dv">7</span>]</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree3) <span class="op">==</span> [<span class="dv">5</span>, <span class="dv">7</span>, <span class="dv">9</span>]</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree4) <span class="op">==</span> [<span class="dv">2</span>, <span class="dv">5</span>, <span class="dv">7</span>, <span class="dv">9</span>]</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">assert</span> f(tree5) <span class="op">==</span> [<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">5</span>, <span class="dv">7</span>, <span class="dv">9</span>]</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a>    <span class="bu">print</span> <span class="st">&#39;ok&#39;</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>check_flattener(flatten)  <span class="co"># ok</span></span></code></pre></div>
<p>Our challenge for today is to convert <code>flatten</code> into an iterative version.
Other than a new trick – partial evaluation – the transformation is straightforward, so I’ll move quickly.</p>
<p>Let’s do this!</p>
<h3 id="eliminating-the-first-recursive-call">Eliminating the first recursive call</h3>
<p>First, let’s separate the base case from the incremental work:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst):</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> flatten(bst.left) <span class="op">+</span> [bst.val] <span class="op">+</span> flatten(bst.right)</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(bst)</span></code></pre></div>
<p>And let’s break the incremental work into smaller pieces to see what’s going on.</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst):</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(bst)</span></code></pre></div>
<p>Let’s try to get rid of the first recursive call by assuming that somebody has passed us its result via a secret argument <code>left</code>:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst, left<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> left <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(bst)</span></code></pre></div>
<p>And now we’ll make <code>step</code> return values that parallel its input arguments:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst, left<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> left <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> bst, left  <span class="co"># &lt;-- add bst</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(bst)[<span class="op">-</span><span class="dv">1</span>]  <span class="co"># &lt;-- note [-1]</span></span></code></pre></div>
<p>In the first recursive call, the transformation applied to <code>bst</code> is <code>.left</code>, so we want to apply the opposite transformation to <code>bst</code> in the returned values.
And what’s the opposite of descending to a node’s left subtree?
It’s ascending to the node’s parent.
So we want something like this:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="co"># this code does not work!</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst, left<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> left <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> get_parent(bst), left  <span class="co"># &lt;-- need get_parent</span></span></code></pre></div>
<p>But we’re stuck.
We can’t define <code>get_parent</code> because our tree data structure doesn’t keep track of parents, only children.</p>
<p>New plan:
Maybe we can assume that someone has <em>passed us</em> the node’s parent and go from there?</p>
<p>But this plan hits the same brick wall:
If we add a new argument to accept the parent, we must for parallelism add a new return value to emit the transformed parent, which is the parent of the parent.
But we can’t compute the parent of the parent because, as before, we have no way of implementing <code>get_parent</code>.</p>
<p>So we do what mathematicians do when their assumptions hit a brick wall: we strengthen our assumption!
Now we assume that someone has passed us <em>all of the parents</em>, right up to the tree’s root.
And that assumption gives us what we need:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(bst, parents, left<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> left <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents[<span class="op">-</span><span class="dv">1</span>], parents[:<span class="op">-</span><span class="dv">1</span>], left</span></code></pre></div>
<p>Note that we’re using the Python stack convention for <code>parents</code>; thus the immediate parent of <code>bst</code> is given by the final element <code>parents[-1]</code>.</p>
<p>As a simplification, we can eliminate the <code>bst</code> argument by considering it the final parent pushed onto the stack:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()  <span class="co"># &lt;-- bst = top of parents stack</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> left <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>        left <span class="op">=</span> flatten(bst.left)</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span></code></pre></div>
<p>Now that <code>step</code> requires the <code>parents</code> stack as an argument, the base function must provide it:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> []</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> [bst]</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(parents)[<span class="op">-</span><span class="dv">1</span>]</span></code></pre></div>
<p>But we still haven’t eliminated the first recursive call.
To do that, we’ll need to pass the <code>step</code> function a value for its <code>left</code> argument, which will cause the recursive call to be skipped.</p>
<p>But we only know what that value should be for one case, the base case, when <code>bst</code> is <code>None</code>; then <code>left</code> must be <code>[]</code>.
To get to that case from the tree’s root, where <code>bst</code> is definitely not <code>None</code>, we must iteratively replicate the normal recursive calls on <code>bst.left</code> until we hit the leftmost leaf node.
And then, to compute the desired result, we must reverse the trip, iterating the <code>step</code> function until we have returned to the tree’s root, where the <code>parents</code> stack must be empty:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="co"># find initial conditions for secret-feature &quot;left&quot;</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> []</span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> []</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>        parents.append(bst)</span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> bst.left</span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a>    <span class="co"># iterate to compute the result</span></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents:</span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>        parents, left <span class="op">=</span> step(parents, left)</span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span></code></pre></div>
<p>And just like that, one of the recursive calls has been transformed into iteration.
We’re halfway to the finish line!</p>
<h3 id="eliminating-the-second-recursive-call">Eliminating the second recursive call</h3>
<p>But we still have to eliminate that final recursive call to <code>flatten</code>, now sequestered in <code>step</code>.
Let’s take a closer look at that function after we make its <code>left</code> argument required since it always gets called with a value now:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    right <span class="op">=</span> flatten(bst.right)</span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span></code></pre></div>
<p>To get rid of the recursive call to <code>flatten</code>, we’re going to use a new trick: partial evaluation.
Basically, we’re going to replace the call to <code>flatten</code> with the function body of <code>flatten</code>, after we rename all its variables to prevent conflicts.
So let’s make a copy of <code>flatten</code> and suffix all its variables with <code>1</code>:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten1(bst1):</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    left1 <span class="op">=</span> []</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents1:</span>
<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>        parents1, left1 <span class="op">=</span> step(parents1, left1)</span>
<span id="cb15-9"><a href="#cb15-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left1</span></code></pre></div>
<p>And then let’s make its arguments and return values explicit:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> ARGUMENTS</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    left1 <span class="op">=</span> []</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents1:</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        parents1, left1 <span class="op">=</span> step(parents1, left1)</span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    RETURNS <span class="op">=</span> (left1, )</span></code></pre></div>
<p>And then we’ll drop this expansion into <code>step</code>:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- begin partial evaluation --</span></span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> (bst.right, )</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a>    left1 <span class="op">=</span> []</span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb17-11"><a href="#cb17-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents1:</span>
<span id="cb17-12"><a href="#cb17-12" aria-hidden="true" tabindex="-1"></a>        parents1, left1 <span class="op">=</span> step(parents1, left1)</span>
<span id="cb17-13"><a href="#cb17-13" aria-hidden="true" tabindex="-1"></a>    (right, ) <span class="op">=</span> (left1, )</span>
<span id="cb17-14"><a href="#cb17-14" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- end partial evaluation --</span></span>
<span id="cb17-15"><a href="#cb17-15" aria-hidden="true" tabindex="-1"></a>    left.extend(right)</span>
<span id="cb17-16"><a href="#cb17-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span></code></pre></div>
<p>Now we can eliminate code by fusion across the partial-evaluation boundary.</p>
<p>First up: <code>left1</code>.
We can now see that this variable accumulates values that, in the end, get appended to <code>left</code> (via the return variable <code>right</code>).
But we can just as well append those values to <code>left</code> directly, eliminating <code>left1</code> within the boundary and the call to <code>left.extend(right)</code> without:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- begin partial evaluation --</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> (bst.right, )</span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>    <span class="co"># left1 = []  # &lt;-- eliminate and use left instead</span></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb18-11"><a href="#cb18-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents1:</span>
<span id="cb18-12"><a href="#cb18-12" aria-hidden="true" tabindex="-1"></a>        parents1, left <span class="op">=</span> step(parents1, left)</span>
<span id="cb18-13"><a href="#cb18-13" aria-hidden="true" tabindex="-1"></a>    <span class="co"># (right, ) = (left, )  # &lt;-- eliminated</span></span>
<span id="cb18-14"><a href="#cb18-14" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- end partial evaluation --</span></span>
<span id="cb18-15"><a href="#cb18-15" aria-hidden="true" tabindex="-1"></a>    <span class="co"># left.extend(right)  # &lt;-- eliminated</span></span>
<span id="cb18-16"><a href="#cb18-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span></code></pre></div>
<p>For this next fusion, we’re going to need to recall our base function to get the necessary outside scope:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- begin partial evaluation --</span></span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> (bst.right, )</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents1:</span>
<span id="cb19-11"><a href="#cb19-11" aria-hidden="true" tabindex="-1"></a>        parents1, left <span class="op">=</span> step(parents1, left)</span>
<span id="cb19-12"><a href="#cb19-12" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- end partial evaluation --</span></span>
<span id="cb19-13"><a href="#cb19-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span>
<span id="cb19-14"><a href="#cb19-14" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-15"><a href="#cb19-15" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb19-16"><a href="#cb19-16" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> []</span>
<span id="cb19-17"><a href="#cb19-17" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> []</span>
<span id="cb19-18"><a href="#cb19-18" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb19-19"><a href="#cb19-19" aria-hidden="true" tabindex="-1"></a>        parents.append(bst)</span>
<span id="cb19-20"><a href="#cb19-20" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> bst.left</span>
<span id="cb19-21"><a href="#cb19-21" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents:</span>
<span id="cb19-22"><a href="#cb19-22" aria-hidden="true" tabindex="-1"></a>        parents, left <span class="op">=</span> step(parents, left)</span>
<span id="cb19-23"><a href="#cb19-23" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span></code></pre></div>
<p>When <code>flatten</code> calls <code>step</code> and the code within the partially evaluated region executes, it builds up a stack of nodes <code>parents1</code> and then calls <code>step</code> iteratively to pop values off of that stack and process them.
When it’s finished, control returns to <code>step</code> proper, which then returns to its caller, <code>flatten</code>, with the values (<code>parents</code>, <code>left</code>).
But look at what <code>flatten</code> then does with <code>parents</code>: it calls <code>step</code> iteratively to pop values off of that stack and process them in exactly the same way.</p>
<p>So we can eliminate the <code>while</code> loop in <code>step</code> – and the recursive call! – by returning not <code>parents</code> but <code>parents + parents1</code>, which will make the <code>while</code> loop in <code>flatten</code> do the exact same work.</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- begin partial evaluation --</span></span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> (bst.right, )</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a>    parents1 <span class="op">=</span> []</span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>        parents1.append(bst1)</span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>    <span class="co"># while parents1:                            # &lt;-- eliminated</span></span>
<span id="cb20-11"><a href="#cb20-11" aria-hidden="true" tabindex="-1"></a>    <span class="co">#     parents1, left = step(parents1, left)  #</span></span>
<span id="cb20-12"><a href="#cb20-12" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- end partial evaluation --</span></span>
<span id="cb20-13"><a href="#cb20-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents <span class="op">+</span> parents1, left  <span class="co"># parents -&gt; parents + parents1</span></span></code></pre></div>
<p>And then we can eliminate <code>parents1</code> completely by taking the values we would have appended to it and appending them directly to <code>parents</code>:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- begin partial evaluation --</span></span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    (bst1, ) <span class="op">=</span> (bst.right, )</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>    <span class="co"># parents1 = []  # &lt;-- eliminated</span></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>        parents.append(bst1)  <span class="co"># parents1 -&gt; parents</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>    <span class="co"># -- end partial evaluation --</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left  <span class="co"># parents + parents1 -&gt; parents</span></span></code></pre></div>
<p>And now, once we remove our partial-evaluation scaffolding, our <code>step</code> function is looking simple again:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(parents, left):</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    bst <span class="op">=</span> parents.pop()</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>    left.append(bst.val)</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    bst1 <span class="op">=</span> bst.right</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a>        parents.append(bst1)</span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst1.left</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> parents, left</span></code></pre></div>
<p>For the final leg of our journey – simplification – let’s inline the <code>step</code> logic back into the base function:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> []</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> []</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>        parents.append(bst)</span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> bst.left</span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents:</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>        parents, left <span class="op">=</span> parents, left</span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> parents.pop()</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>        left.append(bst.val)</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst.right</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb23-13"><a href="#cb23-13" aria-hidden="true" tabindex="-1"></a>            parents.append(bst1)</span>
<span id="cb23-14"><a href="#cb23-14" aria-hidden="true" tabindex="-1"></a>            bst1 <span class="op">=</span> bst1.left</span>
<span id="cb23-15"><a href="#cb23-15" aria-hidden="true" tabindex="-1"></a>        parents, left <span class="op">=</span> parents, left</span>
<span id="cb23-16"><a href="#cb23-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span></code></pre></div>
<p>Let’s eliminate the trivial argument-binding and return-value assignments:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> []</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> []</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> bst <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>        parents.append(bst)</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> bst.left</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents:</span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a>        <span class="co"># parents, left = parents, left  # = no-op</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> parents.pop()</span>
<span id="cb24-10"><a href="#cb24-10" aria-hidden="true" tabindex="-1"></a>        left.append(bst.val)</span>
<span id="cb24-11"><a href="#cb24-11" aria-hidden="true" tabindex="-1"></a>        bst1 <span class="op">=</span> bst.right</span>
<span id="cb24-12"><a href="#cb24-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> bst1 <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb24-13"><a href="#cb24-13" aria-hidden="true" tabindex="-1"></a>            parents.append(bst1)</span>
<span id="cb24-14"><a href="#cb24-14" aria-hidden="true" tabindex="-1"></a>            bst1 <span class="op">=</span> bst1.left</span>
<span id="cb24-15"><a href="#cb24-15" aria-hidden="true" tabindex="-1"></a>        <span class="co"># parents, left = parents, left  # = no-op</span></span>
<span id="cb24-16"><a href="#cb24-16" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span></code></pre></div>
<p>And, finally, factor out the duplicated <code>while</code> loop into a local function:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> flatten(bst):</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>    left <span class="op">=</span> []</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    parents <span class="op">=</span> []</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>    <span class="kw">def</span> descend_left(bst):</span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">while</span> bst <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>            parents.append(bst)</span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>            bst <span class="op">=</span> bst.left</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>    descend_left(bst)</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> parents:</span>
<span id="cb25-10"><a href="#cb25-10" aria-hidden="true" tabindex="-1"></a>        bst <span class="op">=</span> parents.pop()</span>
<span id="cb25-11"><a href="#cb25-11" aria-hidden="true" tabindex="-1"></a>        left.append(bst.val)</span>
<span id="cb25-12"><a href="#cb25-12" aria-hidden="true" tabindex="-1"></a>        descend_left(bst.right)</span>
<span id="cb25-13"><a href="#cb25-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> left</span></code></pre></div>
<p>And that’s it!
We now have a tight, efficient, and iterative version of our original function.
Further, the code is close to idiomatic.</p>
<p>That’s it for this time.
If you have any questions or comments, just hit me at <a href="https://twitter.com/tmoertel">@tmoertel</a> or use the comment form below.</p>
<p>Thanks for reading!</p>
</div>
]]></summary>
</entry>
<entry>
    <title>Lazy merging in Python using streams</title>
    <link href="http://blog.moertel.com/posts/2013-05-26-python-lazy-merge.html" />
    <id>http://blog.moertel.com/posts/2013-05-26-python-lazy-merge.html</id>
    <published>2013-05-26T00:00:00Z</published>
    <updated>2013-05-26T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-05-26">May 26, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;programming&#39;." href="/tags/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;python&#39;." href="/tags/python.html" rel="tag">python</a>, <a title="All pages tagged &#39;iterators&#39;." href="/tags/iterators.html" rel="tag">iterators</a>, <a title="All pages tagged &#39;streams&#39;." href="/tags/streams.html" rel="tag">streams</a>, <a title="All pages tagged &#39;SICP&#39;." href="/tags/SICP.html" rel="tag">SICP</a>, <a title="All pages tagged &#39;functional programming&#39;." href="/tags/functional%20programming.html" rel="tag">functional programming</a></span></div>

<div itemprop="articleBody">
<p>Recently while solving a programming puzzle in Python, I needed to merge a series of <em>N</em> iterators, each yielding values in sorted order, into a single iterator over the sorted values.
The trick is that, when asked for a value from the merged series, you must extract all <em>N</em> iterators’ next values to determine which is the smallest.
And then, of course, you can emit only that one value.
So what do you do with the remaining <em>N</em> – 1 values you’ve extracted?</p>
<p>Instead of trying to find some place to store them, perhaps it would be better to avoid the problem altogether by not extracting more values than we are prepared to emit.
This we can do by converting the iterators into an equivalent form in which the next value is always exposed and hence available for making decisions <em>before</em> extraction.
This form is basically the <a href="http://mitpress.mit.edu/sicp/full-text/sicp/book/node69.html"><em>stream</em>
of SICP fame</a>.</p>
<p>The idea is to convert each <a href="http://www.python.org/dev/peps/pep-0234/">Python iterator</a> into either <code>None</code> (representing an empty stream) or a pair containing the iterator’s next value and the iterator itself:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> iterator_to_stream(iterator):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Convert an iterator into a stream (None if the iterator is empty).&quot;&quot;&quot;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">try</span>:</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> iterator.<span class="bu">next</span>(), iterator</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">except</span> <span class="pp">StopIteration</span>:</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="va">None</span></span></code></pre></div>
<p>Then to extract values from the stream, you just apply <code>stream_next</code> to it, and it will hand you back the next value and the updated state of the stream:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> stream_next(stream):</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Get (next_value, next_stream) from a stream.&quot;&quot;&quot;</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>    val, iterator <span class="op">=</span> stream</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> val, iterator_to_stream(iterator)</span></code></pre></div>
<p>Since streams expose their next value, they can be ordered by that value.
And for my task that was the property that made all the difference:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> heapq</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> merge(iterators):</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Make a lazy sorted iterator that merges lazy sorted iterators.&quot;&quot;&quot;</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>    streams <span class="op">=</span> <span class="bu">map</span>(iterator_to_stream, <span class="bu">map</span>(<span class="bu">iter</span>, iterators))</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>    heapq.heapify(streams)</span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> streams:</span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a>        stream <span class="op">=</span> heapq.heappop(streams)</span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> stream <span class="kw">is</span> <span class="kw">not</span> <span class="va">None</span>:</span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true" tabindex="-1"></a>            val, stream <span class="op">=</span> stream_next(stream)</span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true" tabindex="-1"></a>            heapq.heappush(streams, stream)</span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true" tabindex="-1"></a>            <span class="cf">yield</span> val</span></code></pre></div>
<p>An example use:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> xs <span class="op">=</span> merge([<span class="bu">xrange</span>(<span class="dv">3</span>), <span class="bu">xrange</span>(<span class="dv">2</span>, <span class="dv">9</span>), <span class="bu">xrange</span>(<span class="dv">5</span>)])</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> xs</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;</span>generator <span class="bu">object</span> merge at <span class="bn">0x7fea07c9d320</span><span class="op">&gt;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">list</span>(xs)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>[<span class="dv">0</span>, <span class="dv">0</span>, <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">2</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">3</span>, <span class="dv">4</span>, <span class="dv">4</span>, <span class="dv">5</span>, <span class="dv">6</span>, <span class="dv">7</span>, <span class="dv">8</span>]</span></code></pre></div>
</div>
]]></summary>
</entry>
<entry>
    <title>Tricks of the trade: Recursion to Iteration, Part 2: Eliminating Recursion with the Time-Traveling Secret Feature Trick</title>
    <link href="http://blog.moertel.com/posts/2013-05-14-recursive-to-iterative-2.html" />
    <id>http://blog.moertel.com/posts/2013-05-14-recursive-to-iterative-2.html</id>
    <published>2013-05-14T00:00:00Z</published>
    <updated>2013-05-14T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-05-14">May 14, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;programming&#39;." href="/tags/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;recursion&#39;." href="/tags/recursion.html" rel="tag">recursion</a>, <a title="All pages tagged &#39;iteration&#39;." href="/tags/iteration.html" rel="tag">iteration</a>, <a title="All pages tagged &#39;python&#39;." href="/tags/python.html" rel="tag">python</a>, <a title="All pages tagged &#39;google code jam&#39;." href="/tags/google%20code%20jam.html" rel="tag">google code jam</a>, <a title="All pages tagged &#39;puzzles&#39;." href="/tags/puzzles.html" rel="tag">puzzles</a>, <a title="All pages tagged &#39;recursion-to-iteration series&#39;." href="/tags/recursion-to-iteration%20series.html" rel="tag">recursion-to-iteration series</a>, <a title="All pages tagged &#39;tail calls&#39;." href="/tags/tail%20calls.html" rel="tag">tail calls</a></span></div>

<div itemprop="articleBody">
<p>This is the second post in <a href="http://blog.moertel.com/tags/recursion-to-iteration%20series.html">a series on converting recursive algorithms into iterative algorithms</a>.
If you haven’t read the <a href="http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html">previous post</a>, you probably should.
It introduces some terms and background that will be helpful.</p>
<p>Last time, if you’ll recall, we discussed The Simple Method of converting recursive functions into iterative functions.
The method, as its name implies, is straightforward and mostly mechanical.
The only potential trouble is that, for the method to work, you must convert all of the recursive calls in your function into tail calls.</p>
<p>This task can be tricky.
So we also discussed the <em>Secret Feature</em> trick for putting recursive calls into tail-call form.
That trick works well for simple recursive calls, but when your calls aren’t so simple, you need a beefier version of the trick.</p>
<p>That’s the subject of this post: the <em>Time-Traveling Secret Feature</em> trick.
<strong>It’s like sending a <a href="http://en.wikipedia.org/wiki/Terminator_(character)">T-800</a> back in time to terminate a function’s recursiveness before it can ever offer resistance in the present.</strong></p>
<p>Yeah.</p>
<p>But we’ll have to work up to it.
So stick with the early examples to prepare for the cybernetic brain augmentations to come.</p>
<p>Enough talk!
Let’s start with a practical example.</p>
<p><strong>Update 2013-06-17:</strong> <em>If you want another example, here’s also <a href="https://gist.github.com/tmoertel/5798134">a step-by-step conversion of the Fibonacci function</a>.</em></p>
<h3 id="computing-binomial-coefficients">Computing binomial coefficients</h3>
<p>The <a href="http://en.wikipedia.org/wiki/Binomial_coefficient">binomial coefficient</a> <span class="math inline">\(\binom{n}{k}\)</span> for integers <span class="math inline">\(n\)</span> and <span class="math inline">\(k\)</span> gives the number of ways to choose <span class="math inline">\(k\)</span> items from a set of <span class="math inline">\(n\)</span> items.
For this reason, it’s often pronounced “<span class="math inline">\(n\)</span> choose <span class="math inline">\(k\)</span>.”
It’s very common in <a href="http://en.wikipedia.org/wiki/Binomial_coefficient#Combinatorics_and_statistics">combinatorics and statistics</a> and often pops up in the analysis of algorithms.
A whole chapter, in fact, is dedicated to them in Graham, Knuth, and Patashnik’s <a href="http://en.wikipedia.org/wiki/Concrete_Mathematics"><em>Concrete Mathematics</em></a>.</p>
<p>Math textbooks define the coefficient like this:
<span class="math display">\[\binom{n}{k} = \frac{n!}{k!(n-k)!},\]</span>
but that form <a href="http://blogs.msdn.com/b/oldnewthing/archive/2013/05/08/10416823.aspx">causes all sorts of problems for computers</a>.
Fortunately, <em>Concrete Mathematics</em> helpfully points out a lifesaving absorption identity:
<span class="math display">\[\binom{n}{k} = \frac{n}{k}\binom{n - 1}{k - 1},\]</span>
and we know what that is, don’t we?
That’s a recursive function just waiting to happen!</p>
<p>And that identity, along with the base case <span class="math inline">\(\binom{n}{0} = 1\)</span>, gives us today’s running example:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k</span></code></pre></div>
<p>Before going further, a cautionary point.
Math math and computer math are not the same.
In math math, <span class="math inline">\(\frac{nx}{k} = \frac{n}{k}x = \frac{x}{k}n\)</span>, but in computer math the equation does not necessarily hold because of finite precision or, in our case, because we’re dealing with integer division that throws away remainders.
(By the way, in Python, <code>//</code> is the division operator that throws away remainders.)
For this reason, I have been careful to use the form</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k</span></code></pre></div>
<p>instead of the more literal translation</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>(n <span class="op">//</span> k) <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>which, if you try it, you’ll see often produces the wrong answer.</p>
<p>Okay, our challenge is set before us.
Ready to de-recursivify <code>binomial</code>?</p>
<h3 id="once-again-the-secret-feature-trick">Once again, the Secret Feature trick</h3>
<p>First, however, we must put the function’s recursive call into tail-call form.
And you remember how to do that, right?
With the Secret Feature trick, of course!
As a refresher from last time, here’s the trick in a nutshell:</p>
<ol type="1">
<li>Find a recursive call that’s not a tail call.</li>
<li>Identify what work is being done between that call and its <code>return</code> statement.</li>
<li>Extend the function with a secret feature to do that work, as controlled by a new accumulator argument with a default value that causes it to do nothing.</li>
<li>Use the secret feature to eliminate the old work.</li>
<li>You’ve now got a tail call!</li>
<li>Repeat until all recursive calls are tail calls.</li>
</ol>
<p>Let’s go through it, by the numbers.</p>
<ol type="1">
<li><p><em>Find a recursive call that’s not a tail call.</em></p>
<p>Well, there’s only three lines of logic.
We’re not talking rocket science here.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>    <span class="co">#          ^^^^^^^^^^^^^^^^^^^^^^</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>    <span class="co">#               right here!</span></span></code></pre></div></li>
<li><p><em>Identify what work is being done between that call and its <code>return</code> statement.</em></p>
<p>In our mind’s eye, let’s lift the recursive call out of the <code>return</code> statement and replace it with the variable <code>x</code>.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> x <span class="op">//</span> k</span></code></pre></div>
<p>Now we can visualize the additional work as a separate function operating on <code>x</code>: multiplying it on the left by one number and dividing it on the right by another:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> work(x, lmul, rdiv):</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lmul <span class="op">*</span> x <span class="op">//</span> rdiv</span></code></pre></div>
<p>For functions this simple, you can just hold them in your head and inline them into your code as needed.
But for more-complicated functions, it really does help to break them out like this.
For this example, I’m going to pretend that our work function is more complicated, just to show how to do it.</p></li>
<li><p><em>Extend the function with a secret feature to do that work,</em> as controlled by a new accumulator argument – in this case a pair (<code>lmul</code>, <code>rdiv</code>) – with a default value that causes it to do nothing.</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> work(x, lmul, rdiv):</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lmul <span class="op">*</span> x <span class="op">//</span> rdiv</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k, lmul<span class="op">=</span><span class="dv">1</span>, rdiv<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> work(<span class="dv">1</span>, lmul, rdiv)</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> work(n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k, lmul, rdiv)</span></code></pre></div>
<p>Note that I just mechanically converted <em>all</em> <code>return {whatever}</code> statements into <code>return work({whatever}, lmul, rdiv)</code>.</p></li>
<li><p><em>Use the secret feature to eliminate the old work.</em></p>
<p>Watch what happens to that final line.</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> work(x, lmul, rdiv):</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lmul <span class="op">*</span> x <span class="op">//</span> rdiv</span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k, lmul<span class="op">=</span><span class="dv">1</span>, rdiv<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> work(<span class="dv">1</span>, lmul, rdiv)</span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>, lmul <span class="op">*</span> n, k <span class="op">*</span> rdiv)</span></code></pre></div></li>
<li><p><em>You’ve now got a tail call!</em></p>
<p>Indeed, we do!
All that’s left is to inline the sole remaining <code>work</code> call:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k, lmul<span class="op">=</span><span class="dv">1</span>, rdiv<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lmul <span class="op">*</span> <span class="dv">1</span> <span class="op">//</span> rdiv</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>, lmul <span class="op">*</span> n, k <span class="op">*</span> rdiv)</span></code></pre></div>
<p>And to simplify away the needless multiplication by <code>1</code> in the <code>return</code> statement:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k, lmul<span class="op">=</span><span class="dv">1</span>, rdiv<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> lmul <span class="op">//</span> rdiv</span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>, lmul <span class="op">*</span> n, k <span class="op">*</span> rdiv)</span></code></pre></div></li>
<li><p><em>Repeat until all recursive calls are tail calls.</em></p>
<p>There was only one, so we’re done! Yay!</p></li>
</ol>
<p>With all the recursive calls (just the one) converted into tail calls, we can easily convert the function into iterative form by applying the Simple Method.
Here’s what we get after we load the function body into a one-shot loop and convert the tail call into an assignment-and-<code>continue</code> pair.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial_iter(n, k, lmul<span class="op">=</span><span class="dv">1</span>, rdiv<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="va">True</span>:</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> lmul <span class="op">//</span> rdiv</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>        (n, k, lmul, rdiv) <span class="op">=</span> (n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>, lmul <span class="op">*</span> n, k <span class="op">*</span> rdiv)</span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">continue</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">break</span></span></code></pre></div>
<p>As a final touch, we can tidy up and in the process tuck the accumulators inside the function body to keep them completely secret:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial_iter(n, k):</span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a>    lmul <span class="op">=</span> rdiv <span class="op">=</span> <span class="dv">1</span></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> k <span class="op">&gt;</span> <span class="dv">0</span>:</span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a>        (n, k, lmul, rdiv) <span class="op">=</span> (n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>, lmul <span class="op">*</span> n, k <span class="op">*</span> rdiv)</span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lmul <span class="op">//</span> rdiv</span></code></pre></div>
<p>And now we have an iterative version of our original <code>binomial</code> function!</p>
<h3 id="a-short-cautionary-lesson">A short, cautionary lesson</h3>
<p>This next part is subtle but important.
To understand what’s going on, you first need to see it.
So, once again, let’s use the Online Python Tutor’s excellent Python-runtime visualizer.
Open the link below in a new tab if you can, and then read on.</p>
<p><a href="http://www.pythontutor.com/visualize.html#code=def+binomial(n,+k)%3A%0A++++%22%22%22Compute+binomial+coefficient+C(n,+k)+%3D+n!+/+(k!+*+(n-k)!).%22%22%22%0A++++if+k+%3D%3D+0%3A%0A++++++++return+1%0A++++return+n+*+binomial(n+-+1,+k+-+1)+//+k%0A%0Adef+binomial_iter(n,+k)%3A%0A++++%22%22%22Compute+binomial+coefficient+C(n,+k)+%3D+n!+/+(k!+*+(n-k)!).%22%22%22%0A++++lmul+%3D+rdiv+%3D+1%0A++++while+k+%3E+0%3A%0A++++++++(n,+k,+lmul,+rdiv)+%3D+(n+-+1,+k+-+1,+lmul+*+n,+k+*+rdiv)%0A++++return+lmul+//+rdiv%0A%0Aprint+binomial(39,+9)%0Aprint+binomial_iter(39,+9)&amp;mode=display&amp;cumulative=false&amp;heapPrimitives=false&amp;drawParentPointers=false&amp;textReferences=false&amp;showOnlyOutputs=false&amp;py=2&amp;curInstr=0">Visualize the execution of <code>binomial(39, 9)</code>.</a></p>
<p>Click the Forward button to advance through each step of the computation.
When you get to step 22, where the recursive version has fully loaded the stack with its nested frames, click slowly.
Watch the return value (in red) carefully as you advance.
See how it gently climbs to the final answer of 211915132, never exceeding that value?</p>
<p>Now continue stepping through to the iterative version.
Watch the value of <code>lmul</code> as you advance.
See how it grows rapidly, finally reaching a whopping 76899763100160?</p>
<p>This difference matters.
While both versions computed the correct answer, the original recursive version would do so without exceeding the capacity of 32-bit signed integers.<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>
The iterative version, however, needs a comparatively hoggish 47 bits to faithfully arrive at the correct answer.</p>
<p>Python’s integers, lucky for us, grow as needed to hold their values, so we need not fear overflow in this case, but not all languages for which we might want to use our recursion-to-iteration techniques offer such protections.
It’s something to keep in mind the next time you’re taking the recursion out of an algorithm in C:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">typedef</span> <span class="dt">int32_t</span> Int<span class="op">;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>Int binomial<span class="op">(</span>Int n<span class="op">,</span> Int k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>k <span class="op">==</span> <span class="dv">0</span><span class="op">)</span></span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> binomial<span class="op">(</span>n <span class="op">-</span> <span class="dv">1</span><span class="op">,</span> k <span class="op">-</span> <span class="dv">1</span><span class="op">)</span> <span class="op">/</span> k<span class="op">;</span></span>
<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-9"><a href="#cb13-9" aria-hidden="true" tabindex="-1"></a>Int binomial_iter<span class="op">(</span>Int n<span class="op">,</span> Int k<span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-10"><a href="#cb13-10" aria-hidden="true" tabindex="-1"></a>    Int lmul <span class="op">=</span> <span class="dv">1</span><span class="op">,</span> rdiv <span class="op">=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb13-11"><a href="#cb13-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="op">(</span>k <span class="op">&gt;</span> <span class="dv">0</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a>        lmul <span class="op">*=</span> n<span class="op">;</span> rdiv <span class="op">*=</span> k<span class="op">;</span> n <span class="op">-=</span> <span class="dv">1</span><span class="op">;</span> k <span class="op">-=</span> <span class="dv">1</span><span class="op">;</span></span>
<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb13-14"><a href="#cb13-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> lmul <span class="op">/</span> rdiv<span class="op">;</span></span>
<span id="cb13-15"><a href="#cb13-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-16"><a href="#cb13-16" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-17"><a href="#cb13-17" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(</span><span class="dt">int</span> argc<span class="op">,</span> <span class="dt">char</span><span class="op">*</span> argv<span class="op">[])</span> <span class="op">{</span></span>
<span id="cb13-18"><a href="#cb13-18" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;binomial(39, 9)      = </span><span class="sc">%ld\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="op">(</span><span class="dt">long</span><span class="op">)</span> binomial<span class="op">(</span><span class="dv">39</span><span class="op">,</span> <span class="dv">9</span><span class="op">));</span></span>
<span id="cb13-19"><a href="#cb13-19" aria-hidden="true" tabindex="-1"></a>    printf<span class="op">(</span><span class="st">&quot;binomial_iter(39, 9) = </span><span class="sc">%ld\n</span><span class="st">&quot;</span><span class="op">,</span> <span class="op">(</span><span class="dt">long</span><span class="op">)</span> binomial_iter<span class="op">(</span><span class="dv">39</span><span class="op">,</span> <span class="dv">9</span><span class="op">));</span></span>
<span id="cb13-20"><a href="#cb13-20" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
<span id="cb13-21"><a href="#cb13-21" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-22"><a href="#cb13-22" aria-hidden="true" tabindex="-1"></a><span class="co">/* Output with Int = int32_t:</span></span>
<span id="cb13-23"><a href="#cb13-23" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-24"><a href="#cb13-24" aria-hidden="true" tabindex="-1"></a><span class="co">binomial(39, 9)      = 211915132</span></span>
<span id="cb13-25"><a href="#cb13-25" aria-hidden="true" tabindex="-1"></a><span class="co">binomial_iter(39, 9) = -4481      &lt;-- oops!</span></span>
<span id="cb13-26"><a href="#cb13-26" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-27"><a href="#cb13-27" aria-hidden="true" tabindex="-1"></a><span class="co">*/</span></span></code></pre></div>
<p>In any case, bigger integers are slower and consume more memory.
In one important way, the original, recursive algorithm was better.
We have lost something important.</p>
<p><em>Now let’s get it back.</em></p>
<h3 id="the-importance-of-respecting-associativity-and-commutativity">The importance of respecting associativity and commutativity</h3>
<p>It turns out that our iterative version of <code>binomial</code> is the original’s evil twin.
Its stack usage looks charming and all, but something else about it is off.
Something hard to put our finger on.
What <em>is</em> the difference?</p>
<p>It all comes down to grouping and ordering decisions.
<em>Implicit</em> grouping and ordering decisions that we overlooked during our code transformations.</p>
<p>Consider how both versions compute <span class="math inline">\(\binom{5}{2}\)</span>.</p>
<p>First, the recursive version.
We start out with <span class="math inline">\(n=5, k=2\)</span> and then recursively expand the expression
<span class="math display">\[n\binom{n-1}{k-1}/k\]</span>
until we hit the base case of <span class="math inline">\(k=0\)</span>.
The series of expansions proceeds like so:</p>
<p><span class="math display">\[\binom{5}{2}
= 5{\binom{4}{1}} / 2
= 5\cdot\left(4\binom{3}{0} / 1\right) / 2
= 5\cdot(4\cdot(1)/1)/2
= 10.\]</span></p>
<p>At every step (except for the base case) we perform a multiplication by <span class="math inline">\(n\)</span> and then a division by <span class="math inline">\(k\)</span>.
It’s that division by <span class="math inline">\(k\)</span> that keeps intermediate results from getting out of hand.</p>
<p>Now lets look at the iterative version.
It’s not so obvious what’s going on.
(Score another point for recursion over iteration!)
But we can puzzle it out.
We start out with both accumulators at <span class="math inline">\(1\)</span> and then loop over the decreasing values of <span class="math inline">\(k\)</span>, building up the accumulators until <span class="math inline">\(k=0\)</span>, at which point we return the quotient of the accumulators.</p>
<p>So the calculation is given by</p>
<p><span class="math display">\[\binom{5}{2}
= \frac{\mathit{lmul}}{\mathit{rdiv}}
= \frac{((1)\cdot 5)\cdot 4}{((1)\cdot 2)\cdot 1}
= 10.\]</span></p>
<p>Both the numerator and denominator grow and grow and grow until the final division.
Not a good trend.</p>
<p>So why did the Secret Feature trick work great for <code>factorial</code> in our previous article but fail us, albeit subtly, now?
The answer is that in <code>factorial</code> the extra work being done between each recursive call and its <code>return</code> statement was multiplication and nothing more.
And multiplication (of integers that don’t overflow) is commutative and associative.
Meaning, ordering and grouping don’t matter.</p>
<p>The lesson, then, is this:
<strong>Think carefully about whether ordering and grouping matter</strong> before using the Secret Feature trick.
If it matters, you have two options:
One, you can modify your algorithm so that ordering and grouping don’t matter and <em>then</em> use the Secret Feature trick.
(But this option is often intractable.)
Two, you can use the <em>Time-Traveling Secret Feature</em> trick, which preserves ordering and grouping.
And <em>that</em> trick is what we’ve been waiting for.</p>
<p>It’s time.</p>
<h3 id="the-time-traveling-secret-feature-trick">The Time-Traveling Secret Feature trick</h3>
<p>What’s about to happen next is so mind-bendingly awesome that you should probably get a drink to prepare yourself.
It’s like combining a T-800 from <em>The Terminator</em>, with the dreams-within-dreams layering from <em>Inception</em>, with the momentary inversion of reality that occurs when the quantum field surrounding an inductive proof collapses and everything snaps into place.</p>
<p>It’s. Really. Cool.</p>
<p>Got your drink?
Okay, let’s do this.</p>
<p>Let’s go back to our original, recursive <code>binomial</code> function:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k</span></code></pre></div>
<p>Our goal is to create an equivalent iterative version that <em>exactly</em> preserves the properties of the original.
Well, how the hell are we going to do that?</p>
<p>Hold that thought for a sec.</p>
<p>Let’s just stop for a moment and think about what that recursive function is doing.
We call it to compute some answer <span class="math inline">\(x_t\)</span>.
But that answer depends on some <em>earlier</em> answer <span class="math inline">\(x_{t-1}\)</span> that the function doesn’t know, so it calls itself to get that answer.
And so on.
Until, finally, it finds one concrete answer <span class="math inline">\(x_0\)</span> that it actually knows and, from which, it can build every subsequent answer.</p>
<p>So, in truth, our answer <span class="math inline">\(x_t\)</span> is just the final element in a whole timeline of needed earlier answers:</p>
<p><span class="math display">\[x_0, x_1, \ldots x_t.\]</span></p>
<p>Well, so what?
Why should we care?</p>
<p>Because we’ve watched <a href="http://www.imdb.com/title/tt0088247/"><em>The Terminator</em></a> about six hundred times!
We <em>know</em> how to get rid of a problem in the present when we’ve seen its timeline:
<em>We send a Terminator into the past to rewrite that timeline so the problem never gets created in the first place.</em></p>
<p>And our little recursive problem with <code>binomial</code> here?
<em>We’ve seen its timeline.</em></p>
<p>That’s right.
It’s about to get real.</p>
<p>One more thing.
<em>Every single one of these steps preserves the original function’s behavior.</em>
You can run your unit tests after every step, and they should all pass.</p>
<p>Let’s begin.</p>
<ol>
<li><p><strong>Send a T-800 terminator unit into the function’s timeline, back to the time of <span class="math inline">\(x_0\)</span>.</strong></p>
<p>Oh, we don’t have a T-800 terminator unit?
No problem.
<em>Assume</em> we’ve sent a T-800 terminator unit into the function’s timeline, back to the time of <span class="math inline">\(x_0\)</span>.</p>
<p>That was easy. What’s next?</p></li>
<li><p><strong>Move the recursive call and surrounding work into a helper function.</strong></p>
<p>This might seem like overkill but prevents mistakes.
Do you make mistakes?
Then just make the helper function already.
I’m calling it <code>step</code> for reasons that will shortly become obvious.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k):</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>) <span class="op">//</span> k</span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)</span></code></pre></div></li>
<li><p><strong>Partition the helper function into its 3 fundamental parts.</strong></p>
<p>They are:</p>
<ol type="1">
<li>the recursive call to get the previous answer <span class="math inline">\(x_{i-1}\)</span>,</li>
<li>the work to compute the current answer <span class="math inline">\(x_i\)</span> from <span class="math inline">\(x_{i-1}\)</span>, and</li>
<li>a <code>return</code> statement applied to <span class="math inline">\(x_i\)</span> alone:</li>
</ol>
<div class="sourceCode" id="cb16"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k):</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>    previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)  <span class="co"># part (1)</span></span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k              <span class="co"># part (2)</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x                             <span class="co"># part (3)</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)</span></code></pre></div></li>
<li><p><strong>Secretly prepare to receive communications from the T-800 terminator unit.</strong></p>
<p>You see, once the T-800 gets its cybernetic hands on earlier values in the timeline, we can use its knowledge to eliminate the recursion.
We just need some way to get that knowledge from the T-800, now stuck in the past, to us, stuck in the present.</p>
<p>Fortunately, we’ve seen time-travel movies, so we know exactly how this problem is solved.
We’ll just use a <a href="https://en.wikipedia.org/wiki/Dead_drop">dead drop</a>!
That’s a prearranged secret location where the T-800 will drop values in the past and where we will check for them in the future.</p>
<p>So, per prior arrangement with the T-800, we’ll extend our helper function with a secret feature that checks the dead drop for a previous value <span class="math inline">\(x_{i-1}\)</span> and, if one’s there, uses it to – <em>muahahahaha</em>! – break the recursive call chain:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):             <span class="co"># &lt;- new stuff</span></span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:                   <span class="co"># &lt;</span></span>
<span id="cb17-3"><a href="#cb17-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)  <span class="co"># &lt;</span></span>
<span id="cb17-4"><a href="#cb17-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb17-5"><a href="#cb17-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> x</span>
<span id="cb17-6"><a href="#cb17-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb17-7"><a href="#cb17-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb17-8"><a href="#cb17-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb17-9"><a href="#cb17-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb17-10"><a href="#cb17-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)</span></code></pre></div>
<p>Ordinarily, we would think of the helper as a function of <span class="math inline">\(n_i\)</span> and <span class="math inline">\(k_i\)</span> that computes <span class="math inline">\(x_i\)</span>.
That’s because the <span class="math inline">\(x_{i-1}\)</span> argument can safely be ignored.
It has no effect unless the T-800 drops a value into it.</p>
<p>But if the T-800 <em>does</em> drop a value into it, we can see the function as representing the transformation</p>
<p><span class="math display">\[(n_i, k_i, x_{i-1}) \to x_i\]</span></p>
<p>Note that <span class="math inline">\(x_{i-1}\)</span> goes in and <span class="math inline">\(x_i\)</span> comes out.
And from that little kernel of power we can do some seriously crazy stuff.
For example: <em>reverse the backward flow of time.</em>
That is, compute forward through the recursive timeline instead of backward.</p>
<p>Yeah.</p>
<p>Read on.</p></li>
<li><p><strong>Modify the helper’s return statement to also pass through its non-secret arguments.</strong></p>
<div class="sourceCode" id="cb18"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n, k, x)  <span class="co"># &lt;-- here</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb18-8"><a href="#cb18-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb18-9"><a href="#cb18-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb18-10"><a href="#cb18-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)[<span class="dv">2</span>]  <span class="co"># &lt;-- note also</span></span></code></pre></div>
<p>Now our helper represents the transformation</p>
<p><span class="math display">\[(n_i, k_i, x_{i-1}) \to (n_i, k_i, x_i)\]</span></p>
<p>Interesting.</p></li>
<li><p><strong>Apply, to the non-secret arguments in the helper’s return statement, the <em>opposite</em> of the transformations applied to them in the recursive call.</strong></p>
<p>Since we passed <span class="math inline">\(n-1,k-1\)</span> into the recursive call, we’ll pass <span class="math inline">\(n+1,k+1\)</span> out through the return statement:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)  <span class="co"># &lt;-- look here</span></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)  <span class="co"># &lt;-- apply opposite here</span></span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb19-9"><a href="#cb19-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb19-10"><a href="#cb19-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)[<span class="dv">2</span>]</span></code></pre></div>
<p>Now our helper represents the transformation</p>
<p><span class="math display">\[(n_i, k_i, x_{i-1}) \to (n_{i+1}, k_{i+1}, x_i)\]</span></p>
<p><em>And now we can reverse the flow of time.</em></p>
<p>When we started out with our original recursive function, if we asked it for <span class="math inline">\(x_t\)</span>, the function had to go back in the timeline to get <span class="math inline">\(x_{t-1}\)</span>.
And to get <span class="math inline">\(x_{t-1}\)</span>, it had to go back even further to get <span class="math inline">\(x_{t-2}\)</span>.
And so on, chewing up stack every backward step of the way to <span class="math inline">\(x_0\)</span>.
It was heartbreaking, watching it work like that.</p>
<p>But now, we can step <em>the other way</em>.
If we have any (<span class="math inline">\(n_i, k_i, x_{i-1})\)</span> we can get <span class="math inline">\(x_i\)</span> straight away, no recursion required.
In goes <span class="math inline">\(x_{i-1}\)</span>, out comes <span class="math inline">\(x_i\)</span>.
<em>We can go forward</em>.</p>
<p>Why, if we knew <span class="math inline">\(n_1\)</span>, <span class="math inline">\(k_1\)</span>, and <span class="math inline">\(x_0\)</span>, we could compute the entire series <span class="math inline">\(x_0, x_1, \ldots x_t\)</span> with <em>zero</em> recursion by starting at <span class="math inline">\(i=0\)</span> and working forward.</p>
<p>So let’s get those values!</p></li>
<li><p><strong>Determine the initial conditions at the start of the timeline.</strong></p>
<p>For this simple example, most of you can probably determine the initial conditions by inspection.
But I’m going to go through the process anyway.
You never know when you might need it.
So:</p>
<p>What’s the start of the timeline?
It’s when the recursive <code>binomial</code> function calls itself so many times that it finally hits one of its base cases, which defines the first entry in the timeline, anchoring the timeline at time <span class="math inline">\(i = 0\)</span>.
The base cases in this example are easy to find since we’ve already split out the <code>step</code> logic; all that’s left in <code>binomial</code> is the base-case logic.
It’s easy to see that there is only one base case, and it’s when <span class="math inline">\(k=0\)</span>:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)</span>
<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb20-8"><a href="#cb20-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:    <span class="co"># &lt;-- base case</span></span>
<span id="cb20-9"><a href="#cb20-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb20-10"><a href="#cb20-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> step(n, k)[<span class="dv">2</span>]</span></code></pre></div>
<p>From this base case we know that at the very start of the timeline we must have <span class="math inline">\(i=0\)</span>, <span class="math inline">\(k=0\)</span>, and <span class="math inline">\(x=1\)</span>.
Thus we know that <span class="math inline">\(k_0=0\)</span> and <span class="math inline">\(x_0=1\)</span>.
And because the timeline ends at time <span class="math inline">\(i = t\)</span>, and we know that <span class="math inline">\((n_t, k_t) = (n, k)\)</span>, the original arguments <code>binomial</code> was called with.</p>
<p>Let’s visualize what we know about the timeline so far:</p>
<table>
<thead>
<tr class="header">
<th style="text-align: right;">time <span class="math inline">\(i\)</span>:</th>
<th style="text-align: center;"><span class="math inline">\(0\)</span></th>
<th style="text-align: center;"><span class="math inline">\(1\)</span></th>
<th style="text-align: center;"><span class="math inline">\(2\)</span></th>
<th style="text-align: center;"><span class="math inline">\(\cdots\)</span></th>
<th style="text-align: center;"><span class="math inline">\(t\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;"><span class="math inline">\(n_i\)</span>:</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;"><span class="math inline">\(n\)</span></td>
</tr>
<tr class="even">
<td style="text-align: right;"><span class="math inline">\(k_i\)</span>:</td>
<td style="text-align: center;"><span class="math inline">\(0\)</span></td>
<td style="text-align: center;">–</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;"><span class="math inline">\(k\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: right;"><span class="math inline">\(x_i\)</span>:</td>
<td style="text-align: center;"><span class="math inline">\(1\)</span></td>
<td style="text-align: center;">–</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;">?</td>
</tr>
</tbody>
</table>
<p>The answer we ultimately seek is <span class="math inline">\(x_t\)</span>, marked by a question mark in the timeline.</p>
<p>Now to determine <span class="math inline">\(n_1\)</span> and <span class="math inline">\(k_1\)</span>.
To do that, we must answer this question:
How do we go from <span class="math inline">\((n_i, k_i)\)</span> to <span class="math inline">\((n_{i+1}, k_{i+1})\)</span>?</p>
<p>We already know the answer!
Our <code>step</code> helper computes <span class="math inline">\((n_i, k_i, x_{i-1}) \to (n_{i+1}, k_{i+1}, x_i)\)</span>.
So look at its logic: How does it transform its <span class="math inline">\(n\)</span> and <span class="math inline">\(k\)</span> arguments?
It adds one to them.
Thus,</p>
<p><span class="math display">\[\begin{eqnarray*}
n_{i+1} &amp; = &amp; n_i + 1,\\
k_{i+1} &amp; = &amp; k_i + 1.
\end{eqnarray*}\]</span></p>
<p>Therefore,
<span class="math display">\[k_1 = k_0 + 1 = 0 + 1 = 1.\]</span>
Since <span class="math inline">\(k_i\)</span> is <span class="math inline">\(i\)</span> steps from <span class="math inline">\(k_0 = 0\)</span> and each step adds <span class="math inline">\(+1\)</span> we have
<span class="math display">\[k_i = k_0 + i (+1) = i.\]</span>
And when <span class="math inline">\(i=t\)</span> we know from the equation above that <span class="math inline">\(t = k_{t} = k\)</span>.</p>
<p>Finally, we can compute <span class="math inline">\(n_1\)</span>, which is <span class="math inline">\(t-1\)</span> <em>reverse</em> steps from <span class="math inline">\(n_t=n\)</span>, the only <span class="math inline">\(n_i\)</span> that we know so far:
<span class="math display">\[n_1 = n_t - (t - 1) (+1) = n - k + 1.\]</span></p>
<p>And now we have our initial conditions:</p>
<p><span class="math display">\[(n_1, k_1, x_0) = (n - k + 1, 1, 0).\]</span></p>
<p>So now our knowledge of the timeline looks like this:</p>
<table>
<thead>
<tr class="header">
<th style="text-align: right;">time <span class="math inline">\(i\)</span>:</th>
<th style="text-align: center;"><span class="math inline">\(0\)</span></th>
<th style="text-align: center;"><span class="math inline">\(1\)</span></th>
<th style="text-align: center;"><span class="math inline">\(2\)</span></th>
<th style="text-align: center;"><span class="math inline">\(\cdots\)</span></th>
<th style="text-align: center;"><span class="math inline">\(t=k\)</span></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: right;"><span class="math inline">\(n_i\)</span>:</td>
<td style="text-align: center;"><span class="math inline">\(n-k\)</span></td>
<td style="text-align: center;"><span class="math inline">\(n-k+1\)</span></td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;"><span class="math inline">\(n\)</span></td>
</tr>
<tr class="even">
<td style="text-align: right;"><span class="math inline">\(k_i\)</span>:</td>
<td style="text-align: center;"><span class="math inline">\(0\)</span></td>
<td style="text-align: center;"><span class="math inline">\(1\)</span></td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;"><span class="math inline">\(k\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: right;"><span class="math inline">\(x_i\)</span>:</td>
<td style="text-align: center;"><span class="math inline">\(1\)</span></td>
<td style="text-align: center;">–</td>
<td style="text-align: center;">–</td>
<td style="text-align: center;"><span class="math inline">\(\cdots\)</span></td>
<td style="text-align: center;">?</td>
</tr>
</tbody>
</table>
<p>And with this knowledge, we can step forward through the timeline, from time <span class="math inline">\(i=1\)</span> to time <span class="math inline">\(i=2\)</span>, and so on, until finally, at the last step when <span class="math inline">\(i=t\)</span> we will have determined <span class="math inline">\(x_t\)</span>, our desired answer!</p>
<p>Let’s do it!</p></li>
<li><p><strong>In the main function, iterate the <code>step</code> helper <span class="math inline">\(t\)</span> times, starting from the initial conditions. Then return <span class="math inline">\(x_t\)</span>.</strong></p>
<div class="sourceCode" id="cb21"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)</span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">==</span> <span class="dv">0</span>:</span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb21-10"><a href="#cb21-10" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> k                                            <span class="co"># &lt;- new</span></span>
<span id="cb21-11"><a href="#cb21-11" aria-hidden="true" tabindex="-1"></a>    (n, k, previous_x) <span class="op">=</span> (n <span class="op">-</span> k <span class="op">+</span> <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>)           <span class="co">#</span></span>
<span id="cb21-12"><a href="#cb21-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> _i <span class="kw">in</span> <span class="bu">xrange</span>(<span class="dv">1</span>, t <span class="op">+</span> <span class="dv">1</span>):                      <span class="co">#</span></span>
<span id="cb21-13"><a href="#cb21-13" aria-hidden="true" tabindex="-1"></a>        (n, k, previous_x) <span class="op">=</span> step(n, k, previous_x)  <span class="co">#</span></span>
<span id="cb21-14"><a href="#cb21-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> previous_x  <span class="co"># = x_t                       #</span></span></code></pre></div>
<p>Boom!
That’s 100% iterative.
But there’s more!</p></li>
<li><p><strong>Remove the base cases from the original function.</strong></p>
<p>Since our iterations start from a base case, the base cases are already incorporated into our new, iterative logic.</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x<span class="op">=</span><span class="va">None</span>):</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> previous_x <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a>        previous_x <span class="op">=</span> binomial(n <span class="op">-</span> <span class="dv">1</span>, k <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)</span>
<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a>    <span class="co"># if k == 0:   # &lt;- remove these lines</span></span>
<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a>    <span class="co">#    return 1  #</span></span>
<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> k</span>
<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a>    (n, k, previous_x) <span class="op">=</span> (n <span class="op">-</span> k <span class="op">+</span> <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>)</span>
<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> _i <span class="kw">in</span> <span class="bu">xrange</span>(<span class="dv">1</span>, t <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a>        (n, k, previous_x) <span class="op">=</span> step(n, k, previous_x)</span>
<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> previous_x  <span class="co"># = x_t</span></span></code></pre></div>
<p>Boom again!</p></li>
<li><p><strong>Remove the secret feature from the <code>step</code> function.</strong></p>
<p>Since <code>previous_x</code> always gets a value now, we can make it a required part of the function.</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> step(n, k, previous_x):  <span class="co"># &lt;- remove default value for previous_x</span></span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>    <span class="co"># if previous_x is None:                  # &lt;- remove these 2 lines</span></span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>    <span class="co">#    previous_x = binomial(n - 1, k - 1)  #</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)</span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb23-8"><a href="#cb23-8" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> k</span>
<span id="cb23-9"><a href="#cb23-9" aria-hidden="true" tabindex="-1"></a>    (n, k, previous_x) <span class="op">=</span> (n <span class="op">-</span> k <span class="op">+</span> <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>)</span>
<span id="cb23-10"><a href="#cb23-10" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> _i <span class="kw">in</span> <span class="bu">xrange</span>(<span class="dv">1</span>, t <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb23-11"><a href="#cb23-11" aria-hidden="true" tabindex="-1"></a>        (n, k, previous_x) <span class="op">=</span> step(n, k, previous_x)</span>
<span id="cb23-12"><a href="#cb23-12" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> previous_x  <span class="co"># = x_t</span></span></code></pre></div></li>
<li><p><strong>Inline the <code>step</code> function.</strong></p>
<p>We’re on it!</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> k</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>    (n, k, previous_x) <span class="op">=</span> (n <span class="op">-</span> k <span class="op">+</span> <span class="dv">1</span>, <span class="dv">1</span>, <span class="dv">1</span>)</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> _i <span class="kw">in</span> <span class="bu">xrange</span>(<span class="dv">1</span>, t <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a>        x <span class="op">=</span> n <span class="op">*</span> previous_x <span class="op">//</span> k</span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a>        (n, k, previous_x) <span class="op">=</span> (n <span class="op">+</span> <span class="dv">1</span>, k <span class="op">+</span> <span class="dv">1</span>, x)</span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> previous_x  <span class="co"># = x_t</span></span></code></pre></div></li>
<li><p><strong>Apply finishing touches.</strong></p>
<p>This example is pretty tight already, but we can substitute away the <code>x</code> variable.</p>
<p>And, because <span class="math inline">\(k_i = i\)</span>, we can replace the <code>for</code> loop’s induction variable <code>_i</code> with <span class="math inline">\(k_i\)</span> and correspondingly eliminate <span class="math inline">\(k_i\)</span> from the step logic.</p>
<p>And, while we’re making stuff better, there’s an obvious optimization.
One property of binomial coefficients is that <span class="math inline">\(\binom{n}{k} = \binom{n}{n-k}\)</span>.
One property of our code is that it runs for <span class="math inline">\(t=k\)</span> steps.
So when <span class="math inline">\(k &gt; n-k\)</span>, we can reduce the number of steps by solving for <span class="math inline">\(\binom{n}{n-k}\)</span> instead.
Let’s add a couple of lines at the start of the logic to claim this optimization.</p>
<p>And, of course, let’s add a docstring – we’re nice like that.</p>
<p>The final result:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> binomial(n, k):</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Compute binomial coefficient C(n, k) = n! / (k! * (n-k)!).&quot;&quot;&quot;</span></span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> k <span class="op">&gt;</span> n <span class="op">-</span> k:</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>        k <span class="op">=</span> n <span class="op">-</span> k   <span class="co"># &#39;pute C(n, n-k) instead if it&#39;s easier</span></span>
<span id="cb25-5"><a href="#cb25-5" aria-hidden="true" tabindex="-1"></a>    t <span class="op">=</span> k</span>
<span id="cb25-6"><a href="#cb25-6" aria-hidden="true" tabindex="-1"></a>    (n, previous_x) <span class="op">=</span> (n <span class="op">-</span> k <span class="op">+</span> <span class="dv">1</span>, <span class="dv">1</span>)</span>
<span id="cb25-7"><a href="#cb25-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">for</span> k <span class="kw">in</span> <span class="bu">xrange</span>(<span class="dv">1</span>, t <span class="op">+</span> <span class="dv">1</span>):</span>
<span id="cb25-8"><a href="#cb25-8" aria-hidden="true" tabindex="-1"></a>        (n, previous_x) <span class="op">=</span> (n <span class="op">+</span> <span class="dv">1</span>, n <span class="op">*</span> previous_x <span class="op">//</span> k)</span>
<span id="cb25-9"><a href="#cb25-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> previous_x  <span class="co"># = x_t</span></span></code></pre></div></li>
</ol>
<p>Let’s review what we just did.
It’s mind blowing:</p>
<ol>
<li>We sent an <em>imaginary</em> T-800 terminator unit back into the function’s timeline.</li>
<li>Then we added a secret feature to our function that allowed the T-800 to <em>send us values from the timeline’s past</em>.</li>
<li>Then we used those values to break the recursive chain, reverse the backward flow of time, and compute the timeline forward and iteratively instead of backward and recursively.</li>
<li>The function then being fully iterative, we removed the secret feature, and the imaginary T-800 winked out of existence. (In an ironic twist of fate, the T-800, via the secret-feature dead drop, had delivered into our hands precisely the knowledge we needed to write both of them out of history!)</li>
<li>And now we have a fast, efficient, and property-preserving iterative version of our original recursive function, and it’s about as good as anything we could hope to conjure up from scratch. (<a href="http://www.pythontutor.com/visualize.html#code=def+binomial(n,+k)%3A%0A++++%22%22%22Compute+binomial+coefficient+C(n,+k)+%3D+n!+/+(k!+*+(n-k)!).%22%22%22%0A++++if+k+%3D%3D+0%3A%0A++++++++return+1%0A++++return+n+*+binomial(n+-+1,+k+-+1)+//+k%0A%0Adef+binomial_iter(n,+k)%3A%0A++++%22%22%22Compute+binomial+coefficient+C(n,+k)+%3D+n!+/+(k!+*+(n-k)!).%22%22%22%0A++++lmul+%3D+rdiv+%3D+1%0A++++while+k+%3E+0%3A%0A++++++++(n,+k,+lmul,+rdiv)+%3D+(n+-+1,+k+-+1,+lmul+*+n,+k+*+rdiv)%0A++++return+lmul+//+rdiv%0A%0Adef+binomial_iter_final(n,+k)%3A%0A++++%22%22%22Compute+binomial+coefficient+C(n,+k)+%3D+n!+/+(k!+*+(n-k)!).%22%22%22%0A++++if+k+%3D%3D+0%3A%0A++++++++return+1%0A++++t+%3D+k%0A++++(n,+k,+previous_x)+%3D+(n+-+k+%2B+1,+1,+1)%0A++++for+_+in+xrange(t)%3A%0A++++++++(n,+k,+previous_x)+%3D+(n+%2B+1,+k+%2B+1,+n+*+previous_x+//+k)%0A++++return+previous_x++%23+%3D+x_t%0A%0Aprint+binomial(39,+9)%0Aprint+binomial_iter(39,+9)%0Aprint+binomial_iter_final(39,+9)&amp;mode=display&amp;cumulative=false&amp;heapPrimitives=false&amp;drawParentPointers=false&amp;textReferences=false&amp;showOnlyOutputs=false&amp;py=2&amp;curInstr=0">See it in action</a> – just one stack frame and easy on the ints, too.)</li>
<li>And – most importantly – we did it all using a mechanical, repeatable process!</li>
</ol>
<h3 id="thanks">Thanks!</h3>
<p>Well, that’s it for this installment.
I hope you enjoyed reading it as much as I did writing it.
If you liked it (or didn’t), or if you found a mistake, or especially if you can think of any way to help make my explanations better, let me know.
Just post a comment or fire me a tweet at <a href="https://twitter.com/tmoertel">@tmoertel</a>.</p>
<p>Until next time, keep your brain recursive and your Python code iterative.</p>
<hr />
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1"><p>In the visualization, you can’t actually see the largest integer produced by the recursive version’s computation. It’s produced between steps 32 and 33, when the return value from step 32 is multiplied by step 33’s <span class="math inline">\(n=39\)</span> to arrive at an integer of <span class="math inline">\(\log_2(39 \cdot 48903492) \approx 30.8\)</span> bits, which is then immediately divided by <span class="math inline">\(k=9\)</span> to produce the final answer.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
]]></summary>
</entry>
<entry>
    <title>Tricks of the trade: Recursion to Iteration, Part 1: The Simple Method, secret features, and accumulators</title>
    <link href="http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html" />
    <id>http://blog.moertel.com/posts/2013-05-11-recursive-to-iterative.html</id>
    <published>2013-05-11T00:00:00Z</published>
    <updated>2013-05-11T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-05-11">May 11, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;programming&#39;." href="/tags/programming.html" rel="tag">programming</a>, <a title="All pages tagged &#39;recursion&#39;." href="/tags/recursion.html" rel="tag">recursion</a>, <a title="All pages tagged &#39;iteration&#39;." href="/tags/iteration.html" rel="tag">iteration</a>, <a title="All pages tagged &#39;python&#39;." href="/tags/python.html" rel="tag">python</a>, <a title="All pages tagged &#39;google code jam&#39;." href="/tags/google%20code%20jam.html" rel="tag">google code jam</a>, <a title="All pages tagged &#39;puzzles&#39;." href="/tags/puzzles.html" rel="tag">puzzles</a>, <a title="All pages tagged &#39;recursion-to-iteration series&#39;." href="/tags/recursion-to-iteration%20series.html" rel="tag">recursion-to-iteration series</a></span></div>

<div itemprop="articleBody">
<p><em>Alternative title: I wish Python had tail-call elimination.</em></p>
<p>Recursive programming is powerful because it maps so easily to <a href="http://en.wikipedia.org/wiki/Mathematical_induction">proof by induction</a>, making it easy to design algorithms and prove them correct.</p>
<p>But recursion is poorly supported by many popular programming languages.
Drop a large input into a recursive algorithm in Python, and you’ll probably hit the runtime’s recursion limit.
Raise the limit, and you may run out of stack space and segfault.</p>
<p>These are not happy outcomes.</p>
<p>Therefore, an important trick of the trade is knowing how to translate recursive algorithms into iterative algorithms.
That way, you can design, prove, and initially code your algorithms in the almighty realm of recursion.
Then, after you’ve got things just the way you want them, you can translate your algorithms into equivalent iterative forms through a series of mechanical steps.
You can prove your cake and run it in Python, too.</p>
<p>This topic – turning recursion into iteration – is fascinating enough that I’m going to do <a href="http://blog.moertel.com/tags/recursion-to-iteration%20series.html">a series of posts on it</a>.
Tail calls, trampolines, continuation-passing style – and more.
Lots of good stuff.</p>
<p>For today, though, let’s just look at one simple method and one supporting trick.</p>
<h3 id="the-simple-method">The Simple Method</h3>
<p>This translation method works on many simple recursive functions.
When it works, it works well, and the results are lean and fast.
I generally try it first and consider more complicated methods only when it fails.</p>
<p>In a nutshell:</p>
<ol type="1">
<li>Study the function.</li>
<li>Convert all recursive calls into <a href="http://en.wikipedia.org/wiki/Tail_call">tail calls</a>.
(If you can’t, stop. Try another method.)</li>
<li>Introduce a one-shot loop around the function body.</li>
<li>Convert tail calls into <code>continue</code> statements.</li>
<li>Tidy up.</li>
</ol>
<p>An important property of this method is that it’s incrementally correct – after every step you have a function that’s equivalent to the original.
So if you have unit tests, you can run them after each and every step to make sure you didn’t make a mistake.</p>
<p>Let’s see the method in action.</p>
<h3 id="example-factorial">Example: factorial</h3>
<p>With a function this simple, we could probably go straight to the iterative version without using any techniques, just a little noggin power.
But the point here is to develop a <em>mechanical process</em> that we can trust when our functions aren’t so simple or our noggins aren’t so powered.
So we’re going to work on a <em>really simple</em> function so that we can focus on the process.</p>
<p>Ready? Then let’s show these guys how cyber-commandos get it done! <a href="https://www.youtube.com/watch?v=0dofacvjRkc&amp;feature=youtube_gdata_player"><em>Mark IV style!</em></a></p>
<ol type="1">
<li><p>Study the original function.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n):</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>Nothing scary here.
Just one recursive call.
<em>We can do this!</em></p></li>
<li><p>Convert recursive calls into tail calls.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">def</span> factorial1a(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>     <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>         <span class="cf">return</span> <span class="dv">1</span> <span class="op">*</span> acc</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>     <span class="cf">return</span> factorial1a(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span></code></pre></div>
<p>(If this step seemed confusing, see the Bonus Explainer at the end of the
article for the “secret feature” trick behind the step.)</p></li>
<li><p>Introduce a one-shot loop around the function body.
You want <code>while True:</code> <em>body</em> <code>; break</code>.</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial1b(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="va">True</span>:</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="dv">1</span> <span class="op">*</span> acc</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> factorial1b(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">break</span></span></code></pre></div>
<p>Yes, I know putting a <code>break</code> after a <code>return</code> is crazy, but do it anyway.
Clean-up comes later.
For now, we’re going by the numbers.</p></li>
<li><p>Replace all recursive tail calls <code>f(x=x1, y=y1, ...)</code> with
<code>(x, y, ...) = (x1, y1, ...); continue</code>. Be sure to update <em>all</em>
arguments in the assignment.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial1c(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> <span class="va">True</span>:</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> <span class="dv">1</span> <span class="op">*</span> acc</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>        (n, acc) <span class="op">=</span> (n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>        <span class="cf">continue</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>        <span class="cf">break</span></span></code></pre></div>
<p>For this step, I copy the original function’s argument list,
parentheses and all, and paste it over the <code>return</code> keyword.
Less chance to screw something up that way.
It’s all about being mechanical.</p></li>
<li><p>Tidy the code and make it more idiomatic.</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial1d(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">while</span> n <span class="op">&gt;</span> <span class="dv">1</span>:</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a>        (n, acc) <span class="op">=</span> (n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> acc</span></code></pre></div>
<p>Okay.
This step is less about mechanics and more about style.
Eliminate the cruft.
Simplify.
Make it sparkle.</p></li>
<li><p>That’s it. You’re finished!</p></li>
</ol>
<h3 id="what-have-we-gained">What have we gained?</h3>
<p>We just did five steps of work to convert our original, recursive <code>factorial</code> function into the equivalent, iterative <code>factorial1d</code> function.
If our programming language had supported tail-call elimination, we could have stopped at step two with <code>factorial1a</code>.
But <em>nooooooo</em>…
We had to press on, all the way through step five, because we’re using Python.
It’s almost enough to make a cyber-commando punch a kitten.</p>
<p>No, the work wasn’t hard, but it was still work.
So what did it buy us?</p>
<p>To <em>see</em> what it bought us, let’s look inside the Python run-time environment.
We’ll use the Online Python Tutor’s visualizer to observe the build-up of stack frames as <code>factorial</code>, <code>factorial1a</code>, and <code>factorial1d</code> each compute the factorial of 5.</p>
<p>This is very cool, so don’t miss the link: <a href="http://www.pythontutor.com/visualize.html#code=%23+original+version%0A%0Adef+factorial(n)%3A%0A++++if+n+%3C+2%3A%0A++++++++return+1%0A++++return+n+*+factorial(n+-+1)%0A%0A%23+tail-call+version%0A%0Adef+factorial1a(n,+acc%3D1)%3A%0A+++++if+n+%3C+2%3A%0A+++++++++return+1+*+acc%0A+++++return+factorial1a(n+-+1,+acc+*+n)%0A%0A%23+iterative+version%0A%0Adef+factorial1d(n,+acc%3D1)%3A%0A++++while+n+%3E+1%3A%0A++++++++(n,+acc)+%3D+(n+-+1,+acc+*+n)%0A++++return+acc%0A%0Aprint+factorial(5)%0Aprint+factorial1a(5)%0Aprint+factorial1d(5)&amp;mode=display&amp;cumulative=false&amp;heapPrimitives=false&amp;drawParentPointers=false&amp;textReferences=false&amp;showOnlyOutputs=false&amp;py=2">Visualize It!</a> (ProTip: Open it in a new tab.)</p>
<p>Click the “Forward” button to step through the execution of the functions.
Notice what happens in the Frames column.
When <code>factorial</code> is computing the factorial of 5, five frames build up on the stack.
Not a coincidence.</p>
<p>Same thing for our tail-recursive <code>factorial1a</code>.
(You’re right. It <em>is</em> tragic.)</p>
<p>But not for our iterative wonder <code>factorial1d</code>.
It uses just <em>one</em> stack frame, over and over, until it’s done.
That’s economy!</p>
<p>That’s why we did the work.
Economy.
We converted <em>O</em>(<em>n</em>) stack use into <em>O</em>(1) stack use.
When <em>n</em> could be large, that savings matters.
It could be the difference between getting an answer and getting a segfault.</p>
<h3 id="not-so-simple-cases">Not-so-simple cases</h3>
<p>Okay, so we tackled <code>factorial</code>.
But that was an easy one.
What if your function isn’t so easy?
Then it’s time for more advanced methods.</p>
<p>That’s our topic for next time.</p>
<p>Until then, keep your brain recursive and your Python code iterative.</p>
<h3 id="bonus-explainer-using-secret-features-for-tail-call-conversion">Bonus Explainer: Using secret features for tail-call conversion</h3>
<p>In step 2 of The Simple Method, we converted the recursive call in this code:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n):</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="dv">1</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)  <span class="co"># &lt;-- right here!</span></span></code></pre></div>
<p>into the recursive <em>tail</em> call in this code:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">def</span> factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a>     <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>         <span class="cf">return</span> <span class="dv">1</span> <span class="op">*</span> acc</span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a>     <span class="cf">return</span> factorial(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)  <span class="co"># &lt;-- oh, yeah!</span></span></code></pre></div>
<p>This conversion is easy once you get the hang of it, but the first few times you see it, it seems like magic.
So let’s take this one step by step.</p>
<p>First, the problem.
We want to get rid of the <code>n *</code> in the following code:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>That <code>n *</code> stands between our recursive call to <code>factorial</code> and the <code>return</code> keyword.
In other words, the code is actually equivalent to the following:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>    x <span class="op">=</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>    result <span class="op">=</span> n <span class="op">*</span> x</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> result</span></code></pre></div>
<p>That is, our code has to call the <code>factorial</code> function, await its result (<code>x</code>), and then <em>do something</em> with that result (multiply it by <code>n</code>) before it can return <em>its</em> result.
It’s that pesky intermediate <em>doing something</em> we must get rid of.
We want <em>nothing</em> but the recursive call to <code>factorial</code> in the <code>return</code> statement.</p>
<p>So how do we get rid of that multiplication?</p>
<p>Here’s the trick.
We extend our function with a <em>multiplication feature</em> and use it to do the multiplication for us.</p>
<p>Shh!
It’s a <em>secret</em> feature, though, just for us.
Nobody else.</p>
<p>In essence, every call to our extended function will not only compute a factorial <em>but also</em> (<em>secretly</em>) <em>multiply that factorial by whatever extra value we give it</em>.
The variables that hold these extra values are often called “accumulators,” so I use the name <code>acc</code> here as a nod to tradition.</p>
<p>So here’s our function, freshly extended:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> acc <span class="op">*</span> <span class="dv">1</span></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> acc <span class="op">*</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>See what I did to add the secret multiplication feature?
Two things.</p>
<p>First, I took the original function and added an additional argument <code>acc</code>, the multiplier.
Note that it defaults to <code>1</code> so that it has no effect until we give it some other value (since <span class="math inline">\(1 \cdot x = x\)</span>).
Gotta keep the secret secret, after all.</p>
<p>Second, I changed <em>every single</em> <code>return</code> statement from <code>return {whatever}</code> to <code>return acc * {whatever}</code>.
Whenever our function would have returned <code>x</code>, it now returns <code>acc * x</code>.
And that’s it.
Our secret feature is done!
<em>And</em> it’s trivial to prove correct.
(In fact, we just did prove it correct! Re-read the second sentence.)</p>
<p>Both changes were entirely mechanical, hard to screw up, and, together, default to doing nothing.
These are the properties you want when adding secret features to your functions.</p>
<p>Okay.
Now we have a function that computes the factorial of <code>n</code> and, secretly, multiplies it by <code>acc</code>.</p>
<p>Now let’s return to that troublesome line, but in our newly extended function:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> acc <span class="op">*</span> n <span class="op">*</span> factorial(n <span class="op">-</span> <span class="dv">1</span>)</span></code></pre></div>
<p>It computes the factorial of <code>n - 1</code> and then multiplies it by <code>acc * n</code>.
But wait!
We don’t need to do that multiplication ourselves.
Not anymore.
Now we can ask our extended factorial function to do it for us, <em>using the secret feature.</em></p>
<p>So we can rewrite the troublesome line as</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> factorial(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span></code></pre></div>
<p>And that’s a tail call!</p>
<p>So our tail-call version of the <code>factorial</code> function is this:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> factorial(n, acc<span class="op">=</span><span class="dv">1</span>):</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> n <span class="op">&lt;</span> <span class="dv">2</span>:</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> acc <span class="op">*</span> <span class="dv">1</span></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>    <span class="cf">return</span> factorial(n <span class="op">-</span> <span class="dv">1</span>, acc <span class="op">*</span> n)</span></code></pre></div>
<p>And now that all our recursive calls are tail calls – there was only the one – this function is easy to convert into iterative form using The Simple Method described in the main article.</p>
<p>Let’s review the Secret Feature trick for making recursive calls into tail calls.
By the numbers:</p>
<ol type="1">
<li>Find a recursive call that’s not a tail call.</li>
<li>Identify what work is being done between that call and its <code>return</code> statement.</li>
<li>Extend the function with a secret feature to do that work, as controlled by a new accumulator argument with a default value that causes it to do nothing.</li>
<li>Use the secret feature to eliminate the old work.</li>
<li>You’ve now got a tail call!</li>
<li>Repeat until all recursive calls are tail calls.</li>
</ol>
<p>With a little practice, it becomes second nature.
So…</p>
<h3 id="exercise-get-your-practice-on">Exercise: Get your practice on!</h3>
<p>You mission is to get rid of the recursion in the following function.
Feel like you can handle it?
Then just <a href="https://github.com/tmoertel/recursion-to-iteration">fork the exercise repo</a> and do your stuff to <a href="https://github.com/tmoertel/recursion-to-iteration/blob/master/exercise1.py">exercise1.py</a>.</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> find_val_or_next_smallest(bst, x):</span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>    <span class="co">&quot;&quot;&quot;Get the greatest value &lt;= x in a binary search tree.</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a><span class="co">    Returns None if no such value can be found.</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a><span class="co">    &quot;&quot;&quot;</span></span>
<span id="cb14-7"><a href="#cb14-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> bst <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> <span class="va">None</span></span>
<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a>    <span class="cf">elif</span> bst.val <span class="op">==</span> x:</span>
<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> x</span>
<span id="cb14-11"><a href="#cb14-11" aria-hidden="true" tabindex="-1"></a>    <span class="cf">elif</span> bst.val <span class="op">&gt;</span> x:</span>
<span id="cb14-12"><a href="#cb14-12" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> find_val_or_next_smallest(bst.left, x)</span>
<span id="cb14-13"><a href="#cb14-13" aria-hidden="true" tabindex="-1"></a>    <span class="cf">else</span>:</span>
<span id="cb14-14"><a href="#cb14-14" aria-hidden="true" tabindex="-1"></a>        right_best <span class="op">=</span> find_val_or_next_smallest(bst.right, x)</span>
<span id="cb14-15"><a href="#cb14-15" aria-hidden="true" tabindex="-1"></a>        <span class="cf">if</span> right_best <span class="kw">is</span> <span class="va">None</span>:</span>
<span id="cb14-16"><a href="#cb14-16" aria-hidden="true" tabindex="-1"></a>            <span class="cf">return</span> bst.val</span>
<span id="cb14-17"><a href="#cb14-17" aria-hidden="true" tabindex="-1"></a>        <span class="cf">return</span> right_best</span></code></pre></div>
<p>Have fun!</p>
</div>
]]></summary>
</entry>
<entry>
    <title>Odds and the evidence of a single coin toss</title>
    <link href="http://blog.moertel.com/posts/2013-03-04-odds-and-the-evidence-of-a-single-coin-toss.html" />
    <id>http://blog.moertel.com/posts/2013-03-04-odds-and-the-evidence-of-a-single-coin-toss.html</id>
    <published>2013-03-04T00:00:00Z</published>
    <updated>2013-03-04T00:00:00Z</updated>
    <summary type="html"><![CDATA[<div class="info byline">By
  <span itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="https://blog.moertel.com/about.html" itemprop="url"><span itemprop="name">Tom Moertel</span></a></span></div>
<div class="info">Posted on <time itemprop="datePublished" datetime="2013-03-04">March  4, 2013</time></div>
<div class="tags">Tags: <span itemprop="keywords"><a title="All pages tagged &#39;probability&#39;." href="/tags/probability.html" rel="tag">probability</a>, <a title="All pages tagged &#39;odds&#39;." href="/tags/odds.html" rel="tag">odds</a>, <a title="All pages tagged &#39;bayesian&#39;." href="/tags/bayesian.html" rel="tag">bayesian</a>, <a title="All pages tagged &#39;coin-toss-problem&#39;." href="/tags/coin-toss-problem.html" rel="tag">coin-toss-problem</a>, <a title="All pages tagged &#39;reasoning&#39;." href="/tags/reasoning.html" rel="tag">reasoning</a>, <a title="All pages tagged &#39;evidence&#39;." href="/tags/evidence.html" rel="tag">evidence</a></span></div>

<div itemprop="articleBody">
<p>A while ago I wrote about <a href="http://blog.moertel.com/posts/2010-12-20-more-on-the-evidence-of-a-single-coin-toss.html">how to update your beliefs in light of the evidence contained within a single coin toss</a>.
My article ended with the tantalizing prospect of an easier way to do such updates using <em>odds</em>.
That prospect is what we’ll explore in this article.</p>
<p>First, we’ll be using the same probability notation as before.
If you’re unfamiliar with it, go back and review <a href="http://blog.moertel.com/posts/2010-12-20-more-on-the-evidence-of-a-single-coin-toss.html">the earlier article</a>.</p>
<p>Second, if you’re reading this article from a feed, there’s a good chance that the math is going to look screwy because MathML doesn’t travel well. If so, just click through to the original article for a proper rendering.</p>
<p>Now, to the good stuff.</p>
<h3 id="introducing-odds">Introducing odds</h3>
<p>The odds on a proposition <span class="math inline">\(X\)</span>, written <span class="math inline">\(O(X)\)</span>, is just the probability that <span class="math inline">\(X\)</span> is true relative to the probability that it is false:
<span class="math display">\[O(X) = \frac{P(X)}{P(\neg X)} = \frac{P(X)}{1 - P(X)}\]</span></p>
<p>Thus given a probability <span class="math inline">\(p\)</span> we can compute the equivalent odds <span class="math inline">\(o = p/(1-p)\)</span>.
This formula maps (monotonically) the intuitive probability scale of <span class="math inline">\(p \in [0, 1]\)</span> to the seemingly bizarre odds scale of <span class="math inline">\(o \in [0, \infty]\)</span>.
Why would we want to do this?
The short answer: odds are often easier to work with.</p>
<p>But before we see how odds can make calculations easier, let’s try to gain some intuition about what they represent.
Here are some common degrees of belief encoded as both probabilities and odds:</p>
<table>
<thead>
<tr class="header">
<th style="text-align: left;">degree of belief</th>
<th style="text-align: left;">probability</th>
<th style="text-align: left;">odds</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: left;">I’m certain it’s false</td>
<td style="text-align: left;"><span class="math inline">\(p=0\)</span></td>
<td style="text-align: left;"><span class="math inline">\(o=0\)</span></td>
</tr>
<tr class="even">
<td style="text-align: left;">I’m certain it’s true</td>
<td style="text-align: left;"><span class="math inline">\(p=1\)</span></td>
<td style="text-align: left;"><span class="math inline">\(o=\infty\)</span></td>
</tr>
<tr class="odd">
<td style="text-align: left;">I have no idea</td>
<td style="text-align: left;"><span class="math inline">\(p=1/2\)</span></td>
<td style="text-align: left;"><span class="math inline">\(o=1\)</span></td>
</tr>
</tbody>
</table>
<p>For historical reasons, you’ll often see odds written as a ratio <span class="math inline">\(n:m\)</span>.
These ratios can be normalized to the form <span class="math inline">\(o:1\)</span> where <span class="math inline">\(o = n/m\)</span>.
When <span class="math inline">\(n=m\)</span>, the odds are said to be “even” or “one-to-one” or “fifty-fifty”; all such ratios normalize to <span class="math inline">\(o=1\)</span>.</p>
<h3 id="updating-beliefs-using-odds">Updating beliefs using odds</h3>
<p>If you’ll recall, Bayes’ rule tells us that the plausibility of a proposition <span class="math inline">\(X\)</span> in light of some new evidence <span class="math inline">\(E\)</span> is just the proposition’s prior plausibility multiplied by an adjustment factor for the new evidence:</p>
<p><span class="math display">\[(\mbox{new plausibility}) = (\mbox{old plausibility}) \times (\mbox{evidence adjustment})\]</span></p>
<p>In terms of probabilities, it looks like this:</p>
<p><span class="math display">\[P(X \mid E) = P(X) \times {P(E \mid X)}/{P(E)}\]</span></p>
<p>What about in terms of odds?
Since odds relate the probabilities of <span class="math inline">\(X\)</span> and <span class="math inline">\(\neg X\)</span>, let’s consider what happens to the probability of <span class="math inline">\(\neg X\)</span> when we learn about new evidence <span class="math inline">\(E\)</span>.
As for <span class="math inline">\(X\)</span>, it’s just a straightforward application of Bayes’ rule:</p>
<p><span class="math display">\[P(\neg X \mid E) = P(\neg X) \times {P(E \mid \neg X)}/{P(E)}\]</span></p>
<p>Now let’s divide the first equation by the second:</p>
<p><span class="math display">\[\frac{P(X \mid E)}{P(\neg X \mid E)} =
  \frac{P(X) \times {P(E \mid X)}/{P(E)}}{P(\neg X) \times {P(E \mid \neg X)}/{P(E)}}\]</span></p>
<p>Breaking up the terms gives us pieces we can begin to recognize:</p>
<p><span class="math display">\[\frac{P(X \mid E)}{P(\neg X \mid E)} =
  \frac{P(X)}{P(\neg X)} \times \frac{P(E \mid X)}{P(E \mid \neg X)} \times \frac{1/P(E)}{1/P(E)}\]</span></p>
<p>The term on the left side and the initial term on the right side are now easily recognized as odds.
The final term on the right side, involving our prior beliefs about <span class="math inline">\(E\)</span>, helpfully drops out altogether.
(This is a big win, as we’ll see later.)
What we’re left with is simple and easy to interpret:</p>
<p><span class="math display">\[O(X \mid E) =  O(X) \times \frac{P(E \mid X)}{P(E \mid \neg X)}\]</span></p>
<p>In other words, it’s our familiar belief-updating rule, just in terms of odds:</p>
<p><span class="math display">\[(\mbox{new odds}) = (\mbox{old odds}) \times (\mbox{evidence adjustment})\]</span></p>
<p>But now the evidence adjustment is a ratio of two likelihoods (and is often called a “likelihood ratio”):</p>
<table>
<thead>
<tr class="header">
<th style="text-align: center;">adjustment for probabilities</th>
<th style="text-align: center;">adjustment for odds</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td style="text-align: center;"><span class="math display">\[\frac{P(E \mid X)}{P(E)}\]</span></td>
<td style="text-align: center;"><span class="math display">\[\frac{P(E \mid X)}{P(E \mid \neg X)}\]</span></td>
</tr>
</tbody>
</table>
<p>Note the difference in denominators.
It’s often easier to come by <span class="math inline">\(P(E \mid \neg X)\)</span> than <span class="math inline">\(P(E)\)</span>.
As a case in point, let’s return to <a href="http://blog.moertel.com/posts/2010-12-07-on-the-evidence-of-a-single-coin-toss.html">our earlier coin-toss problem</a>.</p>
<h3 id="using-odds-to-update-our-beliefs-in-the-coin-toss-problem">Using odds to update our beliefs in the coin-toss problem</h3>
<p>If you’ll recall, I had claimed <span class="math inline">\(S\)</span>, that I had a special coin that always comes up heads.
You then observed evidence <span class="math inline">\(H\)</span>, that when you flipped the coin it did indeed come up heads.
My question to you was this: How much more should you believe <span class="math inline">\(S\)</span> in light of <span class="math inline">\(H\)</span>?</p>
<p>This “how much more” is exactly what our evidence adjustment represents.
In terms of odds, it’s just the likelihood ratio</p>
<p><span class="math display">\[\frac{P(H \mid S)}{P(H \mid \neg S)}.\]</span></p>
<p>If the coin is special, we know it will come up heads; thus the numerator is <span class="math inline">\(1\)</span>.
But if it’s not special, we have no reason to believe it’s more likely to come up heads or tails; thus the denominator is <span class="math inline">\(1/2\)</span>.
And that’s all we need:</p>
<p><span class="math display">\[\frac{P(H \mid S)}{P(H \mid \neg S)} = \frac{1}{1/2} = 2.\]</span></p>
<p>Problem solved: <em>In light of the coin coming up heads, we should double our odds on the coin being special.</em></p>
<h3 id="chaining-updates">Chaining updates</h3>
<p>Notice that in this case the evidence adjustment is a constant multiplier of <span class="math inline">\(2\)</span>.
In other words, <em>regardless of our prior odds that the coin is special</em>, when we see the coin come up heads, we should double our odds.</p>
<p><em>Exercise:</em> What if you flip the coin three times and get three heads?
How should this outcome affect your beliefs about <span class="math inline">\(S\)</span>?</p>
<p><em>Solution:</em>
This three-flip experiment is just the one-flip experiment repeated three times.
And each time we know what to do: double our odds on <span class="math inline">\(S\)</span>.
Thus observing the three-heads outcome should cause us to scale our prior odds by <span class="math inline">\(2\times 2\times 2 = 2^3 = 8\)</span>.</p>
<p>Using odds, our belief updates become trivial.
If the coin continues to come up heads in <span class="math inline">\(100\)</span> follow-up experiments, we just scale the current odds by <span class="math inline">\(2^{100}\)</span>.</p>
<p>In contrast, recall that <a href="http://blog.moertel.com/posts/2010-12-20-more-on-the-evidence-of-a-single-coin-toss.html">when we had solved the problem using probabilities</a>, the evidence adjustment was not constant; it depended upon our prior probability of <span class="math inline">\(S\)</span>.
If our prior probability was <span class="math inline">\(p\)</span>, our evidence adjustment was <span class="math inline">\(2/(1 + p)\)</span>.
This dependence makes it harder to answer questions about repeated experiments because each experiment affects our current probability <span class="math inline">\(p\)</span> and thus alters our evidence adjustment.
No more easy chaining.</p>
<p>So using odds in this case is a big win (and will often be when testing binary hypotheses).</p>
<h3 id="the-point">The point</h3>
<p>Odds and probabilities are two ways of encoding degrees of belief.
They are equivalent but have different effects on calculation.
Using one or the other will often make your life easier, so know how to use both.</p>
<p>P.S. If you find this stuff interesting, the best formal treatment I’ve found is <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0521592712"><em>Probability Theory: The Logic of Science</em></a>, a delightful book by <a href="http://en.wikipedia.org/wiki/Edwin_Thompson_Jaynes">E. T. Jaynes</a>.
You can read the <a href="http://bayes.wustl.edu/etj/prob/book.pdf">first three chapters online</a>.
The first chapter is especially rewarding; in it Jaynes builds the logic of “plausible reasoning” from the ground up.</p>
</div>
]]></summary>
</entry>

</feed>
