<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Blaine Buxton</title>
<link>https://blog.blainebuxton.net/</link>
<atom:link href="https://blog.blainebuxton.net/index.xml" rel="self" type="application/rss+xml"/>
<description>Musings on development</description>
<image>
<url>https://blog.blainebuxton.net/blaine_logo.png</url>
<title>Blaine Buxton</title>
<link>https://blog.blainebuxton.net/</link>
<height>82</height>
<width>144</width>
</image>
<generator>quarto-1.9.36</generator>
<lastBuildDate>Sun, 21 Apr 2024 04:00:00 GMT</lastBuildDate>
<item>
  <title>Implicit Interfaces in Python</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2024-04-21-implicit-interfaces/</link>
  <description><![CDATA[ 





<p>One of the ideas that I really like from <a href="https://go.dev/">Go</a> is <a href="https://go.dev/tour/methods/10">implicit interfaces</a>. It allows clients to document the exact usage of a wide object and constrain what parts to be used. The good news is that Python’s optional type system allows for implicit interfaces.</p>
<section id="example" class="level2">
<h2 class="anchored" data-anchor-id="example">Example</h2>
<p>The <a href="https://www.pygame.org/docs/ref/time.html#pygame.time.Clock">pygame.time.Clock</a> object has many methods and let’s say we want to document and constrain that we only use the <code>tick</code> method. If we keep the signature the same as the implementation, there is no need to cast and type checking will make sure we use no other methods.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SimClock(Protocol):</span>
<span id="cb1-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tick(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, framerate: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb1-3">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb1-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Wait for a tick to pass as defined by framerate. This is to keep the simulation running at a consistent rate.</span></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb1-6">        ...</span>
<span id="cb1-7"></span>
<span id="cb1-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Other code ...</span></span>
<span id="cb1-9"></span>
<span id="cb1-10">clock: SimClock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SimClock, pygame.time.Clock()</span>
<span id="cb1-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb1-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Processing code...</span></span>
<span id="cb1-13">    clock.tick(fps) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># this is good</span></span>
<span id="cb1-14">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># clock.get_time() &lt;- This will fail type checking</span></span></code></pre></div></div>
<p>If the method signature is not the same, then we must cast. The example below changes <code>tick</code> to accept an integer instead of a float and not caring about the return. Thus, being more restrictive. I feel casting is a typing code smell, so I stick with the signatures in the implementation. But, this can not be always avoided. As always there are no hard and fast rules.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SimClock(Protocol):</span>
<span id="cb2-2">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tick(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, framerate: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb2-3">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        Wait for a tick to pass as defined by framerate. This is to keep the simulation running at a consistent rate.</span></span>
<span id="cb2-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">        """</span></span>
<span id="cb2-6">        ...</span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Other code ...</span></span>
<span id="cb2-9"></span>
<span id="cb2-10">clock: SimClock <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> cast(SimClock, pygame.time.Clock()) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># CAST!</span></span>
<span id="cb2-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>:</span>
<span id="cb2-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Processing code...</span></span>
<span id="cb2-13">    clock.tick(fps) <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># same as before</span></span></code></pre></div></div>
</section>
<section id="why" class="level2">
<h2 class="anchored" data-anchor-id="why">Why?</h2>
<p>Why go through the trouble? We are tring to increase readability and help us focus on what the code is actually implementing. Reducing the surface area of an external object, helps with all of that. It means that someone new to the code doesn’t have to read through all of the methods in the library to know exactly which ones will be used in a glance. You can even add comments if none are available in the library to further reduce cognitive load.</p>


</section>

 ]]></description>
  <category>python</category>
  <guid>https://blog.blainebuxton.net/posts/2024-04-21-implicit-interfaces/</guid>
  <pubDate>Sun, 21 Apr 2024 04:00:00 GMT</pubDate>
</item>
<item>
  <title>PySpark Unit Testing</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2023-09-28-pyspark-testing/pyspark-testing.html</link>
  <description><![CDATA[ 





<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>One of the features that I love about PySpark is the data frame abstraction is agnostic about data sources and destinations. This allows unit testing data transformations without connecting to a database or file system. As a bonus data frames are immutable and each transformation returns a new one. This means we can test transformations on the data in bite-sized chunks.</p>
<p>All we need to do is create an in-memory data frame, perform a set of transformations, then check the data by executing an action. As an added bonus, the transformations can be tested without data. Given an input schema, the resulting output schema can be confirmed alone. No data needed. This allows us to make sure that our PySpark script fulfills its contract. The unit tests can verify preconditions and postconditions by comparing schemas.</p>
</section>
<section id="example" class="level2">
<h2 class="anchored" data-anchor-id="example">Example</h2>
<p>Let’s start with a simple example. Our dataset is a simple list of musicians with their bands and roles. It’s just enough to keep explanations clear.</p>
<div id="6d4895f4-8ae0-4e16-9f69-e86afface267" class="cell" data-execution_count="17">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pyspark.sql <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> SparkSession, DataFrame, Column</span>
<span id="cb1-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pyspark.sql.types <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sqlt</span>
<span id="cb1-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pyspark.sql.functions <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> sqlf</span></code></pre></div></div>
</div>
<div id="b7b59671-540e-4312-b4ab-5c2304bc0049" class="cell" data-execution_count="18">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1">spark <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SparkSession.builder.getOrCreate()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</div>
<div id="9d8568ed-5b99-4752-8b3f-42d9698f0685" class="cell" data-execution_count="19">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb3-1">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb3-2">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rob"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Halford"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Judas Priest"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb3-3">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cooper"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hollywood Vampires"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb3-4">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Steve"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Harris"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Iron Maiden"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bassist"</span>),</span>
<span id="cb3-5">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"James"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hetfield"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Metallica"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb3-6">    (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bernie"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Worrell"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Parliament"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Keyboardist"</span>),</span>
<span id="cb3-7">]</span>
<span id="cb3-8"></span>
<span id="cb3-9">schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sqlt.StructType(</span>
<span id="cb3-10">    [</span>
<span id="cb3-11">        sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first_name"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb3-12">        sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last_name"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb3-13">        sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb3-14">        sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"role"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb3-15">    ]</span>
<span id="cb3-16">)</span>
<span id="cb3-17"></span>
<span id="cb3-18">df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spark.createDataFrame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, schema<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schema)</span>
<span id="cb3-19">df.printSchema()</span>
<span id="cb3-20">df.show(truncate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>root
 |-- first_name: string (nullable = true)
 |-- last_name: string (nullable = true)
 |-- band: string (nullable = true)
 |-- role: string (nullable = true)

+----------+---------+------------------+-----------+
|first_name|last_name|band              |role       |
+----------+---------+------------------+-----------+
|Rob       |Halford  |Judas Priest      |Singer     |
|Alice     |Cooper   |Hollywood Vampires|Singer     |
|Steve     |Harris   |Iron Maiden       |Bassist    |
|James     |Hetfield |Metallica         |Singer     |
|Bernie    |Worrell  |Parliament        |Keyboardist|
+----------+---------+------------------+-----------+
</code></pre>
</div>
</div>
</section>
<section id="implement-transformations" class="level2">
<h2 class="anchored" data-anchor-id="implement-transformations">Implement Transformations</h2>
<p>Let’s create some transformation functions that we can use to test our data.</p>
<div id="8a28f291-b38b-4505-bec5-ce4372542e42" class="cell" data-execution_count="20">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> drop_unnecessary(df: DataFrame) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DataFrame:</span>
<span id="cb5-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb5-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Removed the role column</span></span>
<span id="cb5-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb5-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df.drop(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"role"</span>)</span>
<span id="cb5-6"></span>
<span id="cb5-7"></span>
<span id="cb5-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> only_singers(df: DataFrame) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DataFrame:</span>
<span id="cb5-9">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb5-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Filter out only the singers</span></span>
<span id="cb5-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb5-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df.where(sqlf.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"role"</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>)</span>
<span id="cb5-13"></span>
<span id="cb5-14"></span>
<span id="cb5-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> combine_names(first: Column, last: Column) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Column:</span>
<span id="cb5-16">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb5-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Take the first name and last name columns and create a single name structure</span></span>
<span id="cb5-18"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb5-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sqlf.struct(first.alias(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first"</span>), last.alias(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last"</span>))</span>
<span id="cb5-20"></span>
<span id="cb5-21"></span>
<span id="cb5-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fix_name(df: DataFrame) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DataFrame:</span>
<span id="cb5-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb5-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Fix names from two columns to one</span></span>
<span id="cb5-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb5-26">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> df.select(</span>
<span id="cb5-27">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>,</span>
<span id="cb5-28">        combine_names(sqlf.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first_name"</span>), sqlf.col(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last_name"</span>)).alias(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>),</span>
<span id="cb5-29">    )</span></code></pre></div></div>
</div>
</section>
<section id="run-transformations" class="level2">
<h2 class="anchored" data-anchor-id="run-transformations">Run Transformations</h2>
<p>Let’s run the transformations that we just implemented. The “transform” method on DataFrame allows us to call the transformations in sequence without having to create temporary variables. It also makes the code easier to read with less noise.</p>
<div id="b7f62d7d-43e7-4c44-b72b-8efb14471ae9" class="cell" data-execution_count="21">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Since data frames are lazy, we can filter out the singers after dropping the role column. Notice that</span></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">the code below runs and returns the correct answer.</span></span>
<span id="cb6-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb6-5">new_df <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> df.transform(drop_unnecessary).transform(only_singers).transform(fix_name)</span>
<span id="cb6-6">new_df.show()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>+------------------+-----------------+
|              band|             name|
+------------------+-----------------+
|      Judas Priest|   {Rob, Halford}|
|Hollywood Vampires|  {Alice, Cooper}|
|         Metallica|{James, Hetfield}|
+------------------+-----------------+
</code></pre>
</div>
</div>
</section>
<section id="tests" class="level2">
<h2 class="anchored" data-anchor-id="tests">Tests</h2>
<p>Now, let’s write some tests that verify the output schema for each transformation and that each transformation changes the input data as expected.</p>
<div id="c186ea09-b51b-4f90-af1d-d48d7f18bf88" class="cell" data-execution_count="30">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pytest</span>
<span id="cb8-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ipytest</span>
<span id="cb8-3"></span>
<span id="cb8-4">ipytest.autoconfig()</span>
<span id="cb8-5">ipytest.clean()</span>
<span id="cb8-6"></span>
<span id="cb8-7"></span>
<span id="cb8-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@pytest.fixture</span></span>
<span id="cb8-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> spark() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> SparkSession:</span>
<span id="cb8-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> SparkSession.builder.getOrCreate()</span>
<span id="cb8-11"></span>
<span id="cb8-12"></span>
<span id="cb8-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@pytest.fixture</span></span>
<span id="cb8-14"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> schema() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> sqlt.StructType:</span>
<span id="cb8-15">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb8-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Create the input schema to be used for tests</span></span>
<span id="cb8-17"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb8-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sqlt.StructType(</span>
<span id="cb8-19">        [</span>
<span id="cb8-20">            sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first_name"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb8-21">            sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last_name"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb8-22">            sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb8-23">            sqlt.StructField(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"role"</span>, sqlt.StringType(), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb8-24">        ]</span>
<span id="cb8-25">    )</span>
<span id="cb8-26"></span>
<span id="cb8-27"></span>
<span id="cb8-28"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@pytest.fixture</span></span>
<span id="cb8-29"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> data(spark: SparkSession, schema: sqlt.StructType) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> DataFrame:</span>
<span id="cb8-30">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb8-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Sample input data to use in tests</span></span>
<span id="cb8-32"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb8-33">    data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb8-34">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rob"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Halford"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Judas Priest"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb8-35">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alice"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cooper"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hollywood Vampires"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb8-36">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Steve"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Harris"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Iron Maiden"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bassist"</span>),</span>
<span id="cb8-37">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"James"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hetfield"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Metallica"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Singer"</span>),</span>
<span id="cb8-38">        (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bernie"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Worrell"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Parliament"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Keyboardist"</span>),</span>
<span id="cb8-39">    ]</span>
<span id="cb8-40">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> spark.createDataFrame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, schema<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schema)</span>
<span id="cb8-41"></span>
<span id="cb8-42"></span>
<span id="cb8-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Schema tests</span></span>
<span id="cb8-44"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_drop_unnecessary_schema(spark: SparkSession, schema: sqlt.StructType):</span>
<span id="cb8-45">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb8-46"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    This test verifies only the column names</span></span>
<span id="cb8-47"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb8-48">    empty <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spark.createDataFrame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[], schema<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schema)</span>
<span id="cb8-49">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> empty.transform(drop_unnecessary)</span>
<span id="cb8-50">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first_name"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last_name"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> result.columns</span>
<span id="cb8-51"></span>
<span id="cb8-52"></span>
<span id="cb8-53"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_only_singers_schema(spark: SparkSession, schema: sqlt.StructType):</span>
<span id="cb8-54">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb8-55"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    You can also verify the contract by comparing schema instances.</span></span>
<span id="cb8-56"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    In this case, the schemas should be the same.</span></span>
<span id="cb8-57"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb8-58">    empty <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spark.createDataFrame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[], schema<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schema)</span>
<span id="cb8-59">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> empty.transform(only_singers)</span>
<span id="cb8-60">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> result.schema <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> schema</span>
<span id="cb8-61"></span>
<span id="cb8-62"></span>
<span id="cb8-63"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_fix_name_schema(spark: SparkSession, schema: sqlt.StructType):</span>
<span id="cb8-64">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb8-65"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Schema can also be verified with a simple string</span></span>
<span id="cb8-66"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb8-67">    empty <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> spark.createDataFrame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[], schema<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schema)</span>
<span id="cb8-68">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> empty.transform(fix_name)</span>
<span id="cb8-69">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> result.columns</span>
<span id="cb8-70">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> (</span>
<span id="cb8-71">        result.schema[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>].simpleString() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name:struct&lt;first:string,last:string&gt;"</span></span>
<span id="cb8-72">    )</span>
<span id="cb8-73"></span>
<span id="cb8-74"></span>
<span id="cb8-75"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Data test</span></span>
<span id="cb8-76"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_end_to_end(spark: SparkSession, data: DataFrame):</span>
<span id="cb8-77">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb8-78">        data.transform(drop_unnecessary).transform(only_singers).transform(fix_name)</span>
<span id="cb8-79">    )</span>
<span id="cb8-80">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># call an action</span></span>
<span id="cb8-81">    output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> result.collect()</span>
<span id="cb8-82">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(output) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb8-83"></span>
<span id="cb8-84">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> output[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Judas Priest"</span></span>
<span id="cb8-85">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> output[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"first"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Rob"</span></span>
<span id="cb8-86">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> output[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"last"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Halford"</span></span>
<span id="cb8-87"></span>
<span id="cb8-88">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> output[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hollywood Vampires"</span></span>
<span id="cb8-89">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> output[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"band"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Metallica"</span></span>
<span id="cb8-90"></span>
<span id="cb8-91"></span>
<span id="cb8-92">ipytest.run()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">                                                                                         [100%]</span>

<span class="ansi-green-fg ansi-bold">4 passed</span><span class="ansi-green-fg"> in 0.20s</span>
</pre>
</div>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>I hope this gave you some ideas on how to test the transformations in your own pipelines. It’s helped me simplify my tests and verify edge cases more easily. It’s caught many errors sooner without doing a full run of the script or using all of the data. It also makes debugging quicker since the tests are smaller.</p>


</section>

 ]]></description>
  <category>python</category>
  <category>pyspark</category>
  <guid>https://blog.blainebuxton.net/posts/2023-09-28-pyspark-testing/pyspark-testing.html</guid>
  <pubDate>Thu, 28 Sep 2023 04:00:00 GMT</pubDate>
</item>
<item>
  <title>Tower Of Hanoi Solver</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2023-08-27-julia-hanoi/blog.html</link>
  <description><![CDATA[ 





<section id="experimenting-with-julia" class="level2">
<h2 class="anchored" data-anchor-id="experimenting-with-julia">Experimenting with Julia</h2>
<p>I’ve always loved the <a href="https://en.wikipedia.org/wiki/Tower_of_Hanoi">Towers of Hanoi</a> ever since I was introduced to it as a kid by chance. I thought it would be perfect to write a solver using Julia to learn it. This is my first project using Julia and I found it enjoyable. I’m still learning the ropes so to speak. For future projects, I would like to stick to a more strict functional style of programming for the solvers and use the naming convention of using “!” postfix to denote stateful functions.</p>
<p>Julia initially picqued my interest with its take on types, multiple dispatch, and no objects. It forces you away from generic types which can make for more readable code. The typing system gets you thinking about the problem differently and how you can use types to better document intent without relying on problematic “if” statements. The packaging system, REPL, and jupyter integration make developing and trying out packages easy. There is a learning curve and some frustrations with how code is loaded that gets in the way of development initially. But, nothing a Google search can’t fix. All part of learning something new and a different take on programming.</p>
<p>The lack of encapsulation is worrisome for large projects. I have the same issue with Python, but documentation and a few team guidelines help. It’s always good to have strict enforcement though. Minimizing mutable state structures and documenting the functions that mutate to use goes a long way. All in all a minor quibble.</p>
<p>Overall, I enjoyed coding in Julia and plan to implement more projects with it. The type system is the intriguing piece and I did some experiements in the code to try to push my understanding. Look at the implementation of <a href="https://github.com/btbuxton/TowerOfHanoi.jl/blob/44c2530a5da80ee486fbc0eb9e7b9f2970e92349/src/TowerOfHanoi.jl#L99">moves in the domain</a> for an example. This was a quick weekend project and comments are minimal. There are several emergent design patterns in Julia that I would love to explore as well like the <a href="https://github.com/JuliaLang/julia/issues/2345#issuecomment-54537633">Holy Trait Pattern</a> and work more through the excellent <a href="https://github.com/PacktPublishing/Hands-on-Design-Patterns-and-Best-Practices-with-Julia/tree/master">“Hands on Design Patterns and Best Practices with Julia” book</a>.</p>
<p>If you would like to follow along, I have provided the source for the <a href="https://github.com/btbuxton/TowerOfHanoi.jl/blob/main/src/TowerOfHanoi.jl">domain</a> along with the <a href="https://github.com/btbuxton/TowerOfHanoi.jl/blob/main/test/runtests.jl">tests</a>. I implemented two solvers and provided the source for the <a href="https://github.com/btbuxton/TowerOfHanoi.jl/blob/main/src/naive_solver.jl">naive version</a> and the <a href="https://github.com/btbuxton/TowerOfHanoi.jl/blob/main/src/heuristic_solver.jl">A* with heurstic version</a>.</p>
<div id="292f077a-a3b8-46fc-b1b3-52b872aa922f" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Pkg</span></span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Pkg</span>.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">activate</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<div class="ansi-escaped-output">
<pre><span class="ansi-green-fg ansi-bold">  Activating</span> project at `~/Documents/julia/TowerOfHanoi`
</pre>
</div>
</div>
</div>
</section>
<section id="naive" class="level2">
<h2 class="anchored" data-anchor-id="naive">Naive</h2>
<p>A sample run with 4 discs is shown below. Keep scrolling for the A* version.</p>
<div id="8d5dd93a-b4d3-416e-a828-7f1441253969" class="cell" data-scrolled="true" data-execution_count="17">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">include</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"src/naive_solver.jl"</span>)</span></code></pre></div></div>
</div>
<div class="cell-output cell-output-stdout" style="max-height: 250px;overflow-y: scroll"><pre>Moves to solve: 79
    ***                          
   *****                         
  *******                        
 *********                       
heurstic value: 16
Move from 1 to 3
                                 
   *****                         
  *******                        
 *********                ***    
heurstic value: 14
Move from 3 to 2
                                 
   *****                         
  *******                        
 *********     ***               
heurstic value: 14
Move from 1 to 3
                                 
                                 
  *******                        
 *********     ***       *****   
heurstic value: 14
Move from 2 to 3
                                 
                                 
  *******                 ***    
 *********               *****   
heurstic value: 16
Move from 3 to 1
                                 
    ***                          
  *******                        
 *********               *****   
heurstic value: 15
Move from 3 to 2
                                 
    ***                          
  *******                        
 *********    *****              
heurstic value: 15
Move from 1 to 3
                                 
                                 
  *******                        
 *********    *****       ***    
heurstic value: 14
Move from 3 to 2
                                 
                                 
  *******      ***               
 *********    *****              
heurstic value: 16
Move from 1 to 3
                                 
                                 
               ***               
 *********    *****     *******  
heurstic value: 18
Move from 2 to 3
                                 
                                 
                          ***    
 *********    *****     *******  
heurstic value: 18
Move from 3 to 1
                                 
                                 
    ***                          
 *********    *****     *******  
heurstic value: 16
Move from 2 to 3
                                 
                                 
    ***                  *****   
 *********              *******  
heurstic value: 18
Move from 1 to 3
                                 
                          ***    
                         *****   
 *********              *******  
heurstic value: 22
Move from 3 to 2
                                 
                                 
                         *****   
 *********     ***      *******  
heurstic value: 18
Move from 3 to 1
                                 
                                 
   *****                         
 *********     ***      *******  
heurstic value: 15
Move from 2 to 3
                                 
                                 
   *****                  ***    
 *********              *******  
heurstic value: 17
Move from 3 to 1
                                 
    ***                          
   *****                         
 *********              *******  
heurstic value: 16
Move from 3 to 2
                                 
    ***                          
   *****                         
 *********   *******             
heurstic value: 16
Move from 1 to 3
                                 
                                 
   *****                         
 *********   *******      ***    
heurstic value: 15
Move from 3 to 2
                                 
                                 
   *****       ***               
 *********   *******             
heurstic value: 17
Move from 1 to 3
                                 
                                 
               ***               
 *********   *******     *****   
heurstic value: 18
Move from 2 to 3
                                 
                                 
                          ***    
 *********   *******     *****   
heurstic value: 18
Move from 3 to 1
                                 
                                 
    ***                          
 *********   *******     *****   
heurstic value: 16
Move from 3 to 2
                                 
                                 
    ***       *****              
 *********   *******             
heurstic value: 18
Move from 1 to 3
                                 
                                 
              *****              
 *********   *******      ***    
heurstic value: 18
Move from 3 to 2
                                 
               ***               
              *****              
 *********   *******             
heurstic value: 22
Move from 1 to 3
                                 
               ***               
              *****              
             *******   ********* 
heurstic value: 26
Move from 2 to 3
                                 
                                 
              *****       ***    
             *******   ********* 
heurstic value: 24
Move from 3 to 1
                                 
                                 
              *****              
    ***      *******   ********* 
heurstic value: 21
Move from 2 to 3
                                 
                                 
                         *****   
    ***      *******   ********* 
heurstic value: 21
Move from 1 to 3
                                 
                          ***    
                         *****   
             *******   ********* 
heurstic value: 26
Move from 3 to 2
                                 
                                 
               ***       *****   
             *******   ********* 
heurstic value: 24
Move from 3 to 1
                                 
                                 
               ***               
   *****     *******   ********* 
heurstic value: 20
Move from 2 to 3
                                 
                                 
                          ***    
   *****     *******   ********* 
heurstic value: 20
Move from 3 to 1
                                 
                                 
    ***                          
   *****     *******   ********* 
heurstic value: 18
Move from 2 to 3
                                 
                                 
    ***                 *******  
   *****               ********* 
heurstic value: 20
Move from 1 to 3
                                 
                          ***    
                        *******  
   *****               ********* 
heurstic value: 24
Move from 3 to 2
                                 
                                 
                        *******  
   *****       ***     ********* 
heurstic value: 20
Move from 1 to 3
                                 
                         *****   
                        *******  
               ***     ********* 
heurstic value: 26
Move from 2 to 3
                          ***    
                         *****   
                        *******  
                       ********* 
heurstic value: 32
Move from 3 to 1
                                 
                         *****   
                        *******  
    ***                ********* 
heurstic value: 25
Move from 3 to 2
                                 
                                 
                        *******  
    ***       *****    ********* 
heurstic value: 21
Move from 1 to 3
                                 
                          ***    
                        *******  
              *****    ********* 
heurstic value: 26
Move from 3 to 2
                                 
                                 
               ***      *******  
              *****    ********* 
heurstic value: 24
Move from 3 to 1
                                 
                                 
               ***               
  *******     *****    ********* 
heurstic value: 19
Move from 2 to 3
                                 
                                 
                          ***    
  *******     *****    ********* 
heurstic value: 19
Move from 3 to 1
                                 
                                 
    ***                          
  *******     *****    ********* 
heurstic value: 17
Move from 2 to 3
                                 
                                 
    ***                  *****   
  *******              ********* 
heurstic value: 19
Move from 1 to 3
                                 
                          ***    
                         *****   
  *******              ********* 
heurstic value: 23
Move from 3 to 2
                                 
                                 
                         *****   
  *******      ***     ********* 
heurstic value: 19
Move from 3 to 1
                                 
                                 
   *****                         
  *******      ***     ********* 
heurstic value: 16
Move from 2 to 3
                                 
                                 
   *****                  ***    
  *******              ********* 
heurstic value: 18
Move from 3 to 1
                                 
    ***                          
   *****                         
  *******              ********* 
heurstic value: 17
Move from 3 to 2
                                 
    ***                          
   *****                         
  *******   *********            
heurstic value: 17
Move from 1 to 3
                                 
                                 
   *****                         
  *******   *********     ***    
heurstic value: 16
Move from 3 to 2
                                 
                                 
   *****       ***               
  *******   *********            
heurstic value: 18
Move from 1 to 3
                                 
                                 
               ***               
  *******   *********    *****   
heurstic value: 19
Move from 2 to 3
                                 
                                 
                          ***    
  *******   *********    *****   
heurstic value: 19
Move from 3 to 1
                                 
                                 
    ***                          
  *******   *********    *****   
heurstic value: 17
Move from 3 to 2
                                 
                                 
    ***       *****              
  *******   *********            
heurstic value: 19
Move from 1 to 3
                                 
                                 
              *****              
  *******   *********     ***    
heurstic value: 19
Move from 3 to 2
                                 
               ***               
              *****              
  *******   *********            
heurstic value: 23
Move from 1 to 3
                                 
               ***               
              *****              
            *********   *******  
heurstic value: 26
Move from 2 to 3
                                 
                                 
              *****       ***    
            *********   *******  
heurstic value: 24
Move from 3 to 1
                                 
                                 
              *****              
    ***     *********   *******  
heurstic value: 21
Move from 2 to 3
                                 
                                 
                         *****   
    ***     *********   *******  
heurstic value: 21
Move from 1 to 3
                                 
                          ***    
                         *****   
            *********   *******  
heurstic value: 26
Move from 3 to 2
                                 
                                 
               ***       *****   
            *********   *******  
heurstic value: 24
Move from 3 to 1
                                 
                                 
               ***               
   *****    *********   *******  
heurstic value: 20
Move from 2 to 3
                                 
                                 
                          ***    
   *****    *********   *******  
heurstic value: 20
Move from 3 to 1
                                 
                                 
    ***                          
   *****    *********   *******  
heurstic value: 18
Move from 3 to 2
                                 
                                 
    ***      *******             
   *****    *********            
heurstic value: 20
Move from 1 to 3
                                 
                                 
             *******             
   *****    *********     ***    
heurstic value: 20
Move from 3 to 2
                                 
               ***               
             *******             
   *****    *********            
heurstic value: 24
Move from 1 to 3
                                 
               ***               
             *******             
            *********    *****   
heurstic value: 26
Move from 2 to 3
                                 
                                 
             *******      ***    
            *********    *****   
heurstic value: 24
Move from 3 to 1
                                 
                                 
             *******             
    ***     *********    *****   
heurstic value: 21
Move from 3 to 2
                                 
              *****              
             *******             
    ***     *********            
heurstic value: 25
Move from 1 to 2
final:
               ***               
              *****              
             *******             
            *********            
</pre></div>
</section>
<section id="a-heuristic" class="level2">
<h2 class="anchored" data-anchor-id="a-heuristic"><a href="https://en.wikipedia.org/wiki/A*_search_algorithm">A*</a> Heuristic</h2>
<p>I implemented the A* algorigithm and used the following heurstic function:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">heuristic</span>(initial<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Tower</span>, state<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Tower</span>)</span>
<span id="cb3-2">    disc_cache <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">Dict</span>()</span>
<span id="cb3-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (r, rod) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(initial.rods)</span>
<span id="cb3-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (d, disc) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(rod.discs)</span>
<span id="cb3-5">            disc_cache[disc]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(r,d)</span>
<span id="cb3-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-8">    num_discs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(disc_cache)</span>
<span id="cb3-9">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb3-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (r, rod) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(state.rods)</span>
<span id="cb3-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (d, disc) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enumerate</span>(rod.discs)</span>
<span id="cb3-12">            (ir, id) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> disc_cache[disc]</span>
<span id="cb3-13">            rod_diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(ir <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> r) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> ? <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb3-14">            disc_diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> num_discs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">abs</span>(id <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> d)</span>
<span id="cb3-15">            result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> rod_diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> disc_diff</span>
<span id="cb3-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-17">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span>
<span id="cb3-18">    result</span>
<span id="cb3-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">end</span></span></code></pre></div></div>
<p>It simply sums how many discs are not in the goal state from the given intial. Thus, a higher score is closer to the goal and the A* algorithm maximizes search for it.</p>
<p>A sample run with 4 discs is shown below.</p>
<p>The naive solver took 79 moves and the A* solver took 21 moves. A huge improvement in finding the solution. This was a great project to learn the basics of Julia.</p>
<div id="38596379-3fff-48fd-8a7e-c56a9bdb0fea" class="cell" data-scrolled="true" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource julia number-lines code-with-copy"><code class="sourceCode julia"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">include</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"src/heuristic_solver.jl"</span>)</span></code></pre></div></div>
</div>
<div class="cell-output cell-output-stdout" style="max-height: 250px;overflow-y: scroll">
<pre>Number of moves: 21
    ***                          
   *****                         
  *******                        
 *********                       
heurstic value: 16
Move from 1 to 2
                                 
   *****                         
  *******                        
 *********     ***               
heurstic value: 14
Move from 2 to 3
                                 
   *****                         
  *******                        
 *********                ***    
heurstic value: 14
Move from 1 to 2
                                 
                                 
  *******                        
 *********    *****       ***    
heurstic value: 14
Move from 3 to 2
                                 
                                 
  *******      ***               
 *********    *****              
heurstic value: 16
Move from 1 to 3
                                 
                                 
               ***               
 *********    *****     *******  
heurstic value: 18
Move from 2 to 3
                                 
                                 
                          ***    
 *********    *****     *******  
heurstic value: 18
Move from 3 to 1
                                 
                                 
    ***                          
 *********    *****     *******  
heurstic value: 16
Move from 2 to 3
                                 
                                 
    ***                  *****   
 *********              *******  
heurstic value: 18
Move from 1 to 3
                                 
                          ***    
                         *****   
 *********              *******  
heurstic value: 22
Move from 1 to 2
                                 
                          ***    
                         *****   
            *********   *******  
heurstic value: 26
Move from 3 to 2
                                 
                                 
               ***       *****   
            *********   *******  
heurstic value: 24
Move from 3 to 1
                                 
                                 
               ***               
   *****    *********   *******  
heurstic value: 20
Move from 2 to 3
                                 
                                 
                          ***    
   *****    *********   *******  
heurstic value: 20
Move from 3 to 1
                                 
                                 
    ***                          
   *****    *********   *******  
heurstic value: 18
Move from 3 to 2
                                 
                                 
    ***      *******             
   *****    *********            
heurstic value: 20
Move from 1 to 2
                                 
               ***               
             *******             
   *****    *********            
heurstic value: 24
Move from 1 to 3
                                 
               ***               
             *******             
            *********    *****   
heurstic value: 26
Move from 2 to 3
                                 
                                 
             *******      ***    
            *********    *****   
heurstic value: 24
Move from 3 to 1
                                 
                                 
             *******             
    ***     *********    *****   
heurstic value: 21
Move from 3 to 2
                                 
              *****              
             *******             
    ***     *********            
heurstic value: 25
Move from 1 to 2
               ***               
              *****              
             *******             
            *********            
</pre>
</div>


</section>

 ]]></description>
  <category>julia</category>
  <guid>https://blog.blainebuxton.net/posts/2023-08-27-julia-hanoi/blog.html</guid>
  <pubDate>Sun, 27 Aug 2023 04:00:00 GMT</pubDate>
</item>
<item>
  <title>Einstein Puzzle Solver</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2023-08-20-einstein-puzzle/einstein_blog.html</link>
  <description><![CDATA[ 





<section id="puzzle-and-idea" class="level2">
<h2 class="anchored" data-anchor-id="puzzle-and-idea">Puzzle and idea</h2>
<p>I love number puzzles and bought <a href="https://professorpuzzle.com/products/puzzles/einstein/number-puzzle/">one inspired by Einstein</a> on holiday recently. The idea is simple. There’s 16 tiles with numbers that can be placed in a 4x4 grid. The goal is for each row, column, and diagonal to sum up to 264. The tiles can be flipped so if tile has “66” imprinted on it, it can also represent “99”.</p>
<p>Here’s an example layout of tiles.</p>
<pre><code>---------------------
| 18 | 89 | 98 | 61 |
-----+----+----+-----
| 68 | 91 | 88 | 16 |
-----+----+----+-----
| 81 | 19 | 66 | 99 |
-----+----+----+-----
| 96 | 69 | 11 | 86 |
---------------------</code></pre>
<p>Things quickly escalated when I got the idea to write a solver that would use genetic programming concepts. The algorithm is simple. Start with a population of all scrambled states, then pick the best layouts out of the population. Exchange a few tiles in each of samples from the the best to create a new population along with a few new scrambled states. Repeat until we get a layout of tiles that satisfies the goal.</p>
</section>
<section id="puzzle-domain" class="level2">
<h2 class="anchored" data-anchor-id="puzzle-domain">Puzzle Domain</h2>
<p>First things first. A domain to model the puzzle was needed.</p>
<div id="cd02a572-59fe-4ffa-9f00-82ffde6d4682" class="cell" data-execution_count="9">
<details class="code-fold">
<summary>Source</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> itertools</span>
<span id="cb2-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb2-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Iterable, Sequence</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Type to represent the layout of tiles</span></span>
<span id="cb2-6">State <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]</span>
<span id="cb2-7"></span>
<span id="cb2-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Map the values of a number when flipped</span></span>
<span id="cb2-9">FLIP_MAP: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-10">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb2-11">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>,</span>
<span id="cb2-12">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>,</span>
<span id="cb2-13">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>,</span>
<span id="cb2-14">}</span>
<span id="cb2-15"></span>
<span id="cb2-16"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># All the tiles represented</span></span>
<span id="cb2-17">ALL_TILES: State <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [</span>
<span id="cb2-18">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>,</span>
<span id="cb2-19">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>,</span>
<span id="cb2-20">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>,</span>
<span id="cb2-21">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>,</span>
<span id="cb2-22">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>,</span>
<span id="cb2-23">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>,</span>
<span id="cb2-24">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>,</span>
<span id="cb2-25">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>,</span>
<span id="cb2-26">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>,</span>
<span id="cb2-27">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>,</span>
<span id="cb2-28">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>,</span>
<span id="cb2-29">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>,</span>
<span id="cb2-30">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>,</span>
<span id="cb2-31">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>,</span>
<span id="cb2-32">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>,</span>
<span id="cb2-33">    <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>,</span>
<span id="cb2-34">]</span>
<span id="cb2-35"></span>
<span id="cb2-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The goal that each row, column, and diagonal should sum up to</span></span>
<span id="cb2-37">GOAL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">264</span></span>
<span id="cb2-38"></span>
<span id="cb2-39"></span>
<span id="cb2-40"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> flip(tile: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, flip_map: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FLIP_MAP) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>:</span>
<span id="cb2-41">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Take a tile and flip it. So, 89 will become 68.</span></span>
<span id="cb2-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Calling it twice should return the original tile. 89-&gt;68-&gt;89</span></span>
<span id="cb2-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-45">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> tile <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> tile <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb2-46">    ones <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tile <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb2-47">    tens <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tile <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span>
<span id="cb2-48">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> flip_map[ones] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> flip_map[tens]</span>
<span id="cb2-49"></span>
<span id="cb2-50"></span>
<span id="cb2-51"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_rows(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]:</span>
<span id="cb2-52">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Return the sum of all rows</span></span>
<span id="cb2-54"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-55">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>]), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>]), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>])]</span>
<span id="cb2-56"></span>
<span id="cb2-57"></span>
<span id="cb2-58"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_columns(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]:</span>
<span id="cb2-59">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-60"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Return the sum of all columns</span></span>
<span id="cb2-61"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-62">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [</span>
<span id="cb2-63">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(tiles) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>),</span>
<span id="cb2-64">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(tiles) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb2-65">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(tiles) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb2-66">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(tiles) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>),</span>
<span id="cb2-67">    ]</span>
<span id="cb2-68"></span>
<span id="cb2-69"></span>
<span id="cb2-70"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_diagonals(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]:</span>
<span id="cb2-71">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-72"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Return the sum of the two diagonals</span></span>
<span id="cb2-73"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-74">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [</span>
<span id="cb2-75">        tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>],</span>
<span id="cb2-76">        tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> tiles[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>],</span>
<span id="cb2-77">    ]</span>
<span id="cb2-78"></span>
<span id="cb2-79"></span>
<span id="cb2-80"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> score_iter(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Iterable[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]:</span>
<span id="cb2-81">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb2-82"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Return a score for each row, column, and diagonal.</span></span>
<span id="cb2-83"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    The score is the distance away from the goal.</span></span>
<span id="cb2-84"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb2-85">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (</span>
<span id="cb2-86">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">abs</span>(each <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> GOAL)</span>
<span id="cb2-87">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> itertools.chain(</span>
<span id="cb2-88">            add_rows(tiles), add_columns(tiles), add_diagonals(tiles)</span>
<span id="cb2-89">        )</span>
<span id="cb2-90">    )</span>
<span id="cb2-91"></span>
<span id="cb2-92"></span>
<span id="cb2-93"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> score(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb2-94">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Return a sum of how far away from goal for each row, column, and diagonal. This score is divided by the goal."</span></span>
<span id="cb2-95">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(GOAL) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> score_iter(tiles))</span>
<span id="cb2-96"></span>
<span id="cb2-97"></span>
<span id="cb2-98"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> score_breakdown(tiles: State) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>]:</span>
<span id="cb2-99">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Return a list of all the scores"</span></span>
<span id="cb2-100">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(score_iter(tiles))</span>
<span id="cb2-101"></span>
<span id="cb2-102"></span>
<span id="cb2-103"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> chance(probability: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span>:</span>
<span id="cb2-104">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Return True with probability between 1 and 0"</span></span>
<span id="cb2-105">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> random.random() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> probability</span>
<span id="cb2-106"></span>
<span id="cb2-107"></span>
<span id="cb2-108"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> exchange(</span>
<span id="cb2-109">    tiles: State,</span>
<span id="cb2-110">    probability_to_flip: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>,</span>
<span id="cb2-111">    probability_to_exchange: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.95</span>,</span>
<span id="cb2-112">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> State:</span>
<span id="cb2-113">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Return a new state of tiles after exchanging two and possibly flipping either"</span></span>
<span id="cb2-114">    choices <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.sample(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tiles)), k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb2-115">    new_tiles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tiles.copy()</span>
<span id="cb2-116">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> index <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> choices:</span>
<span id="cb2-117">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> chance(probability_to_flip):</span>
<span id="cb2-118">            new_tiles[index] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> flip(new_tiles[index])</span>
<span id="cb2-119">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> chance(probability_to_exchange):</span>
<span id="cb2-120">        new_tiles[choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]], new_tiles[choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb2-121">            new_tiles[choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]],</span>
<span id="cb2-122">            new_tiles[choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]],</span>
<span id="cb2-123">        )</span>
<span id="cb2-124">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> new_tiles</span>
<span id="cb2-125"></span>
<span id="cb2-126"></span>
<span id="cb2-127"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> scramble(tiles: State, probability_to_flip: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> State:</span>
<span id="cb2-128">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Scramble all of the tiles"</span></span>
<span id="cb2-129">    result <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.sample(tiles, k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(tiles))</span>
<span id="cb2-130">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [flip(each) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> chance(probability_to_flip) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> each <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> result]</span></code></pre></div></div>
</details>
</div>
</section>
<section id="domain-tests" class="level2">
<h2 class="anchored" data-anchor-id="domain-tests">Domain Tests</h2>
<p>To make sure the domain is correct, some tests were needed.</p>
<div id="78b4271d-217b-42a9-b321-987b8905a400" class="cell" data-execution_count="2">
<details class="code-fold">
<summary>Source</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ipytest</span>
<span id="cb3-2"></span>
<span id="cb3-3">ipytest.autoconfig()</span>
<span id="cb3-4">ipytest.clean()</span>
<span id="cb3-5"></span>
<span id="cb3-6"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb3-7"></span>
<span id="cb3-8"></span>
<span id="cb3-9"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_flip():</span>
<span id="cb3-10">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> assert_flip(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, expected: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>):</span>
<span id="cb3-11">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> flip(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> expected</span>
<span id="cb3-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> flip(expected) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">input</span></span>
<span id="cb3-13"></span>
<span id="cb3-14">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>)</span>
<span id="cb3-15">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>)</span>
<span id="cb3-16">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>)</span>
<span id="cb3-17">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>)</span>
<span id="cb3-18">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>)</span>
<span id="cb3-19">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>)</span>
<span id="cb3-20">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>)</span>
<span id="cb3-21">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>)</span>
<span id="cb3-22">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>)</span>
<span id="cb3-23">    assert_flip(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>)</span>
<span id="cb3-24"></span>
<span id="cb3-25"></span>
<span id="cb3-26"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_add_rows():</span>
<span id="cb3-27">    tiles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>]</span>
<span id="cb3-28">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_rows(tiles)</span>
<span id="cb3-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">26</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">58</span>]</span>
<span id="cb3-30"></span>
<span id="cb3-31"></span>
<span id="cb3-32"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_add_columns():</span>
<span id="cb3-33">    tiles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>]</span>
<span id="cb3-34">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_columns(tiles)</span>
<span id="cb3-35">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">36</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>]</span>
<span id="cb3-36"></span>
<span id="cb3-37"></span>
<span id="cb3-38"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_add_diagonals():</span>
<span id="cb3-39">    tiles <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">14</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>]</span>
<span id="cb3-40">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> add_diagonals(tiles)</span>
<span id="cb3-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">13</span>]</span>
<span id="cb3-42"></span>
<span id="cb3-43"></span>
<span id="cb3-44"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_score():</span>
<span id="cb3-45">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> score(ALL_TILES)</span>
<span id="cb3-46">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> math.isclose(actual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.708</span>, abs_tol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb3-47"></span>
<span id="cb3-48"></span>
<span id="cb3-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_solution():</span>
<span id="cb3-50">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> score([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>])</span>
<span id="cb3-51">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> math.isclose(actual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, abs_tol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb3-52"></span>
<span id="cb3-53"></span>
<span id="cb3-54"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_solution_another():</span>
<span id="cb3-55">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> score([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>])</span>
<span id="cb3-56">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> math.isclose(actual, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, abs_tol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb3-57"></span>
<span id="cb3-58"></span>
<span id="cb3-59"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_score_breakdown():</span>
<span id="cb3-60">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> score_breakdown(ALL_TILES)</span>
<span id="cb3-61">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">94</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">196</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">127</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">83</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">52</span>]</span>
<span id="cb3-62"></span>
<span id="cb3-63"></span>
<span id="cb3-64"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_sum():</span>
<span id="cb3-65">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Example to show sum of four tiles"</span></span>
<span id="cb3-66">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">264</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>])</span>
<span id="cb3-67"></span>
<span id="cb3-68"></span>
<span id="cb3-69">ipytest.run()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</details>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">                                                                                    [100%]</span>

<span class="ansi-green-fg ansi-bold">9 passed</span><span class="ansi-green-fg"> in 0.01s</span>
</pre>
</div>
</div>
</div>
</section>
<section id="genetic-programming-inspired-solution" class="level2">
<h2 class="anchored" data-anchor-id="genetic-programming-inspired-solution">Genetic Programming Inspired Solution</h2>
<p>The implementation creates a generation of tile layouts for each iteration until a layout is found that sums up to 264 across each row, column, and diagonal. There are few hyper parameters that were tweaked by hand while researching. The most important provided are what percentage of the top population to keep for mutations and how many new layouts to add. Finally, probabilities can be changed for the chances of flipping a tile in a mutation and if the tiles will be exchanged. Using 10% of the top tile layouts seemed to work the best, while generating a new population that is 90% of the original size by sampling with replacement mutating each. Finally, adding new scrambled layouts for the remaining 10%. Repeat until a solution is found.</p>
<p>It’s not perfect and it can get stuck in local minima. But, it is able find a solution in most cases in under 100,000 generations. Further research is needed for improvement.</p>
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div id="fig-population" class="quarto-float quarto-figure quarto-figure-center anchored">
<figure class="quarto-float quarto-float-fig figure">
<div aria-describedby="fig-population-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
<div>
<svg width="672" height="480" viewbox="0.00 0.00 388.58 113.80" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" style="; max-width: none; max-height: none">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 109.8)">
<title>g</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-109.8 384.58,-109.8 384.58,4 -4,4"></polygon>
<!-- node0 -->
<g id="node1" class="node">
<title>node0</title>
<polygon fill="none" stroke="black" points="0,-30.7 0,-80.3 70.05,-80.3 70.05,-30.7 0,-30.7"></polygon>
<text text-anchor="middle" x="35.03" y="-63.7" font-family="Times,serif" font-size="14.00">Best 10%</text>
<polyline fill="none" stroke="black" points="0,-55.5 70.05,-55.5 "></polyline>
<text text-anchor="middle" x="35.03" y="-38.9" font-family="Times,serif" font-size="14.00">Rest 90%</text>
</g>
<!-- node1 -->
<g id="node2" class="node">
<title>node1</title>
<polygon fill="none" stroke="black" points="106.05,-55.7 106.05,-105.3 380.58,-105.3 380.58,-55.7 106.05,-55.7"></polygon>
<text text-anchor="middle" x="243.32" y="-88.7" font-family="Times,serif" font-size="14.00">Sample with Replacement and Exchange 90%</text>
<polyline fill="none" stroke="black" points="106.05,-80.5 380.58,-80.5 "></polyline>
<text text-anchor="middle" x="243.32" y="-63.9" font-family="Times,serif" font-size="14.00">New Population (Random Shuffle) 10%</text>
</g>
<!-- node0&#45;&gt;node1 -->
<g id="0" class="edge">
<title>node0:f0-&gt;node1:f0</title>
<path fill="none" stroke="black" d="M70.05,-67.5C85.42,-67.5 86.82,-83.07 96.3,-89.63"></path>
<polygon fill="black" stroke="black" points="95.47,-93.04 106.05,-92.5 97.45,-86.32 95.47,-93.04"></polygon>
</g>
<!-- node2 -->
<g id="node3" class="node">
<title>node2</title>
<polygon fill="none" stroke="black" points="213.55,-0.5 213.55,-36.5 273.08,-36.5 273.08,-0.5 213.55,-0.5"></polygon>
<text text-anchor="middle" x="243.32" y="-14.4" font-family="Times,serif" font-size="14.00">Discard</text>
</g>
<!-- node0&#45;&gt;node2 -->
<g id="1" class="edge">
<title>node0:f1-&gt;node2:f0</title>
<path fill="none" stroke="black" d="M70.05,-43.5C116.25,-43.5 168.67,-34.69 203.63,-27.53"></path>
<polygon fill="black" stroke="black" points="204.39,-30.94 213.46,-25.46 202.95,-24.09 204.39,-30.94"></polygon>
</g>
</g>
</svg>
</div>
</div>
<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-population-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
Figure&nbsp;1: How New Generations Are Created.
</figcaption>
</figure>
</div>
</div>
</div>
<div id="bd65c4d6-2a19-4e27-9afb-ef5e82c0c0ef" class="cell" data-scrolled="true" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dataclasses <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> dataclass</span>
<span id="cb4-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> typing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Callable, Optional</span>
<span id="cb4-5"></span>
<span id="cb4-6"></span>
<span id="cb4-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> initial_pop(tiles: State <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ALL_TILES, size: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>]]:</span>
<span id="cb4-8">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Create a population of size of scrambled tiles"</span></span>
<span id="cb4-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [scramble(tiles) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(size)]</span>
<span id="cb4-10"></span>
<span id="cb4-11"></span>
<span id="cb4-12"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sample_pop_best(pop: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[State], best: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[State]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>[State]:</span>
<span id="cb4-13">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb4-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Sample with replacement to create a new population of the best and add a population of new fully scrambled tiles.</span></span>
<span id="cb4-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb4-16">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> [</span>
<span id="cb4-17">        exchange(each) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> random.choices(best, k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pop) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(best))</span>
<span id="cb4-18">    ] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> initial_pop(size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(best))</span>
<span id="cb4-19"></span>
<span id="cb4-20"></span>
<span id="cb4-21"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span>(frozen<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb4-22"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Progress:</span>
<span id="cb4-23">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb4-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Simple holder for progress</span></span>
<span id="cb4-25"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb4-26"></span>
<span id="cb4-27">    generation: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span></span>
<span id="cb4-28">    mean_score: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb4-29">    best_score: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span></span>
<span id="cb4-30">    best_thus_far: State</span>
<span id="cb4-31"></span>
<span id="cb4-32"></span>
<span id="cb4-33"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> run(</span>
<span id="cb4-34">    keep_percent: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.1</span>,</span>
<span id="cb4-35">    progress_update: Callable[[Progress], <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> progress: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,</span>
<span id="cb4-36">    max_generations: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100_000</span>,</span>
<span id="cb4-37">) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> Optional[State]:</span>
<span id="cb4-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb4-39"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Simple solution using genetic programming concepts.</span></span>
<span id="cb4-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb4-41">    pop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> initial_pop()</span>
<span id="cb4-42">    generation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-43">    to_keep <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(pop) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> keep_percent)</span>
<span id="cb4-44">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> generation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;=</span> max_generations:</span>
<span id="cb4-45">        scores <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(score, pop))</span>
<span id="cb4-46">        top_best <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sorted</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(scores, pop), key<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> each: each[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])[:to_keep]</span>
<span id="cb4-47">        best_score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> top_best[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb4-48">        best <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> top_best[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]</span>
<span id="cb4-49">        mean_score <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(each[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> top_best) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(top_best)</span>
<span id="cb4-50">        progress <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Progress(generation, mean_score, mean_score, best)</span>
<span id="cb4-51">        progress_update(progress)</span>
<span id="cb4-52">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> math.isclose(best_score, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>):</span>
<span id="cb4-53">            solution_index <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> scores.index(best_score)</span>
<span id="cb4-54">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> pop[solution_index]</span>
<span id="cb4-55">        pop <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sample_pop_best(pop, [each[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> each <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> top_best])</span>
<span id="cb4-56">        generation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb4-57">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb4-58"></span>
<span id="cb4-59"></span>
<span id="cb4-60"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@dataclass</span></span>
<span id="cb4-61"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> UpdatePrinter:</span>
<span id="cb4-62">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""</span></span>
<span id="cb4-63"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    Simple object to be used for printing periodic progress</span></span>
<span id="cb4-64"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    """</span></span>
<span id="cb4-65"></span>
<span id="cb4-66">    generation: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb4-67">    how_often: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span></span>
<span id="cb4-68"></span>
<span id="cb4-69">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, progress: Progress) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>:</span>
<span id="cb4-70">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.generation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> progress.generation</span>
<span id="cb4-71">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> progress.generation <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.how_often <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:</span>
<span id="cb4-72">            <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(</span>
<span id="cb4-73">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gen:"</span>,</span>
<span id="cb4-74">                progress.generation,</span>
<span id="cb4-75">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mean:"</span>,</span>
<span id="cb4-76">                <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(progress.mean_score, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-77">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"best:"</span>,</span>
<span id="cb4-78">                <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(progress.best_score, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb4-79">                progress.best_thus_far,</span>
<span id="cb4-80">            )</span></code></pre></div></div>
</div>
</section>
<section id="sample-run" class="level2">
<h2 class="anchored" data-anchor-id="sample-run">Sample run</h2>
<div id="8e7859df-1a50-4cc4-b779-0767c54ca0aa" class="cell" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%%</span>time</span>
<span id="cb5-2">seed <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1690419104</span></span>
<span id="cb5-3">update <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> UpdatePrinter()</span>
<span id="cb5-4">random.seed(seed)</span>
<span id="cb5-5">solution <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> run(progress_update<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>update)</span>
<span id="cb5-6"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"generations: "</span>, update.generation)</span>
<span id="cb5-7"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solution: "</span>, solution)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>gen: 100 mean: 0.1423 best: 0.1423 [18, 89, 98, 61, 68, 91, 88, 16, 81, 19, 66, 99, 96, 69, 11, 86]
gen: 200 mean: 0.1404 best: 0.1404 [18, 91, 86, 69, 61, 88, 96, 18, 98, 11, 66, 89, 89, 66, 19, 91]
gen: 300 mean: 0.1322 best: 0.1322 [18, 89, 96, 61, 66, 88, 91, 19, 91, 18, 66, 86, 89, 69, 11, 98]
gen: 400 mean: 0.1441 best: 0.1441 [19, 89, 91, 66, 66, 88, 98, 11, 91, 18, 61, 89, 86, 69, 18, 96]
generations:  423
solution:  [18, 99, 86, 61, 66, 81, 98, 19, 91, 16, 69, 88, 89, 68, 11, 96]
CPU times: user 3.03 s, sys: 11.1 ms, total: 3.04 s
Wall time: 3.04 s</code></pre>
</div>
</div>
</section>
<section id="more-solutions" class="level2">
<h2 class="anchored" data-anchor-id="more-solutions">More solutions</h2>
<div id="8c11fd8c-3518-4196-b782-07aeaa50a698" class="cell" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode numberSource python number-lines code-with-copy"><code class="sourceCode python"><span id="cb7-1">ipytest.clean()</span>
<span id="cb7-2"></span>
<span id="cb7-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pytest</span>
<span id="cb7-4"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> math</span>
<span id="cb7-5"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb7-6"></span>
<span id="cb7-7">SOLUTIONS <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb7-8">    (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1669425992</span>, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>]),</span>
<span id="cb7-9">    (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1669426298</span>, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>]),</span>
<span id="cb7-10">    (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1690419104</span>, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">99</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">86</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">61</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">66</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">81</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">98</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">19</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">91</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">69</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">88</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">89</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">68</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">96</span>]),</span>
<span id="cb7-11">)</span>
<span id="cb7-12"></span>
<span id="cb7-13"></span>
<span id="cb7-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@pytest.mark.parametrize</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"seed, expected"</span>, SOLUTIONS)</span>
<span id="cb7-15"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test_solution(seed: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, expected: State):</span>
<span id="cb7-16">    random.seed(seed)</span>
<span id="cb7-17">    actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> run()</span>
<span id="cb7-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> actual <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> expected</span>
<span id="cb7-19">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> math.isclose(score(actual), <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.0</span>, abs_tol<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.001</span>)</span>
<span id="cb7-20"></span>
<span id="cb7-21"></span>
<span id="cb7-22">ipytest.run()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">.</span><span class="ansi-green-fg">                                                                                          [100%]</span>

<span class="ansi-green-fg ansi-bold">3 passed</span><span class="ansi-green-fg"> in 109.71s (0:01:49)</span>
</pre>
</div>
</div>
</div>


</section>

 ]]></description>
  <category>python</category>
  <guid>https://blog.blainebuxton.net/posts/2023-08-20-einstein-puzzle/einstein_blog.html</guid>
  <pubDate>Sun, 20 Aug 2023 04:00:00 GMT</pubDate>
</item>
<item>
  <title>Optional Typing in Python</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2023-07-30-optional-typing-presentation/</link>
  <description><![CDATA[ 





<p>Gave a talk at the <a href="http://www.meetup.com/python-178/">Tampa Python User Group</a> on <a href="https://docs.google.com/presentation/d/1CHa_ejK15EVZE5CPlqwaZE2h190L58FQXMO3619Ue_8/edit?usp=sharing">Optional Typing</a>. The talk was last year in May, but I wanted to share it on my new blog.</p>
<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vQdtd0wj7D5k-e6bm1X27739WL7Hfdo0gnHo4Q5a0JLYrU2yUnPn8z8cwCKUM9WWUe946Cb60CPykMe/embed?start=false&amp;loop=false&amp;delayms=3000" frameborder="0" width="533" height="429" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>



 ]]></description>
  <category>talks</category>
  <category>python</category>
  <guid>https://blog.blainebuxton.net/posts/2023-07-30-optional-typing-presentation/</guid>
  <pubDate>Sun, 30 Jul 2023 04:00:00 GMT</pubDate>
</item>
<item>
  <title>Welcome To My New Blog</title>
  <dc:creator>Blaine Buxton</dc:creator>
  <link>https://blog.blainebuxton.net/posts/2023-07-29-welcome/</link>
  <description><![CDATA[ 





<p>This is the first post in my new <a href="https://quarto.org/">Quarto</a> blog. Welcome!</p>
<p>If you are looking for my older posts, please visit <a href="https://blabux.blogspot.com/">here</a>.</p>



 ]]></description>
  <category>news</category>
  <guid>https://blog.blainebuxton.net/posts/2023-07-29-welcome/</guid>
  <pubDate>Sat, 29 Jul 2023 04:00:00 GMT</pubDate>
  <media:content url="https://blog.blainebuxton.net/blaine_logo.png" medium="image" type="image/png" height="82" width="144"/>
</item>
</channel>
</rss>
