<?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: Aravind Pai</title>
    <description>The latest articles on DEV Community by Aravind Pai (@dragondive).</description>
    <link>https://dev.to/dragondive</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%2F1047203%2F52540ff7-c381-4577-ba9a-db43f0ab3db9.jpeg</url>
      <title>DEV Community: Aravind Pai</title>
      <link>https://dev.to/dragondive</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dragondive"/>
    <language>en</language>
    <item>
      <title>PlantUML to compute diagrams!</title>
      <dc:creator>Aravind Pai</dc:creator>
      <pubDate>Thu, 25 Jul 2024 04:10:38 +0000</pubDate>
      <link>https://dev.to/dragondive/plantuml-to-compute-diagrams-4e76</link>
      <guid>https://dev.to/dragondive/plantuml-to-compute-diagrams-4e76</guid>
      <description>&lt;p&gt;This post is the Part 2 of my fun project on comparing execution times of different languages using the &lt;a href="https://en.wikipedia.org/wiki/Eight_queens_puzzle" rel="noopener noreferrer"&gt;Queen Problem&lt;/a&gt;. &lt;em&gt;[Link to &lt;a href="https://dev.to/dragondive/queen-problem-solution-and-analysis-part-1-3nh1"&gt;Queen Problem Solution and Analysis—Part 1&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/OncePerEpisode" rel="noopener noreferrer"&gt;Once again&lt;/a&gt;, let me first show you some results ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fdragondive.github.io%2Fgh-pages%2Fdocs%2Fassets%2Fimages%2Fqueen5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fdragondive.github.io%2Fgh-pages%2Fdocs%2Fassets%2Fimages%2Fqueen5.png" alt="Solution to the 5-Queen problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 5-Queen problem&lt;br&gt;&lt;br&gt;
    [NOTE: Solution to the 8-Queen problem, which is the canonical version of the N-Queen problem, draws chessboards too small for a teaser. It will appear later in this post, so keep reading. 😆]
  &lt;/p&gt;

&lt;p&gt;... and then take you through the journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Waypoints&lt;/strong&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Motivation and Flashback&lt;/li&gt;
&lt;li&gt;
Solution Explanation

&lt;ul&gt;
&lt;li&gt;Hack to use an array&lt;/li&gt;
&lt;li&gt;Hack to draw a chessboard&lt;/li&gt;
&lt;li&gt;Hack to colour the chessboard in alternating colours&lt;/li&gt;
&lt;li&gt;Hack to arrange the solutions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Results

&lt;ul&gt;
&lt;li&gt;Solution to the 8-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 1-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 2-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 3-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 4-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 5-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 6-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 7-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 9-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 10-Queens problem&lt;/li&gt;
&lt;li&gt;Solution to the 11-Queens problem&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Prior Art

&lt;ul&gt;
&lt;li&gt;Test cricket matches hosting data in a hierarchical structure&lt;/li&gt;
&lt;li&gt;Collatz sequence for a range of numbers&lt;/li&gt;
&lt;li&gt;More examples&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;h2&gt;
  
  
  Motivation and Flashback
&lt;/h2&gt;

&lt;p&gt;In October 2021, I presented PlantUML at &lt;em&gt;Smart Coffee Break&lt;/em&gt;, an internal tech talk series at work. While preparing for my talk, I explored PlantUML in depth and discovered its &lt;a href="https://plantuml.com/preprocessing" rel="noopener noreferrer"&gt;preprocessor&lt;/a&gt;. Initially, I was skeptical about its usefulness compared to writing the diagram descriptions directly.&lt;/p&gt;

&lt;p&gt;However, a few days later, I realized that the preprocessor could function as a general purpose programming language! This insight inspired me to include some examples of &lt;em&gt;computing&lt;/em&gt; diagrams, rather than "just" drawing them, to make my tech talk more entertaining. Thus began my journey of learning the PlantUML preprocessor with fun examples. The Prior Art section showcases some of my creations using the preprocessor as a programming language.&lt;/p&gt;

&lt;p&gt;When working on the Queen problem performance analysis recently, I thought it would be cool to draw all those solutions. This was a fine reason to resume my work with the PlantUML preprocessor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution Explanation
&lt;/h2&gt;

&lt;p&gt;In the first step, I decided to translate my C++ recursive solution (described in &lt;a href="https://dev.to%20post_url%202024-07-14-queen-problem-solution-analysis-part-1%20"&gt;Part 1&lt;/a&gt;) to PlantUML. The only change needed would be to replace &lt;em&gt;printing&lt;/em&gt; the solution with &lt;em&gt;drawing&lt;/em&gt; the solution. However, this is not so simple, I had to use a few hacks to get it working, which I will describe below.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💬 &lt;strong&gt;EXPOSITION&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, you may say it is more efficient to compute the solutions with C++, then draw them with PlantUML, and you would be right! In a professional environment, I would follow that approach too. However, I use the PlantUML preprocessor for computation for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To demonstrate the capability of the PlantUML preprocessor as a full-fledged Turing complete language—a graphical language, if you will.&lt;/li&gt;
&lt;li&gt;Solving the problem in another language and only drawing the solution with PlantUML is mundane and boring. This is a fun project and &lt;a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/RuleOfFun" rel="noopener noreferrer"&gt;I want to have fun&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hack to use an array
&lt;/h3&gt;

&lt;p&gt;Preprocessor does not provide an array or hashmap data structure, but the Queen problem solution requires a few arrays. To resolve this, I hacked string concatenation to simulate an array. This hack creates a variable for each array element by concatenating the array name with the index. For example, if we need an array named &lt;code&gt;pawn&lt;/code&gt; with index positions 0 to 7, we would create 8 variables, &lt;code&gt;pawn0&lt;/code&gt;, &lt;code&gt;pawn1&lt;/code&gt;, ..., &lt;code&gt;pawn7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For convenience and readability, I defined a few helper functions for this hack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function $to_variable($array_name, $index)
'This helper function "hacks" an array.
    !return %string($array_name + $index)
!endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function $get($array_name, $index)
'This helper function gets the value of an array element.
    !return %get_variable_value($to_variable($array_name, $index))
!endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!procedure $set($array_name, $index, $value)
'This helper function sets the value of an array element.
    %set_variable_value($to_variable($array_name, $index), $value)
!endprocedure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hack to draw a chessboard
&lt;/h3&gt;

&lt;p&gt;To draw a chessboard, I needed a way to draw a two-dimensional grid. I had previously used &lt;a href="https://plantuml.com/salt" rel="noopener noreferrer"&gt;Salt wireframe diagrams&lt;/a&gt; to draw grids, so I started from there. I ran into a problem with the table syntax, which &lt;a href="https://github.com/The-Lum" rel="noopener noreferrer"&gt;The-Lum&lt;/a&gt; addressed in this &lt;a href="https://forum.plantuml.net/19039/how-to-insert-newline-into-the-diagram-using-preprocessor?show=19042#a19042" rel="noopener noreferrer"&gt;answer&lt;/a&gt; to my question on the PlantUML forum. Their answer helped me fix the syntax, although my eventual solution did not require Salt.&lt;/p&gt;

&lt;p&gt;The below code draws the two-dimensional grid, with the key points being:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw a vertical bar (&lt;code&gt;|&lt;/code&gt;) for each column.&lt;/li&gt;
&lt;li&gt;Close a row with a vertical bar (&lt;code&gt;|&lt;/code&gt;) and add a newline.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function $make_chessboard()
    !$diagram = ""
    !$row = 0
    'The below two while loops "hack" a table to draw a chessboard.
    !while $row &amp;lt; $n
        !$column = 0
        !while $column &amp;lt; $n
            !$diagram = $diagram + "| "
            !$column = $column + 1
        !endwhile
        !$diagram = $diagram + " |" + %newline()
        !$row = $row + 1
    !endwhile
    !return $diagram
!endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the grid layout ready, placing the Queens solution was easy. While drawing the grid, the Unicode character for Queen (&lt;code&gt;♛&lt;/code&gt;) is placed at the squares denoted by the row and column numbers in the solution. All other squares are left blank.&lt;/p&gt;

&lt;p&gt;Here is the code snippet for placing the Queens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;' snip ... '
!$row = 0
!while $row &amp;lt; $n
    !$column = 0
    !while $column &amp;lt; $n
        ' snip ... '
        !if $get("placed_queen_id", $row) == $column
            !$diagram = $diagram + "♛"
        !endif
        !$column = $column + 1
    !endwhile
    ' snip ... '
    !$row = $row + 1
!endwhile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Hack to colour the chessboard in alternating colours
&lt;/h3&gt;

&lt;p&gt;For the chessboard to look realistic, we need to colour it in alternating light and dark colours. I chose &lt;a href="https://lichess.org" rel="noopener noreferrer"&gt;lichess&lt;/a&gt;'s default chessboard colours. Since &lt;a href="https://github.com/lichess-org" rel="noopener noreferrer"&gt;lichess is open source&lt;/a&gt; 👏, it was easy to obtain the RGB values &lt;a href="https://github.com/lichess-org/lichobile/blob/master/www/images/board/svg/brown.svg?short_path=afac3d9" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are several ways to achieve the alternating colouring. I felt the even-odd approach was the simplest. The preprocessor does not have a modulo division function, hence I used the below integer division hack. &lt;em&gt;[However, this hack may soon be unnecessary if my upcoming pull request to PlantUML gets approved. 😎]&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function $is_odd($number)
'"hack" to check if a number is odd.
'Perform integer division by 2, then multiply by 2. Due to truncation, the value will
'not be equal to the starting number if it is odd.
    !return ($number / 2 * 2) != $number
!endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💭 &lt;strong&gt;SIDENOTE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I later remembered I had the same problem during my exploration in 2021. Back then, I had used a more primitive approach. 😇&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!function $is_even($num)
    !$num_str = %string($num)
    !$last_digit = %substr($num_str, %strlen($num_str) -1, 1)
    !return ($last_digit == "0"\
            || $last_digit == "2"\
            || $last_digit == "4"\
            || $last_digit == "6"\
            || $last_digit == "8")
!endfunction
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Hack to arrange the solutions
&lt;/h3&gt;

&lt;p&gt;The last piece of the puzzle is arranging the multiple solutions in an aesthetically pleasing manner. For this, I used my final hack: make each solution a class in a class diagram! The class name is the solution number while the chessboard showing the solution is a class field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;!procedure $draw_solution()
    class **$solution_counter** {
        $make_chessboard()
    }
    !$solution_counter = $solution_counter + 1
!endprocedure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Below are the solutions, starting with the canonical 8-Queens problem, followed by the others in numerical order.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;TIP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some drawings below are too large to view easily on the webpage. You can open them in a new tab/window or download them for better clarity. The images are in SVG format, allowing you to zoom in for a clearer view.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Solution to the 8-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen8.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen8.svg%3Fraw%3Dtrue" alt="Solution to the 8-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 8-Queens problem&lt;br&gt;&lt;br&gt;
    [For more clarity, please open image in new tab and zoom in.]&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 1-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen1.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen1.svg%3Fraw%3Dtrue" alt="Solution to the 1-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 1-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 2-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen2.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen2.svg%3Fraw%3Dtrue" alt="Solution to the 2-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 2-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 3-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen3.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen3.svg%3Fraw%3Dtrue" alt="Solution to the 3-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 3-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 4-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen4.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen4.svg%3Fraw%3Dtrue" alt="Solution to the 4-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 4-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 5-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen5.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen5.svg%3Fraw%3Dtrue" alt="Solution to the 5-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 5-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 6-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen6.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen6.svg%3Fraw%3Dtrue" alt="Solution to the 6-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 6-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 7-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen7.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fplantuml%2Fqueen7.svg%3Fraw%3Dtrue" alt="Solution to the 7-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 7-Queens problem&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 9-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen9.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen9.svg" alt="Solution to the 9-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 9-Queens problem&lt;br&gt;&lt;br&gt;
    [For more clarity, please open image in new tab and zoom in.]&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 10-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen10.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen10.svg" alt="Solution to the 10-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 10-Queens problem&lt;br&gt;&lt;br&gt;
    [For more clarity, please open image in new tab and zoom in.]&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Solution to the 11-Queens problem
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen11.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fqueen%2Fab78a06d9ca498d6d15ab1955b876c6a27082e42%2Fartifacts%2Fplantuml%2Fqueen11.svg" alt="Solution to the 11-Queens problem"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Solution to the 11-Queens problem&lt;br&gt;&lt;br&gt;
    [For more clarity, please open image in new tab and zoom in.]&lt;br&gt;
  
  &lt;/p&gt;




&lt;h2&gt;
  
  
  Prior Art
&lt;/h2&gt;

&lt;p&gt;Here are some fun and educational examples from my previous exploration in 2021.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test cricket matches hosting data in a hierarchical structure
&lt;/h3&gt;

&lt;p&gt;Data about Test cricket matches hosted at various grounds is available in JSON format. This data is drawn in a hierarchical structure based on the ground's location (city, country), while also recursively computing the sum of all lower levels.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Ftest_match_host_wbs_demo.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Ftest_match_host_wbs_demo.svg%3Fraw%3Dtrue" alt="Hierarchical structure representing Test matches hosting data"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Hierarchical structure representing Test matches hosting data&lt;br&gt;&lt;br&gt;
    [For more clarity, please open image in new tab and zoom in.]&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  Collatz sequence for a range of numbers
&lt;/h3&gt;

&lt;p&gt;The preprocessor draws separate diagrams showing the &lt;a href="http://en.wikipedia.org/wiki/Collatz_sequence" rel="noopener noreferrer"&gt;Collatz sequence&lt;/a&gt; for a range of numbers. The diagrams for two arbitrarily chosen numbers, 18 and 65, are shown below as examples. The complete set of diagrams for numbers 1 to 100 is available in my github repository &lt;a href="https://github.com/dragondive/plantuml_demo/tree/main/src/preprocessor/diagrams" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Fcollatz_sequence_018.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Fcollatz_sequence_018.svg%3Fraw%3Dtrue" alt="Collatz sequence for 18"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Collatz sequence for 18&lt;br&gt;
  
  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Fcollatz_sequence_065.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fplantuml_demo%2Fblob%2Fmain%2Fsrc%2Fpreprocessor%2Fdiagrams%2Fcollatz_sequence_065.svg%3Fraw%3Dtrue" alt="Collatz sequence for 65"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
    Collatz sequence for 65&lt;br&gt;
  
  &lt;/p&gt;

&lt;h3&gt;
  
  
  More examples
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The complete list of examples and more explanation is available in my document &lt;a href="https://github.com/dragondive/plantuml_demo/blob/main/src/preprocessor/README.rst#fun-and-learning-with-the-plantuml-preprocessor" rel="noopener noreferrer"&gt;Fun and learning with the PlantUML preprocessor&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An overview and demo of PlantUML features is available at &lt;a href="https://github.com/dragondive/plantuml_demo/blob/main/README.md#plantuml-demo--and-other-useful-stuff" rel="noopener noreferrer"&gt;PlantUML demo ... and other useful stuff&lt;/a&gt;. Example source codes are also available in the github repository.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>chess</category>
      <category>hack</category>
      <category>fun</category>
      <category>plantuml</category>
    </item>
    <item>
      <title>Queen Problem Solution and Analysis—Part 1</title>
      <dc:creator>Aravind Pai</dc:creator>
      <pubDate>Sun, 14 Jul 2024 09:00:23 +0000</pubDate>
      <link>https://dev.to/dragondive/queen-problem-solution-and-analysis-part-1-3nh1</link>
      <guid>https://dev.to/dragondive/queen-problem-solution-and-analysis-part-1-3nh1</guid>
      <description>&lt;p&gt;This post describes my fun project to solve the &lt;a href="https://en.wikipedia.org/wiki/Eight_queens_puzzle" rel="noopener noreferrer"&gt;Queen problem&lt;/a&gt; in multiple languages and compare their execution runtimes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/InMediasRes" rel="noopener noreferrer"&gt;Let me first show you&lt;/a&gt; the results plot ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_log_scale_plot.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_log_scale_plot.png%3Fraw%3Dtrue" alt="Live results plot (log scale)"&gt;&lt;/a&gt;&lt;br&gt;Results plot (log scale)
  &lt;/p&gt;

&lt;p&gt;... and then take you through the journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Waypoints&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motivation and Flashback&lt;/li&gt;
&lt;li&gt;
Solution Explanation

&lt;ul&gt;
&lt;li&gt;Chess Gyan&lt;/li&gt;
&lt;li&gt;Calculation of the diagonal attacks&lt;/li&gt;
&lt;li&gt;Prototype Algorithm&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Project Plan

&lt;ul&gt;
&lt;li&gt;Storing the result artifacts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Solution Structure&lt;/li&gt;

&lt;li&gt;

Live Results

&lt;ul&gt;
&lt;li&gt;Results interpretation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;What's coming up next?&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation and Flashback
&lt;/h2&gt;

&lt;p&gt;I have not (yet?) formally studied Computer Science. Rather, I gained my knowledge, skills, and experience through self-learning during my professional career. I discovered the &lt;a href="https://en.wikipedia.org/wiki/Eight_queens_puzzle" rel="noopener noreferrer"&gt;Queen problem&lt;/a&gt; about 15 years ago. For several years, I struggled to grasp the backtracking that the solutions mentioned, and particularly, how it was different from brute force.&lt;/p&gt;

&lt;p&gt;Then one fateful day in 2018, I found Abdul Bari's YouTube video. His clear explanation helped me easily understand the backtracking. &lt;em&gt;[I binge-watched his other videos later and realized—like many others before and after me—that he is an amazing teacher!]&lt;/em&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;a href="https://www.youtube.com/watch?si=xy6f1Qk4_XL1wehy&amp;amp;v=xFv_Hl4B83A&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;
      youtube.com
    &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;To verify my understanding, I quickly &lt;a href="https://ideone.com/YU11ym" rel="noopener noreferrer"&gt;prototyped a solution&lt;/a&gt; in C++ on ideone. &lt;em&gt;[Interestingly, when I accidentally resubmitted the solution recently, it failed to compile due to the &lt;code&gt;constexpr&lt;/code&gt; in the template parameter.]&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I did nothing more on it until mid-2024. During this time, I gained more experience with Python. I self-learned CI/CD pipelines, both Github Actions and Gitlab CI. A few weeks ago, I started learning Rust. Putting together all these skills seemed like a fun project. Thus, I revisited the Queen problem.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution Explanation
&lt;/h2&gt;

&lt;p&gt;I decided to continue with my prototype solution and deal with improving it later.&lt;/p&gt;

&lt;p&gt;My prototype solution is based on the following main ideas: &lt;em&gt;[Of course, nothing groundbreaking—thousands of others have solved it before me.]&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pigeonhole Principle&lt;/strong&gt;: Since each Queen occupies an entire row and column, we cannot place more than one Queen on a row or a column. Conversely, a solution to the N-Queen problem (placing N Queens on an NxN chessboard) cannot have any empty row or column. &lt;em&gt;[As embarassing at it sounds in hindsight, this was a key factor I had failed to realize before, due to which I couldn't differentiate backtracking from brute force.]&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calculating the Queen's attack along the diagonals&lt;/strong&gt;: Similarly, we cannot place more than one Queen on any diagonal. Calculating the Queen's attack along diagonals is a little more complicated, though. I'll explain my approach to this later, but first, it is time for some chess ज्ञान (gyan). 😆&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Chess Gyan
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The horizontal rows on a chessboard are called &lt;strong&gt;ranks&lt;/strong&gt; (labelled &lt;code&gt;1&lt;/code&gt; through &lt;code&gt;8&lt;/code&gt;, bottom to top), while the vertical columns are called &lt;strong&gt;files&lt;/strong&gt; (labelled &lt;code&gt;a&lt;/code&gt; through &lt;code&gt;h&lt;/code&gt;, left to right). Nonetheless, in this blog post, I'll call them rows and columns, numbered &lt;code&gt;0&lt;/code&gt; through &lt;code&gt;7&lt;/code&gt; top to bottom and left to right respectively.&lt;/li&gt;
&lt;li&gt;The Queen is the most powerful piece in chess, which controls between 22 and 28 squares on an 8x8 chessboard. That's a control of 34.38% to 43.75% squares. This makes the Queen problem all the more fascinating. Not only can we place 8 Queens on an 8x8 chessboard without an overlap of their controlled squares, but we can do so in 92 different positions!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen22.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen22.png%3Fraw%3Dtrue" alt="Queen controls 22 squares from a corner square."&gt;&lt;/a&gt;&lt;/p&gt;
Queen controls 22 squares from a corner square.



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen28.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen28.png%3Fraw%3Dtrue" alt="Queen controls 28 squares from a central square."&gt;&lt;/a&gt;&lt;/p&gt;
Queen controls 28 squares from a central square.



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculation of the diagonal attacks
&lt;/h3&gt;

&lt;p&gt;When making my prototype, I referred some previous solutions. Many of them used the Queen's row and column position to check if it would occupy the same diagonal as any of the previously placed Queens. I took a different approach, which is equivalent but felt easier to understand and implement.&lt;/p&gt;

&lt;p&gt;I numbered each diagonal, in both directions, so I could maintain an array of flags to represent if a diagonal was already occupied. This is possible because the combination of row and column number satisfy an invariant along each diagonal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Right diagonals&lt;/strong&gt;: The sum of the row and column numbers is the same for all squares on a diagonal going up towards the right. This sum can be used to number the diagonals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fdiagonal_right.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fdiagonal_right.png%3Fraw%3Dtrue" alt="Numbering the right diagonals."&gt;&lt;/a&gt;&lt;/p&gt;
Numbering the right diagonals.



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Left diagonals&lt;/strong&gt;: The difference between the row and column numbers is the same for all squares on a diagonal going up towards the left. This difference can be used to number the diagonals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fdragondive.github.io%2Fgh-pages%2Fdocs%2Fassets%2Fimages%2Fdiagonal_left.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdragondive%2Fdragondive.github.io%2Fgh-pages%2Fdocs%2Fassets%2Fimages%2Fdiagonal_left.png" alt="Numbering the left diagonals."&gt;&lt;/a&gt;&lt;/p&gt;
Numbering the left diagonals.



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prototype Algorithm
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Let each Queen move only along one column. The column number also serves as the Queen's identity. Due to the Pigeonhole Principle mentioned earlier, there is a 1:1 mapping between a Queen and a column. &lt;em&gt;[Equivalently, a Queen could move only along a row, but personally, I found the column mapping more intuitive.]&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;
  &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen_column_move.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdragondive.github.io%2Fassets%2Fimages%2Fqueen_column_move.png%3Fraw%3Dtrue" alt="Let each Queen can move only along one column."&gt;&lt;/a&gt;&lt;br&gt;Let each Queen can move only along one column.
  &lt;br&gt;
  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pseudo-code of the prototype algorithm:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  let ROW = 0
  for COLUMN from 0 to N - 1 (both inclusive):
  {
    if ROW, COLUMN, and both diagonals are not occupied:
    {
        (1) place Queen in column number 'COLUMN'
            [For the row number 'ROW', note occupied column number as 'COLUMN']
        (2) mark ROW, COLUMN, and both diagonals as occupied

        if ROW &amp;lt; N:    // there are still unoccupied rows
        {
            let ROW = ROW + 1
            attempt to place a Queen in (ROW + 1) using the approach in (1) and (2)
        }
        else:
        {
            // We checked the occupancy status along rows, columns and diagonals
            // before placing a Queen. If we have reached here, we must have placed
            // N queens successfully without conflict. We found a solution!

            print solution    // occupied column number in each row denotes the solution
        }

        // When we reach here, we have either found a solution or failed to place a
        // Queen in one of the rows without conflict. In either case, we move on to
        // search for the next solution with a clean slate.

        mark ROW, COLUMN, and both diagonals as unoccupied
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Implementation Details

&lt;ul&gt;
&lt;li&gt;This algorithm naturally leans towards a recursion-based implementation.&lt;/li&gt;
&lt;li&gt;As only one column can be occupied in any row, a one-dimensional array is adequate to note the positions of the Queens. This array also tracks the row occupancy status.&lt;/li&gt;
&lt;li&gt;One-dimensional arrays can denote occupancy of columns and diagonals.&lt;/li&gt;
&lt;li&gt;The left diagonals are numbered from &lt;code&gt;-(N-1)&lt;/code&gt; to &lt;code&gt;+(N+1)&lt;/code&gt;, but arrays in most programming languages support only non-negative indexes. Hence, an offset should be added to bring the left diagonal numbers within the non-negative range.&lt;/li&gt;
&lt;li&gt;The prototype does not store the solutions. Instead, it immediately prints solutions as they are found.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Plan
&lt;/h2&gt;

&lt;p&gt;To expand my prototype into a project, I structured the following project plan:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Step 1&lt;/strong&gt;: Move my 2018 prototype to my Github repository as-is. Rework the solution to accept &lt;code&gt;N&lt;/code&gt; as a command-line input instead of the template parameter. Fix some bugs and write better code documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 2&lt;/strong&gt;: Translate the solution into Python and Rust. To level the playing field, if you will, use the same algorithm in both of those languages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 3&lt;/strong&gt;: Develop scripts to run the solutions and plot the execution times, for both pipeline build and local developer builds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 4&lt;/strong&gt;: Share the first version of the solutions and performance results publicly, for example, in this blog post! 😆&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 5&lt;/strong&gt;: &lt;em&gt;To be revealed in Part 2!&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing the result artifacts
&lt;/h3&gt;

&lt;p&gt;To have even more fun, I initially considered connecting an external artifact repository to store the result artifacts. Unfortunately, the service I had in mind (the one with the small jumping animal) was too pricey for a hobby project. Hence, I opted to use Github itself as the artifact repository for now, and explore alternatives later.&lt;/p&gt;

&lt;p&gt;Execution times would be stored in CSV format, and used to plot graphs in SVG format. By sticking to these text-based formats, I avoid the shenanigans of LFS (Large File Storage)—though BFS (Binary File Storage) would be a more accurate name!&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution Structure
&lt;/h2&gt;

&lt;p&gt;You can find the project on my Github repository: &lt;a href="https://github.com/dragondive/queen" rel="noopener noreferrer"&gt;dragondive/queen&lt;/a&gt; &lt;em&gt;[Code reviews and other contributions are welcome!]&lt;/em&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solutions are developed on the &lt;a href="https://github.com/dragondive/queen/tree/develop/queen" rel="noopener noreferrer"&gt;&lt;code&gt;develop/queen&lt;/code&gt;&lt;/a&gt; branch, with a separate directory for each language.

&lt;ul&gt;
&lt;li&gt;My unoptimized prototype in C++, the project's lead language, is &lt;a href="https://github.com/dragondive/queen/blob/v0.1/c%2B%2B/queen.cc" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Github Actions workflows are currently developed directly on the main branch.

&lt;ul&gt;
&lt;li&gt;The workflow that measures solution execution times and updates the plots is &lt;a href="https://github.com/dragondive/queen/blob/main/.github/workflows/queen.yml" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Solution artifacts are stored on the &lt;a href="https://github.com/dragondive/queen/tree/artifacts" rel="noopener noreferrer"&gt;&lt;code&gt;artifacts&lt;/code&gt; branch&lt;/a&gt; in the &lt;a href="https://github.com/dragondive/queen/tree/artifacts/artifacts" rel="noopener noreferrer"&gt;&lt;code&gt;artifacts&lt;/code&gt; directory&lt;/a&gt;.&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://gist.github.com/qoomon/5dfcdf8eec66a051ecd85625518cfd13" rel="noopener noreferrer"&gt;Conventional commits&lt;/a&gt;, squashed commits and controlled force pushing maintain a clean commit history &lt;em&gt;[With controlled force pushing and interactive rebase, &lt;a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/HardModePerks" rel="noopener noreferrer"&gt;I changed the &lt;code&gt;README.md&lt;/code&gt; in the initial commit to &lt;code&gt;README.rst&lt;/code&gt; and performed several other commit history cleanups retroactively.&lt;/a&gt;]&lt;/em&gt;
&lt;/li&gt;

&lt;li&gt;Tagging the solution versions and running the pipeline jobs is done manually for now.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Results
&lt;/h2&gt;

&lt;p&gt;Execution times for each solution language and version are plotted against &lt;code&gt;N&lt;/code&gt;, considering average values. Each successful pipeline build updates the plot, making them live plots.&lt;/p&gt;

&lt;p&gt;The log scale plot provides a more insightful visualization than the linear scale plot. Nonetheless, the pipeline build updates both the plots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_log_scale_plot.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_log_scale_plot.svg%3Fraw%3Dtrue" alt="Live results plot (log scale)"&gt;&lt;/a&gt;&lt;br&gt;Live results plot (log scale)
  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_linear_scale_plot.svg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fdragondive%2Fqueen%2Fblob%2Fartifacts%2Fartifacts%2Fqueen_linear_scale_plot.svg%3Fraw%3Dtrue" alt="Live results plot (linear scale)"&gt;&lt;/a&gt;&lt;br&gt;Live results plot (linear scale)
  &lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Results interpretation
&lt;/h3&gt;

&lt;p&gt;The most obvious observation is that the C++ solution is the fastest, with Rust close behind, and Python being significantly slower. However, execution time alone should not dictate the choice of language for a particular problem. In my opinion, rules like "never do this" and "always do that" are never helpful and always ignorable.&lt;/p&gt;

&lt;p&gt;This topic has sparked much discussion, controversy and misinformation in both developer and sustainability communities. The debate intensified around 2021 when the 2017 research paper &lt;a href="https://greenlab.di.uminho.pt/wp-content/uploads/2017/09/paperSLE.pdf" rel="noopener noreferrer"&gt;Energy Efficiency across Programming Languages&lt;/a&gt; reentered prominence. That debate was also a motivator for me to revive this fun project, as both software development and sustainability are of great interest to me. &lt;em&gt;[It took me a few years though to get around to it.]&lt;/em&gt; See also Yelle Lieder's blog post on the topic: &lt;a href="https://www.adesso.de/en/news/blog/sustainability-of-programming-languages-java-rather-than-typescript-2.jsp" rel="noopener noreferrer"&gt;Sustainability of programming languages: Java rather than TypeScript?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Personally, I enjoy using both C++ and Python, among other languages. My choice of language for a particular problem is made on a case-by-case basis, and depends on several factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning time&lt;/strong&gt;: How long it takes me (and my team) to learn the language, or in some cases, its specific "advanced" features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development time&lt;/strong&gt;: The time required to write the code. In some cases, it's no good if your program runs 100 ms faster but takes three more months to develop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build time&lt;/strong&gt;: The time it takes to build and deploy the application. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debug time&lt;/strong&gt;: As with everything else in the world, software goes wrong, sooner or later. The amount of time (and occasionally, frustration) it takes to fix problems also matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation, testability and team composition&lt;/strong&gt;: Most non-trivial software is developed by a team of developers. The ease of understanding and reliably modifying others' codes, especially in teams distributed across distant timezones, impacts code quality and value of the application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability of useful libraries and active community&lt;/strong&gt;: These reduce development and maintenance efforts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability of enthusiastic developers&lt;/strong&gt;: Ease of finding developers, especially at work, interested in using the language significantly impacts planning. I have encountered scenarios where developers refused job offers or even interview invitations because &lt;a href="https://devdriven.by/resume/" rel="noopener noreferrer"&gt;they didn't want to work with a specific framework being used&lt;/a&gt; &lt;em&gt;[which was understandable as the framework was company-proprietary and completely different from the industry standards]&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The frequency of use of the application&lt;/strong&gt;: An application used several times per day benefits from high efficiency. One that is used only a few times per year, perhaps not so much.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comparing languages solely by execution time without considering the full context is too simplistic. In particular, &lt;a href="https://www.efinancialcareers.com/news/2023/06/which-programming-language-uses-the-most-energy" rel="noopener noreferrer"&gt;a "faster" language is not necessarily "greener"&lt;/a&gt;. As developers, we should make data-driven decisions objectively, based on many diverse but relevant factors, without being biased towards our favourite language or the &lt;a href="https://devdriven.by/hn/" rel="noopener noreferrer"&gt;"flavour of the month"&lt;/a&gt; language.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's coming up next?
&lt;/h2&gt;

&lt;p&gt;I will optimize and partially rework my prototype. Specifically, I'll replace the recursion with iteration and use a more efficient approach for reporting results instead of the repeated I/O access. I will share my findings in the Part 3 of this blog post.&lt;/p&gt;

&lt;p&gt;Hang on! What about Part 2? I'll be solving the Queen problem using a &lt;em&gt;fourth&lt;/em&gt; language—one that is different, more interesting and more fun than these three. Can you guess which language that will be? Let me know in the comments!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tools Used&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://lichess.org/editor/1q6/6q1/4q3/7q/q7/3q4/5q2/2q5_b_HAha_-_0_1?color=white" rel="noopener noreferrer"&gt;Lichess board editor&lt;/a&gt; for the chessboard annotations.&lt;/li&gt;
&lt;li&gt;Screenpresso image editor for the numbered circles. The tool doesn't support negative numbers, so I manually edited in the minus sign. &lt;em&gt;[Disclaimer: Not a paid promotion—though I am open to the idea if Screenpresso so wishes. 😉]&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>crosslanguagecomparison</category>
      <category>python</category>
      <category>rust</category>
    </item>
    <item>
      <title>My Hello world story</title>
      <dc:creator>Aravind Pai</dc:creator>
      <pubDate>Tue, 21 Mar 2023 12:12:03 +0000</pubDate>
      <link>https://dev.to/dragondive/my-hello-world-story-4o5i</link>
      <guid>https://dev.to/dragondive/my-hello-world-story-4o5i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;hello, world&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The famous &lt;em&gt;first words&lt;/em&gt; in most people's computer programming journey!&lt;/p&gt;

&lt;p&gt;The tradition started with Professor Brian Kernighan's documentation of the B and C programming languages during his time at Bell Labs. Ozaner Hansha describes it in more detail here: &lt;a href="https://ozanerhansha.medium.com/on-the-origin-of-hello-world-61bfe98196d5" rel="noopener noreferrer"&gt;On the Origin of "Hello, World!"&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My early days of ignorance
&lt;/h2&gt;

&lt;p&gt;When I first read it about 15 years ago in &lt;a href="https://openlibrary.org/works/OL4617640W/The_C_Programming_Language?edition=key%3A/books/OL2030445M" rel="noopener noreferrer"&gt;&lt;em&gt;&lt;strong&gt;The C Programming Language&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; (perhaps more famously known as the &lt;em&gt;&lt;strong&gt;K&amp;amp;R C book&lt;/strong&gt;&lt;/em&gt;), I felt the explanation was either exaggerated or dramatized. As a newborn kid in the IT industry, I had the comfort of working in environments already setup by my predecessors. I couldn't comprehend why it was a big hurdle to execute a simple program.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bz4wIu7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dragondive.github.io/assets/images/hello-world-page5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bz4wIu7h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dragondive.github.io/assets/images/hello-world-page5.jpg" alt="Page 5 from K&amp;amp;R" width="800" height="294"&gt;&lt;/a&gt;&lt;br&gt;
  &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--poTK1yIL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dragondive.github.io/assets/images/hello-world-page6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--poTK1yIL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dragondive.github.io/assets/images/hello-world-page6.jpg" alt="Page 6 from K&amp;amp;R" width="800" height="348"&gt;&lt;/a&gt;&lt;br&gt;From my owned copy of the K&amp;amp;R C book, complies with &lt;a href="https://copyrightalliance.org/faqs/what-is-fair-use/" rel="noopener noreferrer"&gt;Fair Use&lt;/a&gt;.
  &lt;/p&gt;

&lt;h2&gt;
  
  
  How experience taught me better
&lt;/h2&gt;

&lt;p&gt;I have since grown out of my ignorance and naivete. Over the years, I have setup many working environments from scratch, many of them in my side-projects (of which, my &lt;a href="https://dragondive.github.io/" rel="noopener noreferrer"&gt;Jekyll-based blog on Github Pages&lt;/a&gt; is &lt;a href="https://dragondive.github.io/2023/03/10/setting-up-my-blog/" rel="noopener noreferrer"&gt;a recent example&lt;/a&gt;). Those experiences helped me fully appreciate the insights behind that explanation.&lt;/p&gt;

&lt;p&gt;In various different scenarios, I have met with each of the mentioned hurdles, and then some more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On some systems, the seemingly trivial writing of a text file was a big hurdle. My preferred vi editor wasn't available, I didn't have permissions to install it, and at the time, I didn't know how to properly use the other editors.&lt;/li&gt;
&lt;li&gt;There have been many occasions of going through &lt;a href="https://www.techtarget.com/searchitoperations/definition/dependency-hell" rel="noopener noreferrer"&gt;dependency hell&lt;/a&gt; to setup the required build tools.&lt;/li&gt;
&lt;li&gt;On a few occasions, the program executed successfully, but it took me a while to figure out where the program output went.&lt;/li&gt;
&lt;li&gt;In the corporate environment, configuring the corporate proxy and fiddling with the VPN settings is frequently a catastrophe by itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hello world, bye cognitive load
&lt;/h2&gt;

&lt;p&gt;In my experience, the greatest value that reaching the &lt;em&gt;Hello world checkpoint&lt;/em&gt; brings is it drastically reduces the &lt;a href="https://bootcamp.uxdesign.cc/what-is-cognitive-load-in-ux-ff068fb8c44d" rel="noopener noreferrer"&gt;cognitive load&lt;/a&gt; afterwards. Having seen the first program run successfully, I can fully focus on solving the actual problem. My subconscious mind is not worried about how to prepare the setup for seeing the outcome of the code I'm now writing. It is a reassuring feeling that there is already a working environment on which I can try out my solution and get quick feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  The many flavours of Hello world
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;Hello world checkpoint&lt;/em&gt; is frequently more than just printing hello world. For example, in Python, printing hello world is a simple function call with zero &lt;a href="https://www.youtube.com/watch?v=4jCjDEb9KZI" rel="noopener noreferrer"&gt;ceremony&lt;/a&gt;. However, that says nothing about whether your setup can use libraries.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you intend to write small Python scripts, your Hello world may involve installing one library and calling one of its functions.&lt;/li&gt;
&lt;li&gt;For Python projects with more elaborate package organization, you may need a Hello world with two modules or packages, and invoking some functions in one module from the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Hello world would also depend on the specific purpose of the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For an application that mainly works with a database, the Hello world would include connecting to a database and executing one read and one write command.&lt;/li&gt;
&lt;li&gt;For an application that processes data fetched from API calls, it would include setting up the authentication and making an API call.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Refining Hello world iteratively
&lt;/h2&gt;

&lt;p&gt;The Hello world checkpoint is not cast in stone. It can—and perhaps should—get refined iteratively as one gains more experience and understanding. My current Hello world for Python projects, for example, includes installing a local package &lt;a href="https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html" rel="noopener noreferrer"&gt;using a &lt;code&gt;pyproject.toml&lt;/code&gt; file&lt;/a&gt;, setting up a simple unit test with &lt;a href="https://docs.pytest.org/" rel="noopener noreferrer"&gt;pytest&lt;/a&gt;, executing the &lt;a href="https://pypi.org/project/black/" rel="noopener noreferrer"&gt;black formatter&lt;/a&gt;, and running &lt;a href="https://prospector.landscape.io/" rel="noopener noreferrer"&gt;prospector code analysis&lt;/a&gt;. For my future Python projects, I may add or change some things as my own depth of knowledge increases and based on how the Python world changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Hello world is not merely a customary ritual, but is immensely helpful for software developers. It is a method to first get the pieces lined up properly before starting to play the game. This makes their subsequent work much easier by closing off one major source of distractions and frustrations.&lt;/p&gt;

&lt;p&gt;Hello world is not one-size-fits-all, it varies from case to case. The developer should seek to constantly refine their Hello world in accordance with changing circumstances and as their own understanding increases.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
