<?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: Hessam A. Cheraghi</title>
    <description>The latest articles on DEV Community by Hessam A. Cheraghi (@hessamcheraghi).</description>
    <link>https://dev.to/hessamcheraghi</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%2F2901225%2F9fcfc7ef-61a4-438f-9566-547cfc2cfed1.png</url>
      <title>DEV Community: Hessam A. Cheraghi</title>
      <link>https://dev.to/hessamcheraghi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hessamcheraghi"/>
    <language>en</language>
    <item>
      <title>Hopscotch Problem In Python</title>
      <dc:creator>Hessam A. Cheraghi</dc:creator>
      <pubDate>Sat, 08 Mar 2025 04:14:21 +0000</pubDate>
      <link>https://dev.to/hessamcheraghi/hopscotch-problem-in-python-3nke</link>
      <guid>https://dev.to/hessamcheraghi/hopscotch-problem-in-python-3nke</guid>
      <description>&lt;p&gt;Imagine you’re sitting by the window, coding. Suddenly, your attention is drawn to a little girl outside, playing hopscotch. She carefully jumps across the drawn tiles—sometimes skipping one and sometimes making a big leap over two. For a moment, you get distracted and pause your work.&lt;/p&gt;

&lt;p&gt;At that moment, your logical mind becomes curious: If the hopscotch tiles are lined up in a row and the girl only jumps one or two steps, how many different ways are there to reach the last tile?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx87rk0kcx45lpr0hkv18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx87rk0kcx45lpr0hkv18.png" alt="A hopscotch pattern with n squares" width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Combinatorics Solution
&lt;/h2&gt;

&lt;p&gt;Someone asked me this question in an algorithmic interview, and the first solution that came to mind was using combinatorics. First, we need to determine how many single jumps and how many double jumps are required to reach the last square.&lt;/p&gt;

&lt;p&gt;For example, if there are four squares, there are three different ways to reach the end:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four single jumps&lt;/li&gt;
&lt;li&gt;Two single jumps and one double jump&lt;/li&gt;
&lt;li&gt;Two consecutive double jumps&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Then I realized that the order of jumps also affects the total number of possibilities. A formula from combinatorics came to mind which could be used to calculate the number of possible arrangements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total arrangements&lt;/strong&gt; = &lt;strong&gt;Factorial of total jumps&lt;/strong&gt; divided by &lt;strong&gt;the factorial of repeated jumps&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Finally, I computed the total number of possibilities for all possible ways. At first glance, the code I wrote seemed to have a time complexity of &lt;code&gt;O(N²)&lt;/code&gt; due to two loops, but since these loops were independent of each other, the actual complexity was &lt;code&gt;O(N)&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Recursion Solution
&lt;/h2&gt;

&lt;p&gt;After solving the problem, I analyzed the results and noticed a pattern: The solution for a given number of squares was equal to the sum of the solutions for the previous two numbers. That rings a bell, &lt;strong&gt;The famous Fibonacci sequence&lt;/strong&gt;! So, I decided to use this approach to solve the problem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6p73rh7swras2m110qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz6p73rh7swras2m110qb.png" alt="Hopscotch problem solutions for inputs from 1 to 5" width="565" height="286"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;h2&gt;
  
  
  Memoized Recursion Solution
&lt;/h2&gt;

&lt;p&gt;When testing my code, I realized that, for large inputs, my implementation was extremely slow. I knew that the time complexity of the Fibonacci function is &lt;code&gt;O(2ⁿ)&lt;/code&gt;. The first improvement that came to mind was using &lt;strong&gt;memoization&lt;/strong&gt;: defining a &lt;code&gt;cache&lt;/code&gt; to store function inputs and outputs. If the function was called with  the same input, instead of calculating the result, get the output directly from the cache.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This code was faster than the combinatorics solution for small inputs, but for large inputs, such as calculating the solution for 30 hopscotch tiles, it was much slower. Also, for inputs greater than 1000, I ran into a &lt;a href="https://docs.python.org/3/library/exceptions.html#RecursionError" rel="noopener noreferrer"&gt;RecursionError&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  For Loop Solution
&lt;/h2&gt;

&lt;p&gt;It was obvious that, to determine the solution for any given input, I only needed the previous two results. This meant that I could solve the problem with a simple loop.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This simple loop was able to outperform the combinatorics solution across all inputs by a constant factor. Additionally, its time complexity was &lt;code&gt;O(N)&lt;/code&gt;, and its space complexity was &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memoized Combinatorics Solution
&lt;/h2&gt;

&lt;p&gt;At this point, I was wondering why the combinatorics approach was slower. After a bit of research, I found that in Python, factorial calculations are performed using a for loop, meaning that what I initially thought was &lt;code&gt;O(N)&lt;/code&gt; was actually &lt;code&gt;O(N²)&lt;/code&gt;. I also noticed that many factorials were being recalculated unnecessarily, so I considered memoizing them.&lt;/p&gt;

&lt;p&gt;Surprisingly, this did not improve performance. In fact, it made the algorithm slower due to the increased space complexity. At this point, I stopped optimizing further and submitted the simple loop solution as my final answer.&lt;/p&gt;




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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8uoktt07ydfl79kblnc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8uoktt07ydfl79kblnc.png" alt="Performance comparison of the algorithms for inputs 10, 20, and 30" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think? If you were asked this question, how would you approach it? Do you think this algorithm can be optimized further? Let me know in the comments!&lt;/p&gt;




&lt;p&gt;P.S. 1: I used the &lt;a href="https://github.com/tonybaloney/rich-bench" rel="noopener noreferrer"&gt;richbench&lt;/a&gt; library to test the speed of the algorithms. These are the specifications of the hardware I was testing on:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CPU: 11th Gen Intel i5-11400H
Memory: 15694 MiB
GPU: Intel TigerLake-H GT1 [UHD Graphics]
OS: Zorin OS 17.2 x86_64
PYTHON_VERSION: 3.12.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;P.S. 2: In Python, &lt;a href="https://docs.python.org/3/library/functools.html#functools.cache" rel="noopener noreferrer"&gt;@functools.cache&lt;/a&gt; is typically used for memoization, but in an algorithmic interview, you should implement it yourself.&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>algorithms</category>
      <category>interview</category>
      <category>python</category>
    </item>
  </channel>
</rss>
