<?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>Forem: Sagar Chakravarthy</title>
    <description>The latest articles on Forem by Sagar Chakravarthy (@bpsagar).</description>
    <link>https://forem.com/bpsagar</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%2F612268%2F4b25a40b-4a33-4645-8424-549e758978e7.jpg</url>
      <title>Forem: Sagar Chakravarthy</title>
      <link>https://forem.com/bpsagar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bpsagar"/>
    <language>en</language>
    <item>
      <title>Building a quick-chat view for Google Meet</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Mon, 08 May 2023 02:40:56 +0000</pubDate>
      <link>https://forem.com/bpsagar/building-a-quick-chat-view-for-google-meet-5d0m</link>
      <guid>https://forem.com/bpsagar/building-a-quick-chat-view-for-google-meet-5d0m</guid>
      <description>&lt;p&gt;&lt;em&gt;This is the second post about building Meaty Meets, you can read the first one &lt;a href="https://bpsagar.substack.com/p/building-a-chrome-extension-to-join"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤯 Problem
&lt;/h2&gt;

&lt;p&gt;As a presenter, I have noticed that it's easy to miss chat notifications during Google Meet calls. People, including myself, often struggle to locate the Google Meet tab amidst a sea of open tabs whenever there is a notification sound. This can lead to awkward pauses, as you thumb through all your open tabs, revealing to the audience who you really are (of course, we wouldn’t want that).&lt;/p&gt;

&lt;p&gt;As the cliche goes, there had to be a better way!&lt;/p&gt;

&lt;h2&gt;
  
  
  💡Solution
&lt;/h2&gt;

&lt;p&gt;The solution comprises of three main parts, which are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Watching for new messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Transmitting and storing the messages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Displaying the messages&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Content scripts
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Content scripts are files that run in the context of web pages. By using the standard &lt;a href="https://developer.mozilla.org/docs/Web/API/Document_Object_Model"&gt;Document Object Model&lt;/a&gt; (DOM), they are able to read details of the web pages the browser visits, make changes to them, and pass information to their parent extension&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://developer.chrome.com/docs/extensions/mv3/content_scripts/"&gt;Source&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Content scripts can be used to watch the Google Meet page for any changes in the chat box section where new messages would show up. Vanilla JavaScript can be used to check the state of the chat box every fixed interval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Message passing
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Communication between extensions and their content scripts works by using message passing. Either side can listen for messages sent from the other end, and respond on the same channel.&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://developer.chrome.com/docs/extensions/mv3/messaging/"&gt;Source&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One-way messages were sufficient for this use-case; new messages detected by the content script could be sent to the Service Worker through the &lt;code&gt;sendMessage&lt;/code&gt; function, and the service worker listened to the message from content scripts and stored them in the local storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Popup action
&lt;/h3&gt;

&lt;p&gt;Extensions provide the functionality of showing custom popup UI when the extension icon on the toolbar is clicked. This was utilized to show the messages as it's easily accessible throughout.&lt;/p&gt;

&lt;p&gt;As an icing on the cake, extension also provide support for displaying a badge:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A bit of text layered over the icon. This makes it easy to update the action to display a small amount of information about the state of the extension, such as a counter. The badge has a text component and a background color.&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://developer.chrome.com/docs/extensions/reference/action/#badge"&gt;Source&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I used this to show notification-count like UI for new messages.&lt;/p&gt;




&lt;p&gt;That’s it, combining all three parts resulted in an easy-to-access chat box extension for Google Meet:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LtDJ5qVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://substackcdn.com/image/fetch/f_auto%2Cq_auto:good%2Cfl_progressive:steep/https%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252Ff5728e00-3f48-4d84-ba8e-e837df20a03c_1270x760.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LtDJ5qVT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://substackcdn.com/image/fetch/f_auto%2Cq_auto:good%2Cfl_progressive:steep/https%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252Ff5728e00-3f48-4d84-ba8e-e837df20a03c_1270x760.jpeg" alt="" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Final thoughts
&lt;/h2&gt;

&lt;p&gt;In conclusion, the power of browser extensions is truly remarkable. With capabilities such as storage, inter-process communication, and the ability to build frontends without hosting, extensions provide an incredible opportunity for developers to create unique and useful tools that enhance the user experience.&lt;/p&gt;

&lt;p&gt;Having discovered the potential of extensions, I'm excited to explore further and find more ways to leverage them in my work. Compared to traditional web apps, extensions offers features that is hard to match. It's a technology that's definitely worth exploring and experimenting with for any developer looking to build innovative tools that solve real-world problems.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Chrome extension to join meetings on time</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Sun, 26 Mar 2023 09:01:27 +0000</pubDate>
      <link>https://forem.com/bpsagar/building-a-chrome-extension-to-join-meetings-on-time-33mg</link>
      <guid>https://forem.com/bpsagar/building-a-chrome-extension-to-join-meetings-on-time-33mg</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;From concept to implementation of Meaty Meets&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤯 Problem
&lt;/h2&gt;

&lt;p&gt;I've lost count of how many times I've accidentally closed a meeting notification and found myself frantically searching through my calendar for the link at the last minute.&lt;/p&gt;

&lt;p&gt;So, I started wondering: could I automate the process of opening links just in time for the meeting? Building a browser extension was the only way to open a new tab or window automatically without any user interaction. And I wanted to create a simple MVP to validate the idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡Solution
&lt;/h2&gt;

&lt;p&gt;At my workplace, we use Google Suite and Google Meet so I set out to solve problem for myself for dogfooding (I find dogfooding term amusing). I considered implementing Google OAuth on the server side, however, doing so would introduce a host of complexities. Not only would I have to deploy and maintain a server, but I would also need to seamlessly hand-off the access token from the server to the Chrome extension.&lt;/p&gt;

&lt;p&gt;Without a server and in turn no publicly available callback URL, I wasn't sure how to make the post login redirection work, as the Chrome extension's path is only available locally. That's when I discovered Chrome Identity API.&lt;/p&gt;

&lt;p&gt;With just a couple of lines of code, I could get the user's access token without the need for any backend or UI. Once the &lt;code&gt;clientId&lt;/code&gt; is configured, the following snippet can be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome.identity.getAuthToken({ interactive: true }, function(token) {
  // Use the token to call the Google Calendar API
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When &lt;code&gt;interactive&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;, it opens up the Sign in screen for the user to select the Google account. With the returned access token after signing in (which should have read-only access to the calendar), I was able to fetch upcoming meetings and open the URL on time. It was an easy and elegant solution that saved me a lot of time and effort.&lt;/p&gt;

&lt;p&gt;I wrapped this solution with a couple of configuration options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customize how early you’d like to join the meetings, and&lt;/li&gt;
&lt;li&gt;An option to open meeting attachments as well
Here’s how it looks 👇&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--in0gt9Bz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4n2jmo3tqc9smdqxp8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--in0gt9Bz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b4n2jmo3tqc9smdqxp8k.png" alt="Screenshot of Meaty Meet's configuration screen" width="880" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Final thoughts
&lt;/h2&gt;

&lt;p&gt;Integrating Google authentication with Chrome extension was a breeze. It opens up so many possibilities without needing a complex setup. Browser extensions are great platforms for implementing low-cost side projects, in my case it was actually 0!&lt;/p&gt;

&lt;p&gt;I have been using Meaty Meets myself to open meeting links a few minutes in advance and I quite like the convenience (of course I might be biased). If you use Google Suite and Google Meet at work, try out Meaty Meets and share your thoughts. It's free and takes only a couple of minutes to set it up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In the next article, I’ll write about how I ideated and built the quick chat view right in the extension’s popup. Stay tuned!&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Resume review thread</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Tue, 07 Dec 2021 16:11:42 +0000</pubDate>
      <link>https://forem.com/bpsagar/resume-review-thread-3842</link>
      <guid>https://forem.com/bpsagar/resume-review-thread-3842</guid>
      <description>&lt;p&gt;👋 Hey everyone! I'm Sagar, Full Stack engineer based in Singapore. I've been working in the software / web development industry for almost 7 years now.&lt;/p&gt;

&lt;p&gt;I've been part of a number of interviews both as an interviewer and interviewee. I would like to give back to the community by reviewing and giving feedback for your resume / portfolio. Feel free to drop links to your resumes in the comments 👇&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Automating personal investment reports with Gitlab Pages and CI/CD pipelines</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Sat, 04 Dec 2021 11:23:03 +0000</pubDate>
      <link>https://forem.com/bpsagar/automating-personal-investment-reports-with-gitlab-pages-and-cicd-pipelines-55jn</link>
      <guid>https://forem.com/bpsagar/automating-personal-investment-reports-with-gitlab-pages-and-cicd-pipelines-55jn</guid>
      <description>&lt;h2&gt;
  
  
  👋 Introduction
&lt;/h2&gt;

&lt;p&gt;I’ve been investing in stocks and mutual funds in the Indian stock market for a couple of years. The reports available on the trading platforms are not sufficient. Moreover, I use multiple platforms making it impossible to look at the health of my portfolio as a whole. So I set out to create my personal investment report. These were my expectations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reports should be available at my fingertips&lt;/li&gt;
&lt;li&gt;Minimal cost and maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can read about my investment strategy &lt;a href="https://medium.com/@bp.sagar/a-year-of-investments-in-indian-markets-72aad24a6064"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💸 Data collection
&lt;/h2&gt;

&lt;p&gt;To create reports I needed two datasets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trades (buys and sells)&lt;/li&gt;
&lt;li&gt;Latest prices&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Trades
&lt;/h3&gt;

&lt;p&gt;The trading platform I use doesn’t provide APIs to fetch my trades automatically 😕. So I manually export the trade book (as CSV) end of every month and store them in a “data” folder in the repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Latest prices
&lt;/h3&gt;

&lt;p&gt;I wrote a python script that crawls the stock exchange sites. It collects the end of day prices which is good enough for my usecase. You can check out the code &lt;a href="https://gist.github.com/bpsagar/a14d2f4fc3ab17cc82b1f6c0acd8549c"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📈 Report generation
&lt;/h2&gt;

&lt;p&gt;With all my trades and their latest prices, I could calculate the metrics that I was interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total investment&lt;/li&gt;
&lt;li&gt;Current value of the portfolio&lt;/li&gt;
&lt;li&gt;Returns (absolute and percentage)&lt;/li&gt;
&lt;li&gt;XIRR (&lt;a href="https://gist.github.com/bpsagar/9f9f530cd8005ba470375e80717ccdb3"&gt;code&lt;/a&gt; to calculate XIRR)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I segregated my trades into equity and debt and calculated the same metrics for the two categories as well. With these metrics, I used &lt;a href="https://pypi.org/project/Jinja2/"&gt;Jinja&lt;/a&gt; templating engine to display these numbers in a simple cards design 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tSB_DjJE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8m2ckym8yz4kimvhdxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tSB_DjJE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8m2ckym8yz4kimvhdxg.png" alt="Screenshot of investment report" width="880" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I set up Gitlab’s pipeline schedule to generate the above HTML file every day after the markets closed. And with Gitlab pages, served the same HTML by placing it inside the public folder. For private repositories, only members can access the Gitlab pages thus making it my &lt;strong&gt;personal&lt;/strong&gt; investment report 👻&lt;/p&gt;




&lt;p&gt;Are you an investor looking to create a personal investment report just like this one? Feel free to drop your comments (or reach out to me on &lt;a href="https://twitter.com/bpsagar"&gt;Twitter&lt;/a&gt;), I can share more details.&lt;/p&gt;




&lt;p&gt;If you liked this article, you can &lt;a href="https://bpsagar.substack.com/"&gt;subscribe&lt;/a&gt; to my newsletter to get new articles directly in your inbox 🙏&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Getting started with writing a simple recursive program</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Sun, 03 Oct 2021 07:43:27 +0000</pubDate>
      <link>https://forem.com/bpsagar/getting-started-with-writing-a-simple-recursive-program-52pi</link>
      <guid>https://forem.com/bpsagar/getting-started-with-writing-a-simple-recursive-program-52pi</guid>
      <description>&lt;p&gt;While writing a recursive program is not a necessary skill, it opens doors to solving problems in new ways that might feel clunky to solve the iterative way.&lt;/p&gt;

&lt;p&gt;Here is a step by step guide to convert an iterative function to a recursive function. The guide works well for cases where we accumulate a result in each iteration.&lt;/p&gt;

&lt;p&gt;I’ll be using factorial of a number as an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Write it the iterative way
&lt;/h3&gt;

&lt;p&gt;We use result variable to accumulate the answer while iterating from 1 through n&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n):
    result = 1
    for i in range(1, n + 1):
        result = result * i
    return result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Parameterize (with defaults) all the variables
&lt;/h3&gt;

&lt;p&gt;Apart from n we are using result and i. We add them as function parameters and set the initial value as default value.&lt;/p&gt;

&lt;p&gt;Our function signature would 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 factorial(n, result=1, i=1):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Function body would be for loop’s body
&lt;/h3&gt;

&lt;p&gt;We make the same updates to variables as in our for loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;result = result * i
i = i + 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end, call its own function with the updated variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return factorial(n, result, i)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our function now looks 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 factorial(n, result=1, i=1):
    result = result * i
    i = i + 1
    return factorial(n, result, i)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Refactor&lt;/strong&gt;: We can directly pass the new values to the function call instead of mutating the variables&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n, result=1, i=1):
    return factorial(n, result * i, i + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Add terminating condition
&lt;/h3&gt;

&lt;p&gt;Add the same for loop’s terminating condition. When we exit our loop, we return the result. We’ll do the same here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n, result=1, i=1):
    if i &amp;gt; n:
        return result
    return factorial(n, result * i, i + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Get rid of extra function parameters
&lt;/h3&gt;

&lt;p&gt;This is where we need to think creatively to get rid of as many function parameters as possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  i. Getting rid of i
&lt;/h4&gt;

&lt;p&gt;n is used only for the termination condition and nowhere else in the logic. So if we reverse the order of iteration (n..1) our termination condition would be i == 0&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n, result=1, i=None):
    i = i or n # initialize i with n
    if i == 0:
        return result
    return factorial(n, result * i, i - 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can clearly see n is not being used anywhere other than initialization. So we can merge n and i into a single variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n, result=1):
    if n == 0:
        return result
    return factorial(n - 1, result * n)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ii. Getting rid of result
&lt;/h4&gt;

&lt;p&gt;To remove result parameter, we update the logic to return result instead of accumulating it. So we would get the following termination condition. Which makes sense, because factorial of 0 is 1.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Since the return value is now result we can apply the operation on the return value instead. Which would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return n * factorial(n - 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. That’s it, we’re done
&lt;/h3&gt;

&lt;p&gt;We now have a recursive function for calculating the factorial&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Another example
&lt;/h2&gt;

&lt;p&gt;Let’s take a popular interview question and apply the same formula to create a recursive function.&lt;/p&gt;

&lt;p&gt;Problem: &lt;a href="https://levelup.gitconnected.com/how-to-solving-chunk-array-interview-questions-a0fe3db12598"&gt;Chunk Array&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Description: Given an array and chunk size as parameters, write a function that will divide the array into several subarrays where each subarray has a length of chunk size&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Step 1: iterative version
def chunk(arr, size):
    chunked = []
    index = 0
    while index &amp;lt; len(arr):
        chunked.append(arr[index:index + size])
        index += size
    return chunked

# Step 2,3,4: add function parameters, body and terminating condition
def chunk(arr, size, index = 0, chunked = []):
    if index &amp;gt;= len(arr):
        return chunked
    return chunk(arr, size, index + size, chunked + arr[index: index + size])

# Step 5.1: get rid of index variable by cutting out the
# chunked part of the arr and assume index is always 0
def chunk(arr, size, chunked = []):
    # update the termination condition accordingly
    if len(arr) == 0:
        return chunked
    chunked.append(arr[:size])    
    return chunk(arr[size:], size, chunked)

# Step 5.2: get rid of `chunked` variable by returning
# the result and extracting the operation outside
def chunk(arr, size):
    # termination condition
    if len(arr) &amp;lt;= size:
        return [arr]
    return [arr[:size]] + chunk(arr[size:], size, chunked)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final code looks like a recursive mathematical definition of a function. If we already have the definition, it would be as easy as writing the same with a programming language. So, often finding a recursive solution would be about finding such definitions that can solve the problem.&lt;/p&gt;

&lt;p&gt;While this seems more mathematical, I personally feel recursive programs are best for solving problems involving combinations and patterns. I’ll be writing an article about this pretty soon, &lt;a href="https://bpsagar.substack.com/p/getting-started-with-writing-a-simple?showWelcome=true"&gt;subscribe&lt;/a&gt; to get notified.&lt;/p&gt;

</description>
      <category>recursion</category>
      <category>programming</category>
    </item>
    <item>
      <title>4 reasons to write your resume in Markdown</title>
      <dc:creator>Sagar Chakravarthy</dc:creator>
      <pubDate>Mon, 20 Sep 2021 14:01:13 +0000</pubDate>
      <link>https://forem.com/bpsagar/4-reasons-to-write-your-resume-in-markdown-24ip</link>
      <guid>https://forem.com/bpsagar/4-reasons-to-write-your-resume-in-markdown-24ip</guid>
      <description>&lt;p&gt;As Software Developers, we often use Markdown to write readme files, take notes or write a blog post like this one 😛. Its simple syntax helps format content easily.  Apart from quick formatting there are several reasons why I would recommend writing resume in Markdown&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Increased focus on your content
&lt;/h2&gt;

&lt;p&gt;Content is the heart of your resume. But quite often we spend more time on its design and aesthetics. With Markdown’s syntax, you can write neatly formatted content first and then apply various themes or designs tailored to your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  📄 Easier to keep it updated
&lt;/h2&gt;

&lt;p&gt;It is recommended to revisit your resume at least twice a year to keep it updated with your latest achievements, responsibilities and skills. With file formats like DOC, PDF, Tex or JPG it is extremely difficult (sometimes impossible) to edit without using any additional tools. In contrast, Markdown is just a text file which can be easily edited. Moving your sections around is as simple as cutting and pasting text. You can even store this file in a git repository to keep track of the changes made over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎨 Flexibility to switch design
&lt;/h2&gt;

&lt;p&gt;Markdown is rendered as HTML. And with a sprinkle of CSS you can create a beautiful, crisp and unique design for your resume. You can even change this design at any point of time without making any changes to your core content. A bunch of CSS themes for Markdown are available online.&lt;/p&gt;

&lt;h2&gt;
  
  
  👀 Better readability
&lt;/h2&gt;

&lt;p&gt;Markdown provides structure for your content in a relatively simple way because of its simple plain-text-formatting syntax.&lt;/p&gt;

&lt;p&gt;Markdown is a great tool for formatting your resume with advantages like maintainability, readability and flexibility. When I was looking for a job, I created a bunch of designs for my resumes. I have now converted it into a web application where you can write your resume in Markdown, try out these designs and download as PDF. Check it out at &lt;a href="https://resumey.pro"&gt;Resumey.Pro&lt;/a&gt; and let me know what you think in the comments below 👇&lt;/p&gt;

</description>
      <category>resume</category>
      <category>markdown</category>
      <category>css</category>
      <category>html</category>
    </item>
  </channel>
</rss>
