<?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: Topher Vizcarra</title>
    <description>The latest articles on DEV Community by Topher Vizcarra (@tigertopher).</description>
    <link>https://dev.to/tigertopher</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%2F369444%2F766491eb-a167-412e-bf6b-c0213f211d00.png</url>
      <title>DEV Community: Topher Vizcarra</title>
      <link>https://dev.to/tigertopher</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tigertopher"/>
    <language>en</language>
    <item>
      <title>Solving The Puzzle Box using Recursive Backtracking in Python</title>
      <dc:creator>Topher Vizcarra</dc:creator>
      <pubDate>Sun, 01 Nov 2020 13:30:28 +0000</pubDate>
      <link>https://dev.to/tigertopher/solving-the-puzzle-box-using-recursive-backtracking-3pfg</link>
      <guid>https://dev.to/tigertopher/solving-the-puzzle-box-using-recursive-backtracking-3pfg</guid>
      <description>&lt;p&gt;My partner and I absolutely love solving puzzles as our bonding moment. This Halloween, we decided to solve &lt;a href="https://www.enchambered.com/puzzles/" rel="noopener noreferrer"&gt;online Escape Room puzzles by Enchambered&lt;/a&gt;. Of all the puzzles we tried that night, the one that stood out the most for me was the mind-bending Puzzle #4. If you haven't tried it, I highly suggest you give it a go - &lt;a href="https://www.enchambered.com/puzzles/puzzle_4_mystery_box/game/" rel="noopener noreferrer"&gt;Puzzle 4 Mystery Box&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Puzzle
&lt;/h1&gt;

&lt;p&gt;The board has numbers from 1 to 9 that are scrambled and four red buttons that divide the board into four quadrants.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shifting the numbers
&lt;/h2&gt;

&lt;p&gt;When one of the red buttons is clicked, the numbers surrounding the button are shifted in clockwise order.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9c2g8b417gl4tz4voh04.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9c2g8b417gl4tz4voh04.gif" alt="Red button shifting the numbers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;On the left of the board, there is a hint implying that to get the key, we need to arrange the numbers in the given order.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm45b58t9o35h7oslzsek.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm45b58t9o35h7oslzsek.png" alt="Hint in Yellow Paper"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It took my partner 5 minutes to solve the puzzle while it took me an hour before I finally gave up. Defeated, I found myself experiencing a puzzle-hangover the next day as I try to find a solution.&lt;/p&gt;

&lt;p&gt;While I think there has to be a strategy to solve this similar to solving a Rubik's cube, I instead went for the brute-force approach of finding a solution by using Recursive Backtracking.&lt;/p&gt;

&lt;h1&gt;
  
  
  Recursive Backtracking
&lt;/h1&gt;

&lt;p&gt;Geeks for Geeks defines &lt;a href="https://www.geeksforgeeks.org/backtracking-introduction/" rel="noopener noreferrer"&gt;backtracking&lt;/a&gt; as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;a general algorithmic technique that considers searching every possible combination to solve a computational problem. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some popular applications of this algorithm are finding solutions for Sudoku, brute-forcing passwords, and path-finding in mazes.&lt;/p&gt;

&lt;p&gt;Meanwhile, &lt;a href="https://www.geeksforgeeks.org/recursion/" rel="noopener noreferrer"&gt;recursion&lt;/a&gt; is defined as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;the process in which a function calls itself directly or indirectly is called recursion and the corresponding function is called as recursive function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Hence, we will be implementing a &lt;em&gt;backtracking&lt;/em&gt; algorithm using &lt;em&gt;recursion&lt;/em&gt; to search for a solution that will lead us to the desired state.&lt;/p&gt;

&lt;p&gt;I find that the most tedious part of implementing this algorithm is representing the puzzle and the operations in code. However, once that is done, writing the general algorithm that does the actual solving is not that difficult at all.&lt;/p&gt;

&lt;p&gt;Implement recursive backtracking once and it should be easy to re-use the pattern to solve similar puzzles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Representing the puzzle
&lt;/h2&gt;

&lt;p&gt;Note: The following code snippets you will see here are implemented using Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Board
&lt;/h3&gt;

&lt;p&gt;We can start by representing the board using 2-dimensional arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initial_board = [
    [7,6,5],
    [8,4,9],
    [3,2,1]
]

solved_board = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Quadrants
&lt;/h3&gt;

&lt;p&gt;Now, let's divide our board into 4 quadrants:&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Folibfo6m4p5hz1cytk2o.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Folibfo6m4p5hz1cytk2o.png" alt="Dividing the board into quadrants"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will be helpful for us when we're representing the button operations that rotate the numbers into code.&lt;/p&gt;

&lt;p&gt;In terms of array indices, the groupings are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Quadrant 1 -&amp;gt; [0,0], [0,1], [1,1], [1,0]
# Quadrant 2 -&amp;gt; [0,1], [0,2], [1,2], [1,1]
# Quadrant 3 -&amp;gt; [1,0], [1,1], [2,1], [2,0]
# Quadrant 4 -&amp;gt; [1,1], [1,2], [2,2], [2,1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkdxt0xexifbwqlqkvgna.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkdxt0xexifbwqlqkvgna.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Rotations
&lt;/h3&gt;

&lt;p&gt;Let us represent the button click operation. We start by defining how to shift in Quadrant 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from copy import deepcopy

# Operations
def shiftQuadrant1(originalBoard):
    board = deepcopy(originalBoard)
    board[0][0], board[0][1], board[1][1], board[1][0] = board[1][0], board[0][0], board[0][1], board[1][1]
    return board
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we needed to import &lt;code&gt;deepcopy&lt;/code&gt; so that we make a copy of the board instance instead of modifying the original board.&lt;/p&gt;

&lt;p&gt;For reference, here is the &lt;a href="https://docs.python.org/3/library/copy.html" rel="noopener noreferrer"&gt;difference between shallow copy vs deep copy&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also, notice how the clockwise rotation of the numbers can easily be implemented in Python as we leverage its simplicity of swapping variable values without explicitly defining a temporary variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# To switch values between a and in b in Python, we do:
# a, b = b, a
# In our case, we can do the clockwise shift of numbers by:
# board[0][0], board[0][1], board[1][1], board[1][0] = board[1][0], board[0][0], board[0][1], board[1][1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Applying the same idea to the three other buttons, we will have the following functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def shiftQuadrant1(originalBoard):
    board = deepcopy(originalBoard)
    board[0][0], board[0][1], board[1][1], board[1][0] = board[1][0], board[0][0], board[0][1], board[1][1]
    return board

def shiftQuadrant2(originalBoard):
    board = deepcopy(originalBoard)
    board[0][1], board[0][2], board[1][2], board[1][1] = board[1][1], board[0][1], board[0][2], board[1][2]
    return board

def shiftQuadrant3(originalBoard):
    board = deepcopy(originalBoard)
    board[1][0], board[1][1], board[2][1], board[2][0] = board[2][0], board[1][0], board[1][1], board[2][1]
    return board

def shiftQuadrant4(originalBoard):
    board = deepcopy(originalBoard)
    board[1][1], board[1][2], board[2][2], board[2][1] = board[2][1], board[1][1], board[1][2], board[2][2]
    return board
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Board Comparisons
&lt;/h3&gt;

&lt;p&gt;Awesome! Now let's set up other functions that will help us out with comparison:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def isSolved(board):
    return areBoardsEqual(board, solved_board)

def areBoardsEqual(board1, board2):
    return board1 == board2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Solver: Recursive Backtracking
&lt;/h3&gt;

&lt;p&gt;Now, let's talk about the actual implementation of Recursive backtracking.&lt;/p&gt;

&lt;p&gt;We start by defining our initial state. Now, from that state, we have to explore the new states that we can arrive at if we perform one of the quadrant shift operations.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ygt3zsn9gfek9n1wxvc.jpg" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ygt3zsn9gfek9n1wxvc.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you had experience implementing a searching algorithm before, then you probably have noticed that we are actually implementing Depth-First Search algorithm.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solver: Pseudocode
&lt;/h3&gt;

&lt;p&gt;Our recursive function will have the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Base case: Is the current board in a solved state? If yes, then terminate.&lt;/li&gt;
&lt;li&gt;Call the &lt;code&gt;solver&lt;/code&gt; function again, but this time, explore the new states achieved after shifting to Q1, Q2, Q3, and Q4 from the current state.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Attempt #1
&lt;/h3&gt;

&lt;p&gt;Putting that into code, we will have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def solve(board, stack):
    if(isSolved(board)):
        print("Solution: ", stack)

    solve(shiftQuadrant1(board), stack + ['Q1'])
    solve(shiftQuadrant2(board), stack + ['Q2'])
    solve(shiftQuadrant3(board), stack + ['Q3'])
    solve(shiftQuadrant4(board), stack + ['Q4'])

# Calling the function with initial value setup:
solve(initial_board, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks neat, right? Not quite. There's actually a problem with our algorithm.&lt;/p&gt;

&lt;p&gt;One, our algorithm will get stuck to one of the states since we are not tracking if we have explored a state before.&lt;/p&gt;

&lt;p&gt;For example, the search algorithm will try doing the shift with [Q1, Q1, Q1, Q1, ...] which returns it to the prior state.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpb9qn5rra6wat2pvgm5c.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpb9qn5rra6wat2pvgm5c.png" alt="Infinite loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix this, let's keep track of all the states of the board that we have already seen. This is done by having a variable to keep track of the explored states and pass it as a function parameter every time we explore a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attempt #2
&lt;/h3&gt;

&lt;p&gt;Our new and improved function will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def isBoardInPastBoardStates(board, pastBoardStates):
    for state in pastBoardStates:
        if(areBoardsEqual(board, state)):
            return True
    return False

def solve(board, stack, pastBoardStates):
    if isBoardInPastBoardStates(board, pastBoardStates):
        return

    if(isSolved(board)):
        print("Solution: ", stack)

    solve(shiftQuadrant1(board), stack + ['Q1'], pastBoardStates + [board])
    solve(shiftQuadrant2(board), stack + ['Q2'], pastBoardStates + [board])
    solve(shiftQuadrant3(board), stack + ['Q3'], pastBoardStates + [board])
    solve(shiftQuadrant4(board), stack + ['Q4'], pastBoardStates + [board])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we added &lt;code&gt;isBoardInPastBoardStates&lt;/code&gt; function to make sure we stop considering states if they were already explored.&lt;/p&gt;

&lt;p&gt;However, our function is not complete yet.&lt;/p&gt;

&lt;p&gt;If you run this, the algorithm will try the following shifting sequence: [Q1, Q1, Q1, Q2, Q1, Q1, Q1, Q2, Q1, Q1, Q1, Q2...] and so on. It will explore deeper on that branch while potentially missing out other viable solutions in other branches. What's our next step then?&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjftr3at3fwl5sc23jmhg.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjftr3at3fwl5sc23jmhg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Iterative Deepening Depth-First Search
&lt;/h3&gt;

&lt;p&gt;Iterative Deepening Depth-First Search. That's a mouthful to read. Good thing it's also known as IDS or IDDFS.&lt;/p&gt;

&lt;p&gt;While I do remember this search algorithm from my CompSci days, I wasn't conscious that I was using it when I was writing the solution until I looked it up online. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IDDFS combines depth-first search’s space-efficiency and breadth-first search’s fast search (for nodes closer to root).&lt;/p&gt;

&lt;p&gt;How does IDDFS work?&lt;br&gt;
IDDFS calls DFS for different depths starting from an initial value. In every call, DFS is restricted from going beyond given depth. So basically we do DFS in a BFS fashion.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This algorithm helps us find better candidate solutions. We can start by setting the maximum depth to be 1, 2, 3, and so on until we find the least depth that has a solution.&lt;/p&gt;

&lt;p&gt;For simplicity's sake, I hard-coded the depth-limit named &lt;code&gt;maxMoves&lt;/code&gt; and noticed that it's in-depth 11 where we first found a solution.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frb9k06av0rae93tkb72w.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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frb9k06av0rae93tkb72w.png" alt="IDDFS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final attempt: IDDFS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def solve(board, stack, pastBoardStates, maxMoves):
    if(len(stack) &amp;gt;= maxMoves):
        return

    if(isSolved(board)):
        print("Solution: ", stack)

    if isBoardInPastBoardStates(board, pastBoardStates):
        return

    solve(shiftQuadrant1(board), stack + ['Q1'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant2(board), stack + ['Q2'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant3(board), stack + ['Q3'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant4(board), stack + ['Q4'], pastBoardStates + [board], maxMoves)

maxMoves = 11
solve(initial_board, [], [], maxMoves)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;maxMoves&lt;/code&gt; represents the limit of our depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from copy import deepcopy

initial_board = [
    [7,6,5],
    [8,4,9],
    [3,2,1]
]

solved_board = [
    [1,2,3],
    [4,5,6],
    [7,8,9]
]

def isSolved(board):
    return areBoardsEqual(board, solved_board)

def areBoardsEqual(board1, board2):
    return board1 == board2

# Operations
def shiftQuadrant1(originalBoard):
    board = deepcopy(originalBoard)
    board[0][0], board[0][1], board[1][1], board[1][0] = board[1][0], board[0][0], board[0][1], board[1][1]
    return board

def shiftQuadrant2(originalBoard):
    board = deepcopy(originalBoard)
    board[0][1], board[0][2], board[1][2], board[1][1] = board[1][1], board[0][1], board[0][2], board[1][2]
    return board

def shiftQuadrant3(originalBoard):
    board = deepcopy(originalBoard)
    board[1][0], board[1][1], board[2][1], board[2][0] = board[2][0], board[1][0], board[1][1], board[2][1]
    return board

def shiftQuadrant4(originalBoard):
    board = deepcopy(originalBoard)
    board[1][1], board[1][2], board[2][2], board[2][1] = board[2][1], board[1][1], board[1][2], board[2][2]
    return board

def isBoardInPastBoardStates(board, pastBoardStates):
    for state in pastBoardStates:
        if(areBoardsEqual(board, state)):
            return True
    return False

attempt = 0
def solve(board, stack, pastBoardStates, maxMoves):
    global attempt
    attempt = attempt + 1

    if(len(stack) &amp;gt;= maxMoves):
        return

    if(isSolved(board)):
        print("Attempt: ", attempt, "Solution: ", stack)

    if isBoardInPastBoardStates(board, pastBoardStates):
        return

    solve(shiftQuadrant1(board), stack + ['Q1'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant2(board), stack + ['Q2'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant3(board), stack + ['Q3'], pastBoardStates + [board], maxMoves)
    solve(shiftQuadrant4(board), stack + ['Q4'], pastBoardStates + [board], maxMoves)

maxMoves = 11
solve(initial_board, [], [], maxMoves)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the code above, we arrive with the following solutions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Attempt # 2472679 Solution:  ['Q2', 'Q4', 'Q3', 'Q4', 'Q1', 'Q3', 'Q1', 'Q3', 'Q2', 'Q3']
Attempt # 3452929 Solution:  ['Q3', 'Q3', 'Q4', 'Q1', 'Q2', 'Q2', 'Q2', 'Q3', 'Q3', 'Q1']
Attempt # 3467708 Solution:  ['Q3', 'Q3', 'Q4', 'Q2', 'Q1', 'Q1', 'Q3', 'Q3', 'Q1', 'Q2']
Attempt # 3621688 Solution:  ['Q3', 'Q4', 'Q2', 'Q1', 'Q3', 'Q1', 'Q3', 'Q2', 'Q1', 'Q3']
Attempt # 4340258 Solution:  ['Q4', 'Q2', 'Q3', 'Q1', 'Q1', 'Q2', 'Q1', 'Q3', 'Q1', 'Q3']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solving the puzzle
&lt;/h2&gt;

&lt;p&gt;Here's a GIF that solves the puzzle following the solutions found by our code: &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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1xw7hrnt89q1gigrvac5.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1xw7hrnt89q1gigrvac5.gif" alt="Solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimisation: Concurrency
&lt;/h3&gt;

&lt;p&gt;Our code ran for almost 40 seconds to find 5 solutions. One way to improve its speed is by leveraging concurrency as it will enable us to explore multiple states in parallel, and consolidate all solutions discovered at the end.&lt;/p&gt;

&lt;p&gt;If you want to access the raw code, you can find it in &lt;a href="https://github.com/TigerTopher/puzzle-box-solver" rel="noopener noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;p&gt;If you know how to solve this problem logically, feel free to leave a comment. Happy solving!&lt;/p&gt;

&lt;p&gt;PS. This article is not sponsored by Enchambered, but I do want to give them a huge shout out for building the Escape Room puzzles that I have thoroughly enjoyed solving with my friends.&lt;/p&gt;

&lt;p&gt;Fin. 🐟&lt;/p&gt;

</description>
      <category>python</category>
      <category>recursion</category>
      <category>puzzles</category>
    </item>
    <item>
      <title>Routing to EC2 without EIP</title>
      <dc:creator>Topher Vizcarra</dc:creator>
      <pubDate>Thu, 18 Jun 2020 16:08:52 +0000</pubDate>
      <link>https://dev.to/tigertopher/routing-to-ec2-without-eip-3eep</link>
      <guid>https://dev.to/tigertopher/routing-to-ec2-without-eip-3eep</guid>
      <description>&lt;h1&gt;
  
  
  TL;DR
&lt;/h1&gt;

&lt;p&gt;Explicitly define that the &lt;code&gt;aws_instance&lt;/code&gt; associates a public IP address and then create a Route 53 &lt;code&gt;A&lt;/code&gt; record that points to the instance's public IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
resource "aws_route53_record" "www" {
  zone_id = "..." # PlaceHosted zone ID here

  name    = "foo_subdomain"
  type    = "A"
  ttl     = "300"
  records = ["${aws_instance.foo.public_ip}"]
}

resource "aws_instance" "foo" {
  ...
  associate_public_ip_address = true
  ...
}
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Where's the load balancer?
&lt;/h2&gt;

&lt;p&gt;Ideally, you want to have a scalable setup where every service is containerised, put them in a private VPC, setup load balancer to handle public requests, and then setup routing for the requests to the services. Unfortunately, I had a setup where I was forced to create a &lt;a href="https://medium.com/@Joachim8675309/devops-concepts-pets-vs-cattle-2380b5aab313"&gt;pet server instead of cattle&lt;/a&gt; in a herd.&lt;/p&gt;

&lt;p&gt;I needed to host a network management tool that required old-school ways of setting up and heavily relying on the state of the disk. To make my life harder it only worked for Ubuntu and it even required me to do a few custom configuration to make it work on the latest distro. 🤷 Luckily, the instance is unlikely to have insane traffic so I am not forced to setup a load balancer to handle scaling issues.&lt;/p&gt;

&lt;p&gt;Since the software itself made it hard to containerise it, I needed to do some compromises. I made sure to harden the instance such as setting up the security group to restrict access to our office IP, and I only allowed shell access through AWS Session Manager. To improve fault-tolerance we setup Data Lifecycle Manager to take snapshots of the instance's EBS volume in regular intervals. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why not use Elastic IPs (EIPs)?
&lt;/h2&gt;

&lt;p&gt;To differentiate public IPs from EIPs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Public IP addresses are dynamic - i.e. if you stop/start your instance you get reassigned a new public IP.&lt;/p&gt;

&lt;p&gt;Elastic IPs get allocated to your account, and stay the same - it's up to you to attach them to an instance or not. You could say they are static public IP addresses.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;EIPs are great for keeping a consistent public IP address. It works for use cases where you need to change the instances behind the IP.&lt;/p&gt;

&lt;p&gt;For my use case, I don't really care if the public IP changed since I don't intend to change the instance every time. If it does change, I'll simply run terraform again to update the Route53 record with the new public IP of the instance.&lt;/p&gt;

&lt;p&gt;Fin. 🐟&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
