<?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: Jenson</title>
    <description>The latest articles on DEV Community by Jenson (@nonfungiblejc).</description>
    <link>https://dev.to/nonfungiblejc</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%2F1369875%2F4b367c11-e01a-4119-b1ae-93e524933813.jpeg</url>
      <title>DEV Community: Jenson</title>
      <link>https://dev.to/nonfungiblejc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nonfungiblejc"/>
    <language>en</language>
    <item>
      <title>Solving Rush Hour with Solidity (1)</title>
      <dc:creator>Jenson</dc:creator>
      <pubDate>Tue, 26 Mar 2024 19:48:19 +0000</pubDate>
      <link>https://dev.to/nonfungiblejc/solving-rush-hour-with-solidity-1-5437</link>
      <guid>https://dev.to/nonfungiblejc/solving-rush-hour-with-solidity-1-5437</guid>
      <description>&lt;p&gt;Solidity, the popular smart contract programming language for Ethereum, is usually associated with complex financial applications and dApps. But what if we used its logical capabilities for something lighter – a fun puzzle game? In this post, we'll explore how to build a basic Rush Hour puzzle solver using Solidity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rush Hour Puzzle
&lt;/h2&gt;

&lt;p&gt;Rush Hour is a sliding block puzzle invented by Nob Yoshigahara in the 1970s. It was first sold in the United States in 1996. It is now being manufactured by ThinkFun (formerly Binary Arts).&lt;br&gt;
&lt;a href="https://www.wikiwand.com/en/Rush_Hour_(puzzle)"&gt;https://www.wikiwand.com/en/Rush_Hour_(puzzle)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Let's get it work
&lt;/h2&gt;

&lt;p&gt;Here is the logic optimization board that I draw. Not sure if you can understand it but anyways...&lt;br&gt;
&lt;a href="https://whimsical.com/rush-hour-solver-logic-optimization-VACNpDNbPCAC7movuuX6iG"&gt;Logic Board&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Encoding the park Map
&lt;/h3&gt;

&lt;p&gt;One approach is to represent the entire playing field as a single uint64 which stores as 8 bytes. Each bit in the uint64 can signify a space on the grid. A value of 1 indicates a blocked space (like a fence), and 0 represents an open space (like a parking spot).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 0 0 0 0 0 0 0 0
 0 1 1 1 1 1 1 0
 0 1 1 1 1 1 1 0
 0 1 1 1 1 1 1 0
 0 1 1 1 1 1 1 0
 0 1 1 1 1 1 1 0
 0 1 1 1 1 1 1 0
 0 0 0 0 0 0 0 0
&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; 1 1 1 1 1 1 1 1
 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 1
 1 0 0 0 0 0 0 1
 1 1 1 1 1 1 1 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Encoding the car
&lt;/h3&gt;

&lt;p&gt;Solidity doesn't have a native data type to directly represent a car with its position and orientation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bit Manipulation: We can manipulate specific bits within the uint64 representing the grid to indicate the car's location and size based on its length (e.g., setting bits corresponding to the car's position).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 1 1 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the car occupying position (2, 0) with a horizontal orientation and length 2 could be represented by setting the bits at positions 36 and 37 in the uint256 representing the grid. This effectively translates to &lt;u&gt;2^36 + 2^37&lt;/u&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculating Next Position
&lt;/h3&gt;

&lt;p&gt;Once we have the direction encoded, we can calculate the car's next position based on its current location and the chosen direction. This involves bit shifting operations within the uint64 representing the grid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For example:&lt;/strong&gt;&lt;br&gt;
Moving the car right from position (2, 0) (represented by 2^36 + 2^37) would involve shifting the car's bit representation by one position to the right. This translates to dividing by 2: (2^36 + 2^37) / 2 = &lt;u&gt;2^35 + 2^36&lt;/u&gt;.&lt;br&gt;
Moving the car down eight positions would involve shifting the car's bit representation eight positions to the right. This translates to dividing by 2 raised to the power of 8: (2^36 + 2^37) / 2^8 = &lt;u&gt;2^28 + 2^29&lt;/u&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Collision Detection with Bitwise Operations
&lt;/h3&gt;

&lt;p&gt;To check if the car's next position is occupied by another car or a fence, we can leverage bitwise operations. Here's the approach:&lt;/p&gt;

&lt;p&gt;Exclusive OR: Perform an exclusive OR (XOR) operation between the following:&lt;/p&gt;

&lt;p&gt;A uint256 representing the full park map with all bits set to 1 (occupied spaces).&lt;br&gt;
A uint256 representing the fence with only the outer border bits set.&lt;br&gt;
A uint256 representing the car's next position after the movement calculation.&lt;br&gt;
Collision Check: If the result of the XOR operation is greater than 0, it indicates that at least one bit in the car's next position overlaps with either a blocked space or the fence, signifying a collision.&lt;/p&gt;
&lt;h3&gt;
  
  
  Packing Car Positions
&lt;/h3&gt;

&lt;p&gt;One efficient way that I am using to represent the entire car configuration is to create a single uint64 that holds the bitwise representation of all cars on the grid.&lt;/p&gt;
&lt;h3&gt;
  
  
  Memoization - Remembering Visited Paths
&lt;/h3&gt;

&lt;p&gt;To optimize the search process, I would like to introduce the concept of memoization. This technique involves storing the results of expensive function calls to avoid redundant calculations.&lt;/p&gt;

&lt;p&gt;In the context of Rush Hour, we can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Track Visited Paths: Maintain a data to store the historical positions of each car during the search process.&lt;/li&gt;
&lt;li&gt;Check Before Moving: Before attempting a car movement, check the memoization data to see if the car has already occupied that position in a previous iteration.&lt;/li&gt;
&lt;li&gt;Skip Redundant Moves: If the car's intended position is found in its historical paths, skip that move and explore other possibilities. This prevents revisiting already explored dead-ends, significantly reducing the search space.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Impact on Complexity
&lt;/h3&gt;

&lt;p&gt;By employing memoization, the number of explored possibilities can be drastically reduced compared to a brute-force approach that tries every single move. In your example:&lt;/p&gt;

&lt;p&gt;Brute Force: Without memoization, exploring all possible cases for a single car on a board width of n would result in 2^36 possibilities.&lt;br&gt;
Memoization with Bounds: With memoization, the maximum number of explored possibilities for a car with i ID (car number i+1 on the map) and ending position at index j on the board can be estimated by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;∑((5^i)*j)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Second topic is coming
&lt;/h2&gt;

&lt;p&gt;I will continue on second post&lt;/p&gt;

</description>
      <category>rushhours</category>
      <category>puzzle</category>
      <category>solidity</category>
      <category>gasoptimization</category>
    </item>
    <item>
      <title>Memory Mapping for Rush Hour in Solidity (A Novel Approach)</title>
      <dc:creator>Jenson</dc:creator>
      <pubDate>Fri, 22 Mar 2024 09:49:51 +0000</pubDate>
      <link>https://dev.to/nonfungiblejc/memory-mapping-for-rush-hour-in-solidity-a-novel-approach-50bl</link>
      <guid>https://dev.to/nonfungiblejc/memory-mapping-for-rush-hour-in-solidity-a-novel-approach-50bl</guid>
      <description>&lt;p&gt;I approached solving Rush Hour puzzles using Solidity's core data structures and logic capabilities. Now, let's dive into a more experimental approach that leverages memory mapping for potential performance gains.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory Allocation based on Car Count
&lt;/h2&gt;

&lt;p&gt;The core idea is to pre-allocate memory during board initialization. The total memory size is calculated based on the number of cars (cars) on the board. Here's the logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exponential Growth: We assume each car can have up to five different positions/orientations (considering up, down, left, right, and no movement).&lt;/li&gt;
&lt;li&gt;Total Cases: The total number of possible game states is calculated as cars raised to the power of cars (i.e., cars ^ cars). This represents the maximum number of memory slots that might be needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  _createSnapMapMemorySpace() Function
&lt;/h2&gt;

&lt;p&gt;The contract has a function named _createSnapMapMemorySpace responsible for allocating the memory space based on the calculated size.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/JensonCollins/rush-hour-puzzle/blob/main/contracts/RushHourSolver.sol#L359"&gt;https://github.com/JensonCollins/rush-hour-puzzle/blob/main/contracts/RushHourSolver.sol#L359&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimizing Memory Usage (is3Len parameter)
&lt;/h3&gt;

&lt;p&gt;To potentially reduce memory allocation size, we can introduce an optional parameter is3Len. This flag might indicate if any car on the board has a length of 3 units.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Impact on Weight: Cars with a length of 3 can occupy more than one grid space simultaneously. This can affect the total number of possible game states, potentially reducing the required memory allocation compared to the cars ^ cars formula.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step Count and Stack Overflow Protection
&lt;/h2&gt;

&lt;p&gt;During the search process, a variable named stepNum might track the depth within the exploration tree (representing the number of moves made).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stack Overflow Risk: Solidity has limitations on stack usage. If the search goes too deep (i.e., stepNum becomes too large), a StackOverflow error might occur.&lt;/li&gt;
&lt;li&gt;Mitigating the Risk: To prevent this error, I declared a constant MAX_STACK_DEEP (e.g., set to 36) to limit the exploration depth.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Efficient Single Byte Storage with Assembly
&lt;/h2&gt;

&lt;p&gt;Solidity v0.8 introduced the mstore8 assembly opcode. This allows setting a single byte in memory storage.&lt;/p&gt;

&lt;p&gt;Saving Step Count: We can leverage mstore8 to store the stepNum value in just one byte within the allocated memory space.&lt;br&gt;
&lt;a href="https://veridelisi.medium.com/learn-evm-opcodes-vii-5f7d778d45b5#:~:text=in%20this%20lesson.-,MSTORE8,only%20valid%20for%2032%20bytes."&gt;mstore8&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Memory mapping for Rush Hour in Solidity is an innovative concept with potential benefits. However, careful consideration of memory constraints and trade-offs is crucial before implementing it in real-world applications.  For complex scenarios, alternative approaches like efficient data structures and heuristic search algorithms might be more practical.&lt;/p&gt;

</description>
      <category>mapping</category>
      <category>solidity</category>
      <category>optimize</category>
      <category>rushhours</category>
    </item>
  </channel>
</rss>
