<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: stevensonmt</title>
    <description>The latest articles on DEV Community by stevensonmt (@stevensonmt).</description>
    <link>https://dev.to/stevensonmt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1652%2F8891908.png</url>
      <title>DEV Community: stevensonmt</title>
      <link>https://dev.to/stevensonmt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stevensonmt"/>
    <language>en</language>
    <item>
      <title>Prim's algorithm in Elixir</title>
      <dc:creator>stevensonmt</dc:creator>
      <pubDate>Fri, 06 May 2022 02:59:20 +0000</pubDate>
      <link>https://dev.to/stevensonmt/prims-algorithm-in-elixir-285n</link>
      <guid>https://dev.to/stevensonmt/prims-algorithm-in-elixir-285n</guid>
      <description>&lt;p&gt;Prim's algorithm is a greedy algorithm for finding the lowest cost tree that includes all nodes of a graph, also called a minimum spanning tree. There are lots of blog posts and tutorials out there about implementing this, but I found it difficult to find information on implementations in functional languages or a functional style with immutable data structures.&lt;/p&gt;

&lt;p&gt;In the implementation below, the nodes of the graph are given as an unordered list. I found it easiest to work with the list as a tuple that could be accessed by index. The collection of nodes is not going to be mutated (no additions or insertions) but is going to be frequently accessed. Because accessing a tuple by index is quite fast I felt this was a good approach. That said, it is not necessary and may actually make this less "functional" in style.&lt;/p&gt;

&lt;p&gt;In Prim's algorithm you need two mathematical sets -- the set of all visited nodes (i.e., the nodes included in the minimum spanning tree) and the set of all nodes in the graph. You choose an arbitrary node to start and iterate over the unvisited nodes to find the minimum distance to connect to the MST. The algorithm is completed when these two sets are equivalent. In the implementation below I have chosen to simply track the set of &lt;em&gt;unvisited&lt;/em&gt; nodes, with the algorithm being complete when the set is empty. This is because in this case I'm only interested in the cost of the MST, not the MST itself. If I needed to return the MST I would track the visited nodes alongside the original set of nodes.&lt;/p&gt;

&lt;p&gt;You also need a way to know the cost of any edge in the graph. In this case I am assuming the graph is given as a series of {x, y} coordinate pairs and the weight of an edge is given by the &lt;a href="https://en.wikipedia.org/wiki/Taxicab_geometry"&gt;Manhattan distance&lt;/a&gt; between them.&lt;/p&gt;

&lt;p&gt;To begin we instantiate the set of unvisited nodes, the running "cost" of the minimum spanning tree, and a priority queue. In this instance I'm using a general balanced tree as the priority queue structure. I know they are not exactly equivalent, but Erlang has builtin GBT and I did not want to implement a priority queue from scratch.&lt;/p&gt;

&lt;p&gt;The keys of the GBT are the distances, and the values of the GBT are a list of nodes that connects with at least one edge at that key distance. Because I'm using a GBT as a queue and the keys must be unique, if I don't use a list as the value of each GBT node the queue will drop nodes and end up being incorrect. This is the only issue I encountered with using GBT as the priority queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;min_cost_connect_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;vertices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
      &lt;span class="n"&gt;points&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;with_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;into&lt;/span&gt;&lt;span class="p"&gt;(%{})&lt;/span&gt;

    &lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MapSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;# This will be our set of unvisited nodes, well, indices&lt;/span&gt;
&lt;span class="c1"&gt;# of nodes.&lt;/span&gt;

    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
&lt;span class="c1"&gt;# We initiate the priority queue with an arbitrary node &lt;/span&gt;
&lt;span class="c1"&gt;# that has a minimum distance of zero. The node index is&lt;/span&gt;
&lt;span class="c1"&gt;# wrapped in a list and entered into the GBT with key 0.&lt;/span&gt;

    &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;do_prims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;do_prims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;MapSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="c1"&gt;# When the set of unvisited nodes (`candidates`) is &lt;/span&gt;
&lt;span class="c1"&gt;# empty we're done.&lt;/span&gt;
      &lt;span class="n"&gt;cost&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;min_dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next_vertex&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;new_queue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;take_smallest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="c1"&gt;# take_smallest/1 returns a 3 tuple of {key, value, new_tree}&lt;/span&gt;
&lt;span class="c1"&gt;# where the new_tree is the original tree with the node that &lt;/span&gt;
&lt;span class="c1"&gt;# has the smallest key removed.&lt;/span&gt;
&lt;span class="c1"&gt;# The next line is necessary to avoid 'deduplicating' the &lt;/span&gt;
&lt;span class="c1"&gt;# queue of nodes that have min_dist as a potential edge cost.&lt;/span&gt;
&lt;span class="c1"&gt;# Arbitrarily taking the head of the list does not impact the&lt;/span&gt;
&lt;span class="c1"&gt;# correctness of the algorithm.&lt;/span&gt;
      &lt;span class="n"&gt;new_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                    &lt;span class="n"&gt;new_queue&lt;/span&gt;
                  &lt;span class="k"&gt;else&lt;/span&gt; 
&lt;span class="c1"&gt;# If multiple nodes have an edge where distance == min_dist,&lt;/span&gt;
&lt;span class="c1"&gt;# we need to put the min_dist key back in the queue with the&lt;/span&gt;
&lt;span class="c1"&gt;# rest of those nodes as the value.&lt;/span&gt;
                    &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_dist&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                  &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="no"&gt;MapSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;member?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_vertex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; 
&lt;span class="c1"&gt;# If the node we chose as the current smallest distance edge&lt;/span&gt;
&lt;span class="c1"&gt;# from the queue has already been visited (i.e., removed from&lt;/span&gt;
&lt;span class="c1"&gt;# the candidates set), then we skip next_vertex and try again&lt;/span&gt;
        &lt;span class="n"&gt;do_prims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="c1"&gt;# If next_vertex has not been visited yet, we mark it as&lt;/span&gt;
&lt;span class="c1"&gt;# visited and update the queue with edges connecting to&lt;/span&gt;
&lt;span class="c1"&gt;# next_vertex. Note that while the queue may include edges&lt;/span&gt;
&lt;span class="c1"&gt;# that would be discarded due to involved nodes already&lt;/span&gt;
&lt;span class="c1"&gt;# having been visited, this step will only ever introduce&lt;/span&gt;
&lt;span class="c1"&gt;# edges for nodes that have not been visited yet.&lt;/span&gt;
        &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MapSet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;next_vertex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;updated_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
          &lt;span class="n"&gt;candidates&lt;/span&gt;
          &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
               &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
                 &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;next_vertex&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# Here's where :gb_trees could really use an ergonomic&lt;/span&gt;
&lt;span class="c1"&gt;# update_or_insert function. There is an update/3 but it&lt;/span&gt;
&lt;span class="c1"&gt;# crashes if the key is not present. It also does not take&lt;/span&gt;
&lt;span class="c1"&gt;# a function as a parameter for the update, so it is less an&lt;/span&gt;
&lt;span class="c1"&gt;# update as a replace method. That's why we first check if the&lt;/span&gt;
&lt;span class="c1"&gt;# distance is already a key in the GBT. If it is, we have to&lt;/span&gt;
&lt;span class="c1"&gt;# get the value of that key and add the current node to the&lt;/span&gt;
&lt;span class="c1"&gt;# list. Otherwise we can just wrap the current node in a list.&lt;/span&gt;
               &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                      &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="k"&gt;else&lt;/span&gt;
                      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="k"&gt;end&lt;/span&gt;
               &lt;span class="ss"&gt;:gb_trees&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
             &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# We have updated the candidates list and the queue, so we &lt;/span&gt;
&lt;span class="c1"&gt;# recurse with the updated cost.&lt;/span&gt;
        &lt;span class="n"&gt;do_prims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vertices&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                 &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                 &lt;span class="n"&gt;updated_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                 &lt;span class="n"&gt;cost&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;min_dist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope someone finds this helpful. If anyone has tips on optimizations or corrections to my understanding of Prim's algorithm I'd love to hear them. Thanks for reading!&lt;/p&gt;

</description>
      <category>primsalgorithm</category>
      <category>minimumspanningtree</category>
      <category>elixir</category>
    </item>
    <item>
      <title> Working with menus in elm-ui</title>
      <dc:creator>stevensonmt</dc:creator>
      <pubDate>Mon, 31 Dec 2018 02:56:17 +0000</pubDate>
      <link>https://dev.to/stevensonmt/-working-with-menus-in-elm-ui-292b</link>
      <guid>https://dev.to/stevensonmt/-working-with-menus-in-elm-ui-292b</guid>
      <description>

&lt;p&gt;Recently had to figure out how to get a modal sort of menu to open and close correctly using the &lt;code&gt;mdgriffith/elm-ui&lt;/code&gt; package in Elm 0.19. For those unfamiliar, the &lt;code&gt;elm-ui&lt;/code&gt; package allows you to create front-end interfaces without resorting to CSS or HTML (with occasional exceptions). If you are working in Elm, I highly recommend it. If you aren't working in Elm yet, I would point to &lt;code&gt;elm-ui&lt;/code&gt; as one of its selling points and a reason to try it out.&lt;/p&gt;

&lt;p&gt;Here is the very basic concept in an &lt;a href="https://ellie-app.com/4jHGYY9PK6Ja1"&gt;ellie&lt;/a&gt;. &lt;br&gt;
Our simple &lt;code&gt;model&lt;/code&gt; has two fields: count and menu. It is defined thus:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type alias Model =
    { count : Int, menu : Bool }


initialModel : Model
initialModel =
    { count = 0, menu = False }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is the view code:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;view : Model -&amp;gt; Html Msg
view model =
    Element.layout [ Element.Background.color (Element.rgb255 30 30 30), padding 10]
    &amp;lt;| column [spacing 10, width &amp;lt;| px 200, Element.Background.color (Element.rgb255 200 30 10)] 
           [ el [ width fill
                , padding 8
                , Element.Font.center
                , Element.Background.color &amp;lt;| 
                      Element.rgb255 120 120 180
                ] &amp;lt;| 
                     Element.text (String.fromInt model.count)
           , el [ centerX
                , Element.Events.onClick OpenMenu
                , Element.below &amp;lt;| myMenu model
                ] &amp;lt;| 
                    Element.text "I'm a menu!"
           ]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And finally our &lt;code&gt;Msgs&lt;/code&gt; and &lt;code&gt;update&lt;/code&gt; function fill out the Elm Architecture for our demo app:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Msg
    = Increment
    | Decrement
    | OpenMenu
    | CloseMenu


update : Msg -&amp;gt; Model -&amp;gt; Model
update msg model =
    case msg of
        Increment -&amp;gt;
            { model | count = model.count + 1 }

        Decrement -&amp;gt;
            { model | count = model.count - 1 }

        OpenMenu -&amp;gt; 
            { model | menu = True }

        CloseMenu -&amp;gt; 
            { model | menu = False }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you try the ellie link you'll find that the menu opens to reveal the buttons for incrementing and decrementing the model count. Easy peasy. BUT the menu stays open. The first step to fix that is to change the menu element's &lt;code&gt;onClick&lt;/code&gt; attribute from an &lt;code&gt;OpenMenu&lt;/code&gt; action to a &lt;code&gt;ToggleMenu&lt;/code&gt; action.&lt;br&gt;
So now we have &lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Msg
    = Increment
    ...
    | ToggleMenu

update : Msg -&amp;gt; Model -&amp;gt; Model
update msg model =
    case msg of
       ...
        ToggleMenu -&amp;gt; { model | menu = not model.menu }

view : Model -&amp;gt; Html Msg
view model =
    ...
    , el [ centerX
                , Element.Events.onClick ToggleMenu
                , Element.below &amp;lt;| myMenu model
                ] &amp;lt;| 
                    Element.text "I'm a menu!"
    ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Sweet! Now the menu opens and closes when the triggering element is clicked. See the updated version &lt;a href="https://ellie-app.com/4jHQRRKK4NXa1"&gt;here&lt;/a&gt;. But lots of users will probably expect the menu to close when any other part of the viewport is clicked. Here is the first way I thought of setting that up:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;view : Model -&amp;gt; Html Msg
view model =
    Element.layout [ Element.Events.onClick CloseMenu
    ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This should mean that clicking anywhere sends the &lt;code&gt;CloseMenu&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt;. See the problem with this approach &lt;a href="https://ellie-app.com/4jHVqgY4NZMa1"&gt;here&lt;/a&gt;. Try to launch the menu and then open the debugger.&lt;/p&gt;

&lt;p&gt;What you see is that clicking the menu sends the &lt;code&gt;ToggleMenu&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; just like we want, but it is immediately followed by the &lt;code&gt;CloseMenu&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt;. This leads to the menu never opening. Ugggh.&lt;/p&gt;

&lt;p&gt;The reason for this is that &lt;code&gt;onClick&lt;/code&gt; events are propagated from child elements to parent elements. And we can't just use the &lt;code&gt;ToggleMenu&lt;/code&gt; fix on the &lt;code&gt;layout&lt;/code&gt; because that would open the menu anytime you click anywhere.&lt;/p&gt;

&lt;p&gt;There are almost certainly many ways to get around this, but the way I hit upon was to put an empty element the size of layout behind the content of the layout using the cleverly named function &lt;a href="https://package.elm-lang.org/packages/mdgriffith/elm-ui/1.1.0/Element#behindContent"&gt;&lt;code&gt;Element.behindContent&lt;/code&gt;&lt;/a&gt;. Giving this element an &lt;code&gt;onClick CloseMenu&lt;/code&gt; attribute works because it is not in a parent-child relationship with the menu elements. &lt;/p&gt;

&lt;p&gt;This approach works okay but there's still a couple of glitches. See it in action &lt;a href="https://ellie-app.com/4jJ5QMPPTD2a1"&gt;here&lt;/a&gt;. The most obvious glitch in terms of the problem of getting the menu to close is that the element displaying the counter is not sending the &lt;code&gt;CloseMenu&lt;/code&gt; &lt;code&gt;Msg&lt;/code&gt; when clicked because it is in front and not a child element of the element we just added. &lt;a href="https://ellie-app.com/4jJgMcr8Gxfa1"&gt;My solution&lt;/a&gt; was to add the &lt;code&gt;onClick CloseMenu&lt;/code&gt; attribute to that element. I'd be interested to hear more elegant solutions though!&lt;/p&gt;

&lt;p&gt;The second obvious hiccup to me is that the menu closes each time you increment or decrement the count. I think most users would expect the menu to stay open until they were done incrementing/decrementing the count as many times as they wanted. I'll leave the solution to that as an exercise for anyone interested.&lt;/p&gt;

&lt;p&gt;Thanks for reading. I hope you found it helpful. If you have questions about Elm or &lt;code&gt;elm-ui&lt;/code&gt; I highly recommend the &lt;a href="https://discourse.elm-lang.org"&gt;Elm Discourse &lt;/a&gt; and the Elm and &lt;code&gt;elm-ui&lt;/code&gt; &lt;a href="https://elmlang.slack.com/messages"&gt;Slack channels&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>elm</category>
      <category>elmui</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Making impossible things impossible in Rust</title>
      <dc:creator>stevensonmt</dc:creator>
      <pubDate>Wed, 06 Jun 2018 16:40:48 +0000</pubDate>
      <link>https://dev.to/stevensonmt/making-impossible-things-impossible-in-rust-3bkg</link>
      <guid>https://dev.to/stevensonmt/making-impossible-things-impossible-in-rust-3bkg</guid>
      <description>&lt;p&gt;I watched Richard Feldman's talk &lt;a href="https://www.youtube.com/watch?v=IcgmSRJHu_8"&gt;Making Impossible States Impossible&lt;/a&gt; a while back when I was learning a little bit of Elm. I'm not sure I understood the execution described in his talk, but the concept of making errors literally impossible with correct data structures stuck with me. I'm in the middle of what is my most ambitious Rust project to date and struggling to get that proper data structure.&lt;/p&gt;

&lt;p&gt;The problem centers around needing to create search strings for a web API that applies to 30+ database sets, each with unique but overlapping available search fields up to the 70s. I need it to be impossible to select an inappropriate field for a given database. &lt;/p&gt;

&lt;p&gt;In the genericized code below I'd like to share a couple of approaches that have become clear to me as I go through this design process. In doing so I hope to improve my own understanding and hopefully that of others with regards to type safety, implementation of traits, and data structures in Rust.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum Foo {
    Foo1(Foo1Field),
    Foo2(Foo2Field),
}

enum Foo1Field {
    Foo1Field1,
    Foo1Field2,
}

enum Foo2Field {
    Foo2Field1,
    Foo2Field2,
}

struct Bar {
    foo: Foo
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this organization you know that every Bar instance will always have a "field" type appropriate to the variant of Foo assigned. It's a little cumbersome to try and access those "fields" though. This is in part because the tuples of Foo1 and Foo2 are of different types.&lt;/p&gt;

&lt;p&gt;An alternative is making more use of traits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enum Foo1Field {
    Foo1Field1,
    Foo1Field2,
}

enum Foo2Field {
    Foo2Field1,
    Foo2Field2,
}

trait Foo {}

impl Foo for Foo1Field {}
impl Foo for Foo2Field {}

struct Bar&amp;lt;T: Foo&amp;gt; {
    foo: T
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this structure I no longer need a &lt;code&gt;Foo&lt;/code&gt; enum, I just need the "field" enums to implement the &lt;code&gt;Foo&lt;/code&gt; trait. The Bar struct now takes any enum that implements the &lt;code&gt;Foo&lt;/code&gt; trait for its &lt;code&gt;foo&lt;/code&gt; field. Accessing the field values is now trivial.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let bar = Bar { foo: Foo1Field::Foo1Field1 };
bar.foo // returns Foo1Field1 //
let bar2 = Bar { foo: Foo2Field::Foo2Field2 };
bar2.foo // returns Foo2Field2

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also allows me to add fields to various database sets without duplicating fields. I simply implement a trait for the new set. Hopefully others will find this helpful. I look forward to hearing additional insights or suggestions for alternative approaches to this type of problem. Thanks for reading.&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Naming Nested For Loops in Rust</title>
      <dc:creator>stevensonmt</dc:creator>
      <pubDate>Thu, 10 May 2018 13:27:06 +0000</pubDate>
      <link>https://dev.to/stevensonmt/naming-nested-for-loops-in-rust-cfp</link>
      <guid>https://dev.to/stevensonmt/naming-nested-for-loops-in-rust-cfp</guid>
      <description>&lt;p&gt;I've been aware of the ability to name for loops in rust for a while, but a recent project made me consider how that can make code more readable. It almost can take the place of a separate comment. My project took a string of variable length and looked for sets of keywords, trying to return the most relevant match.  Some keywords and positions would carry more weight in determining relevancy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'clauses: for clause in text.split(";") {
    'phrases: for phrase in clause.split(",") {
        'words: for word in phrase.split_whitespace() {
            'mainkeywords: for mainkey in MAIN_KEYS.iter() {
                match word.find(mainkey) {
                    Some(_) =&amp;gt; { dostuff(word);
                                 break 'phrases 
                               },
                    _ =&amp;gt; 'secondarykeys: for key in SECONDARY_KEYS.iter() {
                             match key.find(word) {
                                                   Some(_) =&amp;gt; do_other_stuff(word);
                                                   break 'words 
                                                  }
                 }
              }
           }
       }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Naming the loops can have the same effect as comments while providing some useful function. I hadn't seen naming loops as a code organization/readability tool mentioned before and though I'd share. If anyone has comments on this approach in general or the code above specifically I'd love to hear them.&lt;/p&gt;

</description>
      <category>rust</category>
    </item>
    <item>
      <title>Hi, I'm stevensonmt</title>
      <dc:creator>stevensonmt</dc:creator>
      <pubDate>Fri, 03 Feb 2017 04:54:10 +0000</pubDate>
      <link>https://dev.to/stevensonmt/hi-im-stevensonmt</link>
      <guid>https://dev.to/stevensonmt/hi-im-stevensonmt</guid>
      <description>&lt;p&gt;I have been coding for a few years.&lt;/p&gt;

&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/stevensonmt" rel="noopener noreferrer"&gt;stevensonmt&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in the Pacific NW.&lt;/p&gt;

&lt;p&gt;I am an amateur coder with a day job tangentially related to software.&lt;/p&gt;

&lt;p&gt;I mostly program in these languages: ruby, html, css, crystal, rust, elm.&lt;/p&gt;

&lt;p&gt;I am currently learning more about rust and elm while getting a firmer grasp on core concepts such as recursion and the differences between functional and imperative programming.  I would like to learn elixir at some point.&lt;/p&gt;

&lt;p&gt;Nice to meet you.&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
