<?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: S. Sharma</title>
    <description>The latest articles on Forem by S. Sharma (@shawarma).</description>
    <link>https://forem.com/shawarma</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%2F295146%2Fd72c59df-b81f-4443-984e-379c95f0db32.gif</url>
      <title>Forem: S. Sharma</title>
      <link>https://forem.com/shawarma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/shawarma"/>
    <language>en</language>
    <item>
      <title>Plotting Reddit Comment Trends With Pandas</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Thu, 10 Sep 2020 01:58:05 +0000</pubDate>
      <link>https://forem.com/shawarma/plotting-reddit-comment-trends-with-pandas-593m</link>
      <guid>https://forem.com/shawarma/plotting-reddit-comment-trends-with-pandas-593m</guid>
      <description>&lt;p&gt;Hey there!&lt;/p&gt;

&lt;p&gt;I wanted to learn more about Pandas, a Python library for data analysis, so I decided to embark on a mini-project to experiment with it. If you use Reddit, you've probably seen a chain of comments like below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pco3_YGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/82b8rfidinry9v3bo3hs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pco3_YGN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/82b8rfidinry9v3bo3hs.png" alt="picture of reddit comment chain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clearly, you can see that there's a pattern in the number of upvotes. Every reply to the parent comment receives less upvotes compared to the previous reply. It would be interesting to create a bar graph, comparing the number of upvotes the parent comment received, the number of upvotes the first reply received, the number of upvotes the second reply received, ..., the number of upvotes the &lt;code&gt;nth&lt;/code&gt; reply received. Using Reddit's API and Pandas, I implemented a program that would do just that. You can find it on GitHub &lt;a href="https://github.com/sshawarma/comment_analyzer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, we need to import the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;praw&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;math&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;PRAW is a Python wrapper for Reddit's API. &lt;code&gt;matplotlib&lt;/code&gt; is a library for creating static, animated, and interactive visualizations in Python. These imports will become clearer as we move on.&lt;/p&gt;

&lt;p&gt;Next, we need to define authenticate to Reddit's API. PRAW allows us to do this pretty easily with OAuth2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Authenticate using our client secret
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'client_secret.txt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;CLIENT_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;CLIENT_SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;praw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reddit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CLIENT_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CLIENT_SECRET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;user_agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;USER_AGENT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this case, the client ID and client secret is stored in a file (called &lt;code&gt;client_secret.txt&lt;/code&gt;). We read this and return an instance of PRAW's &lt;code&gt;Reddit&lt;/code&gt; class, which allows us to interact with Reddit's APIs.&lt;/p&gt;

&lt;p&gt;Now, we break down what we have to do in logical chunks. First, we need to get a list of submissions, so that we can look at the comments under each post. PRAW allows us to get a list of the hottest submissions from r/all, which is basically an amalgamation of a bunch of submissions from different subreddits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_submission_upvotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reddit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;upvotes_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;submissions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reddit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subreddit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'all'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;hot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;count_upvotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;submissions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;future&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;upvotes_list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The reason we use &lt;code&gt;concurrent.futures&lt;/code&gt; is because, depending on the length of the comment chain we are examining, we might end up taking very long to collect upvotes on one submission but a very short time to collect upvotes on another submission (we will see what the &lt;code&gt;count_upvotes&lt;/code&gt; function does next). Here, &lt;code&gt;m&lt;/code&gt; represents the number of submissions to look at and &lt;code&gt;n&lt;/code&gt; represents the number of comments in a comment chain to examine.&lt;/p&gt;

&lt;p&gt;Next, we need to count the number of upvotes of each comment in a comment chain in each submission. This can be done as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_upvotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;submission&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;upvotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;submission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace_more&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;comment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;submission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;upvotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;comment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;upvotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'nan'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;upvotes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In essence, we get the top comment and keep examining each reply until we have gotten &lt;code&gt;n&lt;/code&gt; comments or until the comment chain ends (to get more comment chains of length &lt;code&gt;n&lt;/code&gt;, we can increase &lt;code&gt;m&lt;/code&gt;). If the comment chain ends prematurely, we add &lt;code&gt;nan&lt;/code&gt; (Not a Number) to indicate that no data was collected for the particular reply in the comment chain because that reply did not exist (the comment chain ended, so there were no more upvotes to count).&lt;/p&gt;

&lt;p&gt;After counting the upvotes of each comment in the top comment chain, we only have to process the data. First, we compute the average number of upvotes for the top comments, the 1st reply, the 2nd reply, etc:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;compute_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;avg_upvotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])):&lt;/span&gt;
        &lt;span class="n"&gt;avg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
        &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isnan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;avg&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;avg_upvotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;avg_upvotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;avg_upvotes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We return a list called &lt;code&gt;avg_upvotes&lt;/code&gt;, which contains the average number of upvotes for the top comment, first reply, second reply, etc. We now convert this list into a bar graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;render_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_upvotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Solution from https://stackoverflow.com/questions/9647202/ordinal-numbers-replacement
&lt;/span&gt;    &lt;span class="n"&gt;ordinal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"%d%s"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;"tsnrhtdd"&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ordinal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'Comment Reply Number'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Average Upvotes'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;avg_upvotes&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Comment Reply Number'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Average Upvotes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;legend&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xlabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Comment Reply Number'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Average Upvotes'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yticks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now all we have to do is put it together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'./comment_analyzer.py [number of submissions to analyze] [number of comments]'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;reddit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;authenticate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;upvotes_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_submission_upvotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reddit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;avg_upvotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;compute_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;upvotes_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;render_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;avg_upvotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The program takes two parameters: the number of submissions to look at and the "depth" of the comment chain we have to look at.&lt;/p&gt;

&lt;p&gt;Running the program (assuming you have the necessary libraries installed with Python 3.6+), you get a bar graph like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pOhvzxd9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ntwchm5b7wo771io8z6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pOhvzxd9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ntwchm5b7wo771io8z6r.png" alt="a right-skewed bar graph"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(The "0th" comment represents the top comment).&lt;/p&gt;

&lt;p&gt;The above graph allows us to visualize the distribution of upvotes on comments on Reddit. Clearly, the distribution is right-skewed: the number of upvotes diminish as we get deeper down the reply chain. This is to be expected, since the top comment tends to be seen first.&lt;/p&gt;

&lt;p&gt;Hopefully, you can see how tools like Pandas and PRAW allow us to collect data and visualize it.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>python</category>
      <category>webdev</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>How to use Hugo and GitHub Pages</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Sun, 06 Sep 2020 02:37:34 +0000</pubDate>
      <link>https://forem.com/shawarma/how-to-use-hugo-and-github-pages-4ehi</link>
      <guid>https://forem.com/shawarma/how-to-use-hugo-and-github-pages-4ehi</guid>
      <description>&lt;p&gt;Hey there!&lt;/p&gt;

&lt;p&gt;I just moved my &lt;a href="https://sshawarma.github.io"&gt;blog&lt;/a&gt; from Jekyll to Hugo and I wanted to give a quick tutorial on how to use Hugo with GitHub pages. &lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;First, you'll need to install Hugo:&lt;/p&gt;

&lt;p&gt;MacOS: &lt;code&gt;brew install hugo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Linux: &lt;code&gt;brew install hugo&lt;/code&gt; (Here's a link on &lt;a href="https://docs.brew.sh/Homebrew-on-Linux"&gt;how to install &lt;code&gt;brew&lt;/code&gt; for Linux&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Windows: &lt;code&gt;choco install hugo -confirm&lt;/code&gt; or &lt;code&gt;scoop install hugo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You may need to install Go.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hugo on GitHub Pages
&lt;/h2&gt;

&lt;p&gt;Installing Hugo for GitHub Pages is pretty simple. First, we will create a new directory (I'll refer to this directory as &lt;code&gt;mysite&lt;/code&gt;). Then, type the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hugo new site mysite
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;mysite
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you type &lt;code&gt;ls&lt;/code&gt;, you'll see a bunch of files in this directory. The only one we care about for now is &lt;code&gt;config.toml&lt;/code&gt;. Go to &lt;code&gt;config.toml&lt;/code&gt; and find the line that says &lt;code&gt;publishDir = public&lt;/code&gt; (or add it somewhere if it's not present). Set &lt;code&gt;publishDir&lt;/code&gt; to &lt;code&gt;docs&lt;/code&gt;. This will be the root directory that GitHub pages will use to deploy our site. Also, find the line with the parameter &lt;code&gt;baseURL&lt;/code&gt; and set &lt;code&gt;baseURL = https://&amp;lt;YOUR-USERNAME&amp;gt;.github.io&lt;/code&gt; where &lt;code&gt;&amp;lt;YOUR-USERNAME&amp;gt;&lt;/code&gt; is your GitHub username.  &lt;/p&gt;

&lt;p&gt;Now, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hugo server &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Go to &lt;a href="https://localhost:1313"&gt;https://localhost:1313/&lt;/a&gt; and confirm that your site is running properly. Then, go to GitHub and make a new repository called &lt;code&gt;&amp;lt;YOUR-USERNAME&amp;gt;.github.io&lt;/code&gt;. Once you do that, go to the &lt;strong&gt;Settings&lt;/strong&gt; tab and scroll down to the section that says &lt;strong&gt;GitHub Pages&lt;/strong&gt;. Under the &lt;strong&gt;Source&lt;/strong&gt; heading, use the dropdown to select the &lt;code&gt;/docs&lt;/code&gt; option. This will inform GitHub Pages that the root directory for your site is under the &lt;code&gt;docs&lt;/code&gt; subdirectory. Finally, click the &lt;strong&gt;Save&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mLWqqQgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o803bjq0fbk6aow6bim2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mLWqqQgJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o803bjq0fbk6aow6bim2.png" alt="GitHub Pages Settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All we have to do now is push your site to the repository. Type the following commands (you're still in the &lt;code&gt;mysite/&lt;/code&gt; folder at this point):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ../
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git clone https://&amp;lt;YOUR-USERNAME&amp;gt;.github.io
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; mysite/ &amp;lt;YOUR-USERNAME&amp;gt;.github.io
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; mysite/
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;YOUR-USERNAME&amp;gt;.github.io
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; hugo
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;docs
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"My Hugo Site"&lt;/span&gt; &lt;span class="c"&gt;# or whatever you want your commit message to be...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;...and that's it! The above commands clone your repository, copy the files from &lt;code&gt;mysite/&lt;/code&gt; to &lt;code&gt;&amp;lt;YOUR-USERNAME&amp;gt;.github.io/&lt;/code&gt;, generate the root directory (&lt;code&gt;docs&lt;/code&gt;) using the &lt;code&gt;Hugo&lt;/code&gt; command, and then commit and push your site to the &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;Likely, you'll be making a lot of changes to your Hugo site. In that case, you'll want a shell script to streamline the process. The following bash script does that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="c"&gt;# If a command fails then the deploy stops&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[0;32mDeploying updates to GitHub...&lt;/span&gt;&lt;span class="se"&gt;\0&lt;/span&gt;&lt;span class="s2"&gt;33[0m&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Build the project.&lt;/span&gt;
hugo &lt;span class="c"&gt;# if using a theme, replace with `hugo -t &amp;lt;YOURTHEME&amp;gt;`&lt;/span&gt;

&lt;span class="c"&gt;# Go To docs folder&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;docs

&lt;span class="c"&gt;# Add changes to git.&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Commit changes.&lt;/span&gt;
&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"rebuilding site &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nv"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi
&lt;/span&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$msg&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Push source and build repos.&lt;/span&gt;
git push origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above was taken from a post by Hugo for deploying your website to GitHub pages, which I &lt;a href="https://gohugo.io/hosting-and-deployment/hosting-on-github/"&gt;recommend reading&lt;/a&gt; for more information on how to add posts, customize/create themes, and write your own templates.&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Leetcode: Middle Node in Linked List</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Thu, 27 Aug 2020 04:20:44 +0000</pubDate>
      <link>https://forem.com/shawarma/leetcode-middle-node-in-linked-list-56d0</link>
      <guid>https://forem.com/shawarma/leetcode-middle-node-in-linked-list-56d0</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Given a non-empty, singly linked list with head node &lt;code&gt;head&lt;/code&gt;, return a middle node of linked list.&lt;/p&gt;

&lt;p&gt;If there are two middle nodes, return the second middle node.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;I came up with the following solution in C++ to the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;middleNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ListNode&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;ListNode&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;slow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;fast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fast&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;slow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;slow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;​ The algorithm above uses two pointers, a &lt;code&gt;slow&lt;/code&gt; pointer and a &lt;code&gt;fast&lt;/code&gt; pointer. The &lt;code&gt;fast&lt;/code&gt; pointer moves twice as fast as the &lt;code&gt;slow&lt;/code&gt; pointer. Below I'll explain why the algorithm works.&lt;/p&gt;

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

&lt;p&gt;​ The input we are given is a non-empty, singly linked list. We must show that the algorithm finds the middle node for all non-empty singly linked lists. A linked list can have an odd length or and even length. If the list has an odd length, that means there is exactly one node in the middle. If the list has an even length, then there are two nodes in the middle and we are required to return the second one.&lt;/p&gt;

&lt;p&gt;​ Let's first consider the odd case. Let's assume there are &lt;code&gt;2m+1&lt;/code&gt; nodes where &lt;code&gt;m&lt;/code&gt; is a positive integer. Both pointers start at node &lt;code&gt;1&lt;/code&gt;. After the first iteration, the &lt;code&gt;fast&lt;/code&gt; pointer is at node &lt;code&gt;3&lt;/code&gt; and the &lt;code&gt;slow&lt;/code&gt; pointer is at node &lt;code&gt;2&lt;/code&gt;. After the second iteration, the &lt;code&gt;fast&lt;/code&gt; pointer is at node &lt;code&gt;5&lt;/code&gt; and the &lt;code&gt;slow&lt;/code&gt; pointer is at node &lt;code&gt;3&lt;/code&gt;. After the third iteration, the &lt;code&gt;fast&lt;/code&gt; pointer is at node &lt;code&gt;7&lt;/code&gt; and the &lt;code&gt;slow&lt;/code&gt; pointer is at node &lt;code&gt;4&lt;/code&gt;. Let's place the values in a table to understand the trend.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;
&lt;code&gt;fast&lt;/code&gt; position&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;slow&lt;/code&gt; position&lt;/th&gt;
&lt;th&gt;iteration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;​ If you notice, the &lt;code&gt;fast&lt;/code&gt; pointer has position &lt;code&gt;2*(position of slow pointer) - 1&lt;/code&gt;. Thus, when the &lt;code&gt;slow&lt;/code&gt; pointer is at the middle of the list (position &lt;code&gt;m+1&lt;/code&gt;) the &lt;code&gt;fast&lt;/code&gt; pointer is at position &lt;code&gt;2*(m+1) - 1 = 2m + 1&lt;/code&gt;. So, if the &lt;code&gt;fast&lt;/code&gt; pointer moves at twice the speed of the &lt;code&gt;slow&lt;/code&gt; pointer, then the &lt;code&gt;slow&lt;/code&gt; pointer will point to the middle node by the time the &lt;code&gt;fast&lt;/code&gt; pointer arrives at the end of the list. &lt;/p&gt;

&lt;p&gt;​ On a similar vein, we can prove that this algorithm works for an even length list. Let there be &lt;code&gt;2m&lt;/code&gt; nodes. Since the pattern is the exact same, we determine that when the &lt;code&gt;slow&lt;/code&gt; pointer arrives at the position &lt;code&gt;m+1&lt;/code&gt; (the second middle node), the &lt;code&gt;fast&lt;/code&gt; pointer is at position &lt;code&gt;2*(m+1) - 1 = 2m + 1&lt;/code&gt;. However, since there are only &lt;code&gt;2m&lt;/code&gt; positions, that means that the &lt;code&gt;fast&lt;/code&gt; pointer has already finished traversing the entire list (&lt;code&gt;NULL&lt;/code&gt;). Thus, the code above still works and the algorithm solves the problem. &lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Cost Models for Algorithmic Analysis</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Wed, 15 Jan 2020 19:35:21 +0000</pubDate>
      <link>https://forem.com/shawarma/cost-models-for-algorithmic-analysis-11no</link>
      <guid>https://forem.com/shawarma/cost-models-for-algorithmic-analysis-11no</guid>
      <description>&lt;p&gt;Recently, I &lt;a href="https://gregorygundersen.com/blog/2020/01/12/why-research-blog/"&gt;read a post&lt;/a&gt; on HN by Gregory Gundersen on why they keep a research blog. I think the idea of having a place where you can explain things to yourself (and to others in the process) sounds quite useful. So, today I'm going to talk about cost models, an important part of algorithmic design and the theory of algorithms.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Cost Model?
&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;cost model&lt;/em&gt; is essentially a model to describe what operations we consider when analyzing an algorithm. For example, when stating the performance of sorting algorithms, we tend to consider &lt;em&gt;comparisons&lt;/em&gt; and &lt;em&gt;array accesses&lt;/em&gt; as operations that incur a cost when we execute them, so we take them into consideration when analyzing the performance of sorting algorithms. Additionally, when analyzing data-structures like LIFO stacks and FIFO queues, we tend to consider &lt;code&gt;push&lt;/code&gt; and &lt;code&gt;pop&lt;/code&gt; (or &lt;code&gt;enqueue&lt;/code&gt; and &lt;code&gt;dequeue&lt;/code&gt;) operations since these operations incur a cost. Technically, any operation (even assigning a variable) incurs a cost, but generally we're interested in operations that are complex enough that they could cause the program to slow down if executed excessively.&lt;/p&gt;

&lt;p&gt;Knuth defined the total cost of a certain number of operations to be computed as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total Cost = Frequency × Time
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The frequency refers to the number of times the operation occurs, and the time refers to how long it takes for the operation itself to execute. For example, if a comparison took 5 seconds on average, and we did 200 comparisons, then the total cost would be 1000 seconds.&lt;/p&gt;

&lt;p&gt;Generally, when talking about algorithmic performance, we don't talk in terms of seconds, minutes, or any unit of time, but in terms of the frequency. This is because the time it takes for an operation to be executed varies depending on the system you're running a program on. The frequency of an operation is not variable, it's well-defined. Therefore, if we know the frequency of operations, then all we need to know is the system-specific time variable to calculate the total cost (we can usually do this by just timing the operation to execute by itself).&lt;/p&gt;

&lt;p&gt;So, when we say that an algorithm's running time is &lt;code&gt;N&lt;/code&gt;^2 or &lt;code&gt;O(N^2)&lt;/code&gt;, what does that mean? The latter is a bit more specific (and I may talk about it another time), but, to put it simply, an algorithm that has a running time of &lt;code&gt;N&lt;/code&gt;^2 executes &lt;code&gt;N&lt;/code&gt;^2 operations. What are these operations? These operations are defined by the cost model. If a sorting algorithm has a running time of &lt;code&gt;N^2&lt;/code&gt; that means that, given an array of size &lt;code&gt;N&lt;/code&gt;, the algorithm requires &lt;code&gt;N^2&lt;/code&gt; comparisons (or array accesses, depending on what we care about) to sort the array. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why use a Cost Model?
&lt;/h3&gt;

&lt;p&gt;I'll be honest, theoretical computer science is usually not applicable in practical situations. However, though you may not be doing any mathematical analysis, it's useful to know &lt;em&gt;what&lt;/em&gt; operations are expensive and what operations aren't. Identifying what operations are the bottleneck in your application allows you to avoid premature optimization (the root of all evil) and, of course, allows you to speed up your program. Additionally, having a "mental cost model" can enable you to be more selective in your choice of algorithm or data-structure for a particular task. For example, if you're writing an IRQ handler, then a ring buffer would probably be a better than a linked-list queue since space is a premium. If you're sorting complex data types (like linked lists), then &lt;a href="https://stackoverflow.com/questions/5222730/why-is-merge-sort-preferred-over-quick-sort-for-sorting-linked-lists"&gt;merge sort would be a better option than quick sort.&lt;/a&gt; If you're making a symbol table, you need to decide what underlying data-structure you will use according to whether your program will be performing more inserting/removing operations or accessing operations.&lt;/p&gt;

&lt;p&gt;The idea of a cost model naturally leads to many questions pertaining to the theory of algorithms. I've listed some links below for anyone who wants to learn more.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://algs4.cs.princeton.edu/14analysis/"&gt;Algorithmic Analysis (Princeton)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/analysis-of-algorithms-set-1-asymptotic-analysis/"&gt;Asymptotic Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Grokking-Algorithms-illustrated-programmers-curious/dp/1617292230?SubscriptionId=AKIAILSHYYTFIVPWUY6Q&amp;amp;tag=duckduckgo-ffab-20&amp;amp;linkCode=xm2&amp;amp;camp=2025&amp;amp;creative=165953&amp;amp;creativeASIN=1617292230"&gt;Grokking Algorithms&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>computerscience</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Busy? Try Todoist</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Sat, 11 Jan 2020 16:05:05 +0000</pubDate>
      <link>https://forem.com/shawarma/busy-try-todoist-36ia</link>
      <guid>https://forem.com/shawarma/busy-try-todoist-36ia</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gYPkBFJw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AP7HNFq_jjtHMzOxJiz72vQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gYPkBFJw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/1%2AP7HNFq_jjtHMzOxJiz72vQ.png" alt="img"&gt;&lt;/a&gt;&lt;em&gt;Source: doist.com&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a weird post because it’s sort of an app promotion but I’m not being paid for it. Either way, I think this app deserves a little bit of attention.&lt;/p&gt;

&lt;p&gt;Everyone needs a to-do list. Keep in mind that this is coming from a person who’s pretty flexible when it comes to task completion. For a long time, I rarely ever used to-do lists because I was usually pretty good at remembering what I had to do. As time went on, however, I needed a better way to keep track of things. So, naturally, I turned to software. That’s when I found &lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt;, a simple app for keeping track of things.&lt;/p&gt;

&lt;p&gt;The reason I’m promoting this app and not others is because it’s free(ish) and it has a nice interface that allows for me to keep track of the specific tasks I have to do. Additionally, I use the app to keep track of project ideas that I want to try out over the weekend since I usually don’t get time to experiment on the weekdays. The app allows me to plan out what I have to do today, tomorrow, and for the next week, which is extremely useful since some to-do list apps are only useful for planning what you want to do on that day. As you add and complete tasks, Todoist measures your progress by providing daily summary reports of the number of tasks you are completing, which other apps don’t do. Speaking of completing tasks, the final — and perhaps best — aspect of the app is that it “rewards” you for completing tasks. Todoist has a feature called “karma” where you earn points for completing more tasks. By gaining a certain number of points, you go to a different level. This feature makes Todoist quite good for productivity, and motivates me to complete the pending — and often boring — tasks that I have to complete in a day.&lt;/p&gt;

&lt;p&gt;Of course, every app has a downside. Todoist operates on a &lt;em&gt;freemium&lt;/em&gt; model, meaning that certain features like weekly summary reports and labels, are not accessible if you don’t upgrade to their premium version. The biggest problem with this app is that &lt;strong&gt;reminders are a premium feature&lt;/strong&gt;. I usually don’t need reminders to complete tasks, I just need to remember what they are, so this isn’t a problem for me. However, if you need reminders, then maybe upgrading to the premium version or getting a different app would be a good choice.&lt;/p&gt;

&lt;p&gt;Thoughts? Opinions? Concerns? Leave a comment below! 😀&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>productivity</category>
    </item>
    <item>
      <title>5 Projects To Do When You're Offline</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Sun, 05 Jan 2020 03:46:48 +0000</pubDate>
      <link>https://forem.com/shawarma/5-projects-to-do-when-you-re-offline-3d6m</link>
      <guid>https://forem.com/shawarma/5-projects-to-do-when-you-re-offline-3d6m</guid>
      <description>&lt;p&gt;Recently, I went on a camping trip with family and I got &lt;strong&gt;really&lt;/strong&gt; bored. The outdoors isn't really my thing (which is why I decided that programming and mathematics suit me more than, say, being a gym instructor), so I naturally brought my computer and phone along with me. Of course, I had no service and no Wi-Fi meaning that I was limited in terms of what I could do. The only real form of entertainment I had was my downloaded music and my text editor.&lt;/p&gt;

&lt;p&gt;A lot of code written nowadays requires some sort of Internet connection. Building a web server? Internet. Developing a vast neural network? Internet. Making an app? Internet. Creating a website? Internet.&lt;/p&gt;

&lt;p&gt;Many of the tools that typical developers make require an Internet connection. Additionally, I assume there are some developers that — like me — would prefer to spend a weekend inside rather than let the sun touch their face or would just like to spend some time doing something productive.&lt;/p&gt;

&lt;p&gt;If you're that type of person, then this article (might) interest you if you (might) find yourself in this situation. If being Internet-isolated is not a problem for you, then please don't recommend that I go outside more because — and this might be a shocker — &lt;em&gt;I don't care&lt;/em&gt;. At all.&lt;/p&gt;

&lt;p&gt;Without further ado, the following are &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline"&gt;5 projects to when you're do offline&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Basic Calculator
&lt;/h3&gt;

&lt;p&gt;I was looking at my phone thinking about what I could do. The calculator app is one of the only functional apps on your phone. I thought I would make a basic calculator on the terminal (like &lt;code&gt;bc&lt;/code&gt;) that could perform addition, subtraction, multiplication, division, and exponentiation according to the order of operations. Additionally, I wanted it to be able to evaluate parenthesized expressions. After a little bit of thinking, &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline/tree/master/calculator"&gt;I created a basic calculator&lt;/a&gt; in C.&lt;/p&gt;

&lt;h3&gt;
  
  
  A File Search Program
&lt;/h3&gt;

&lt;p&gt;Since I can't access any data on the cloud, I only have the files on my local machine to deal with. So, logically, making a file search program makes sense. I wanted it to be simple, so I decided to ignore character files, symbolic links, and block devices. With a majority of the file system minutiae out of the way, we only have to consider directories and regular files. If we come across a directory, then we put all the contents of the directory into a queue. Otherwise, if we come across a regular file, we check to see that the regular file's name matches the user's search query. In a little bit of code, &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline/tree/master/file_search"&gt;I made a crude file search program&lt;/a&gt; (again, in C).&lt;/p&gt;

&lt;h3&gt;
  
  
  Any UNIX Tool
&lt;/h3&gt;

&lt;p&gt;There are a lot of UNIX tools: &lt;code&gt;less&lt;/code&gt;, &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;du&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;ld&lt;/code&gt;, and &lt;code&gt;ps&lt;/code&gt;, to name only a few. If you're on a UNIX system, then pick a UNIX tool to recreate. Generally, most of the knowledge needed to recreate these tools can be found within a few man pages or with just a bit of basic programming knowledge. If you're on Windows, then this task can be especially challenging. &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline/tree/master/grep"&gt;I chose to make a basic version of &lt;code&gt;grep&lt;/code&gt;&lt;/a&gt; (with highlighting).&lt;/p&gt;

&lt;h3&gt;
  
  
  Play with Mazes
&lt;/h3&gt;

&lt;p&gt;Generating random mazes is surprisingly fun and a real algorithmic challenge. The only reason I'm even suggesting this is because of Jamis Buck's &lt;em&gt;Mazes for Programmers&lt;/em&gt;, a thrilling book (that I should have taken with me when I was camping) on maze algorithms. The book is entirely in Ruby, but it can be done in any language. I wrote some basic code to &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline/tree/master/mazes"&gt;generate a maze&lt;/a&gt; of arbitrary size according to user input and output it to the terminal screen using the Binary Tree algorithm (&lt;strong&gt;Disclaimer&lt;/strong&gt;: OK, so I didn't write this code, the author of the book did, but that's besides the point). If you're ever feeling uncreative (like I was when thinking of a project to do), then I would recommend just going through this book. So far, it's been quite entertaining.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recreate Basic Programming Language Features
&lt;/h3&gt;

&lt;p&gt;Another project is to recreate basic features of your programming language of choice in that programming language. I didn't "recreate" &lt;code&gt;malloc()&lt;/code&gt; and &lt;code&gt;calloc()&lt;/code&gt; &lt;em&gt;per se&lt;/em&gt;, but I did implement a simple, dumb &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline/tree/master/alloc"&gt;variant of the two functions&lt;/a&gt; that allocates memory off of a fixed memory pool. Of course, there's many other features you can recreate: slices, vectors, lists, dictionaries, even &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; loops. The choice just depends on what seems interesting to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Again, all the projects I did above are available in &lt;a href="https://github.com/m4rtyr/5-projects-to-do-offline"&gt;this repository&lt;/a&gt;. Some of them can obviously be improved. For example, the calculator could have its own GUI (maybe not in C, but in another language) or handle more complex functions like &lt;code&gt;sin&lt;/code&gt; and square root. The file search program is single-threaded and synchronous. Could an async/threaded approach be faster? The &lt;code&gt;alloc&lt;/code&gt; program is a really dumb implementation of a memory allocation system. There's not even a way to free up memory. Maybe a binary heap would be better (or a Fibonacci heap) rather than a linear, fixed memory pool? The list of improvements are endless.&lt;/p&gt;

&lt;p&gt;Of course, there's many, many more offline projects you can do. Pong, Chess, a JSON parsing library, or even an entirely new programming language are all examples of offline projects that you can embark on.&lt;/p&gt;

&lt;p&gt;Have you done any interesting projects while offline? Have any thoughts? Opinions? Concerns? Ideas? Write a comment below! 😁&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>contributorswanted</category>
      <category>computerscience</category>
      <category>productivity</category>
    </item>
    <item>
      <title>5 Git Commands Everyone Should Know</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Wed, 25 Dec 2019 03:24:30 +0000</pubDate>
      <link>https://forem.com/shawarma/5-git-commands-everyone-should-know-d70</link>
      <guid>https://forem.com/shawarma/5-git-commands-everyone-should-know-d70</guid>
      <description>&lt;p&gt;Git is an amazing tool for version-control and open-source collaboration (though many companies are now using it too!). I think that most people should be able to use Git, especially if it's a requirement for them at work or school. Below are 5 Git commands everyone should know.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git reset --hard [commit hash]&lt;/code&gt; — This is &lt;em&gt;fantastic&lt;/em&gt; as a last resort for when you've really screwed up. Generally, I've only used this when I've tried out a dumb idea (thinking it was good), merged it into my main branch, and then realized that it was, in fact, a dumb idea in the first place. &lt;a href="https://git-scm.com/docs/git-reset"&gt;You might want to read more about this&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git checkout -- [filename]&lt;/code&gt; — If you're ever in a situation where you've made so many changes to a file that you think it's just better to scrap them all, this is the command. &lt;code&gt;git checkout -- [filename]&lt;/code&gt; will undo any uncommitted changes to a file (or a set of files). &lt;a href="https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting"&gt;You might want to read more about this&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git rm [filename]&lt;/code&gt; — This command gets git to stop tracking a file or a set of files. It's pretty useful for removing a file from the working directory &lt;em&gt;and&lt;/em&gt; removing it from git's tracking. &lt;a href="https://git-scm.com/docs/git-rm"&gt;You might want to read more about this&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git config --global alias.[aliasname] [command]&lt;/code&gt; — This is &lt;strong&gt;very&lt;/strong&gt; helpful if you hate typing a lot. &lt;code&gt;git alias&lt;/code&gt; allows you to create short-hands for common git commands. For example, &lt;code&gt;git config --global alias.nbr "checkout -b"&lt;/code&gt; allows you to do &lt;code&gt;git nbr my-branch&lt;/code&gt; to create a new branch called &lt;code&gt;my-branch&lt;/code&gt; instead of &lt;code&gt;git checkout -b my-branch&lt;/code&gt;(I made this exact alias myself). &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases"&gt;You might want to read more about this&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git revert&lt;/code&gt; — OK, so I'll admit, I've never used this once, but I think the command is pretty useful. Given a set of commits, it'll undo those changes and record that revert in a commit. Again, I've never used it, but I can think of many cases where development can go so awry that it's necessary. &lt;a href="https://git-scm.com/docs/git-revert"&gt;You might want to read more about this&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Opinions? Thoughts? Praises? What are some useful git commands for you? Leave a comment below! 😀&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Question: How to make a personal blog that looks good?</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Thu, 19 Dec 2019 23:23:08 +0000</pubDate>
      <link>https://forem.com/shawarma/question-how-to-make-a-personal-blog-that-looks-good-4h82</link>
      <guid>https://forem.com/shawarma/question-how-to-make-a-personal-blog-that-looks-good-4h82</guid>
      <description>&lt;p&gt;I just started using Jekyll and GitHub pages to host my website. While I'm mainly interested in writing posts about math and documenting any interesting programming projects I do, I want to make my website look appealing and interesting. Right now it's a &lt;a href="https://m4rtyr.github.io"&gt;little bit bland&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If anyone more experienced in this area can help, that would be awesome.&lt;/p&gt;

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

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>How To Read A Computer Science Book</title>
      <dc:creator>S. Sharma</dc:creator>
      <pubDate>Thu, 19 Dec 2019 04:49:49 +0000</pubDate>
      <link>https://forem.com/shawarma/how-to-read-a-computer-science-book-4jie</link>
      <guid>https://forem.com/shawarma/how-to-read-a-computer-science-book-4jie</guid>
      <description>&lt;p&gt;New Year's is coming up and I kind of wanted to give a couple basic tips that I learned before we head into the next decade.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't read it like a novel&lt;/strong&gt; — One of the mistakes I made trying to read computer science books is that I tended to read it like a storybook. When we're reading in "storybook" mode, we're in a cognitively &lt;em&gt;passive&lt;/em&gt; mode. That is, we're not engaging with the content, just absorbing it as we go, forgetting the minute details that may be really important for understanding. The key thing to do here is to start reading &lt;em&gt;actively&lt;/em&gt;, which leads me to my next bullet point.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understand exactly what's going on&lt;/strong&gt; — Say you're reading a book about sorting algorithms and they're talking about merge sort. Instead of reading the description of merge sort (and doing any potential practice problems), try to work each example out in your head or, if you must, on paper. That way, you'll fully understand how the algorithm works and already have some exposure to using the algorithm, making practice problems (and real-world problems) easier to solve.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Take notes&lt;/strong&gt; — Look, notes aren't easy for most of us, but taking notes is great for summarizing large amounts of information. If you're taking an online course, then this is an especially good idea. Don't just think, "Oh, I'm not in a classroom, so I can just watch the video." You're going to forget everything once the unit is over. Writing down the important stuff helps our memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't try to do every practice problem&lt;/strong&gt; — This might seem counter-intuitive at first. However, trying to do everything is time-consuming. If you're able to do every problem in a timely manner, great! That's the optimal scenario. But let's face it, not every one of us is going to be brilliant right off the bat. Some topics are hard, and applying the concepts can be difficult. Additionally, sometimes you just don't want to do all or even a majority of the exercises because it feels like so much work. Relax. You don't have to be the next Albert Einstein. Just do as much as you can. Any amount is worth something.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ALWAYS challenge yourself&lt;/strong&gt; — Doing easy problems is fine. Those types of problems can help reinforce certain concepts or skills. However, don't just glance at a problem and say "that's too easy." If it is, why not solve it? I used to do this sometimes out of laziness and sometimes to make myself feel better. If a problem is &lt;em&gt;hard&lt;/em&gt;, however, don't just avoid it. Even if you have an instinctual feeling to avoid it, remember: you're not a genius, and you'll never become a better computer scientist/programmer/mathematician/whatever if you don't try. I know it sounds cliché, but it's worth saying again.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the stuff above are habits that &lt;strong&gt;I&lt;/strong&gt; used to have. In fact, to a certain extent, I still do these things. However, one of my goals for next year (and for the rest of my computer science career) is to make myself less vulnerable to these behaviours and instill more productive habits.&lt;/p&gt;

&lt;p&gt;How do you read technical books? Leave a comment below. Happy Holidays! 🎁&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
