Jekyll2022-01-31T22:59:32-05:00https://blog.vishnus.me/feed.xmlVishnu’s BlogMy blog where I explore full-stack development, problem-solving, and just general programming.Getting my summer 2021 internship + general tips and advice2021-09-27T10:00:00-04:002022-01-31T22:55:25-05:00https://blog.vishnus.me/posts/getting-summer-2021-internship<p>During the summer of 2021, I interned at the University of Waterloo developing a website for the Software Architecture Group (SWAG). This blog post will outline how I got the internship and general tips and observations that I made.</p>
<h2 id="programming-and-extracurriculars">Programming and extracurriculars</h2>
<h3 id="programming">Programming</h3>
<p>During quarantine in around May/June 2020, I improved my programming skills. I learned C++, Flask, and NativeScript. I first created a <a href="https://play.google.com/store/apps/details?id=com.applab.basketball">basketball statistic and live score app</a> using NativeScript. Then, I participated in 4-5 hackathons (not performing particularly well in any of them).</p>
<p>In February 2021, I created a <a href="https://github.com/vishnupsatish/codeio">coding problem grading platform</a> in Flask for my grade 11 computer science final project.</p>
<p>In the same month, I worked with a mathematics teacher in my high school to create an online, interactive version of a math textbook that the teacher wrote. I learned a lot about full-stack development by creating these projects and I added them to my resume.</p>
<h3 id="extracurricular-plan">Extracurricular plan</h3>
<p>In February 2021, I was afraid. Afraid that my extracurriculars weren’t enough, so I made a plan as to what the summer and grade 11 would look like. My plan for the summer was to start a business through the Ontario Summer Business program. My plan for the school year would be to improve my competitive programming skills to try to make CCO in grade 12 and apply to be one of the executives of our school’s computer science club.</p>
<p>By March, I had been progressively losing interest in participating in the business program, but I still worked on my application. I also signed up for a LinkedIn account at this time and noticed that a few of my acquaintances had researched at universities, most notably the University of Toronto. I thought to myself, researching at a university seems like a good way to grow my network and learn more about computer science.</p>
<h2 id="getting-the-internship">Getting the internship</h2>
<h3 id="cold-emailing">Cold emailing</h3>
<p>I created two email templates, one to email startups for internship opportunities and another to email university professors. To email startups, I searched for “top Canadian startups” on LinkedIn, went on their websites, and emailed their general inquiries address. To email professors, I went to the websites of large Canadian universities and emailed a few professors from each university’s computer science department. In total, I cold emailed around 40 startups and 50 professors. By this time, RBC’s Innovation Developer internship for high schoolers had expired, so I realized I was slightly late to the game. I also applied for general software developer intern roles through LinkedIn, but most of those were for post-secondary students so I didn’t hear back from them.</p>
<p>Out of the ~90 people I emailed, I received only three affirmative responses. These responses were:</p>
<ul>
<li>Opportunity to volunteer at a coding camp organized by a university to teach middle school children</li>
<li>Opportunity to work on answering research questions related to computer science and issues pertinent to high schoolers (on a volunteer basis)</li>
<li>Request for a meeting to discuss internship opportunities</li>
</ul>
<p>I did a meeting with the professor who wanted to meet and he gave me a few different opportunities, one of which was a paid internship to create a website for the Software Architecture Group at the University of Waterloo. I emailed him, telling him that was the opportunity that I wanted to work on. I followed up a couple of times and eventually, he responded by telling me that the group was keen on working with me.</p>
<p>After that, there was an opening for a high school software developer intern from IBM that I found through LinkedIn, so I applied for the four high school positions. I was rejected from all four, but I already had an opportunity so I wasn’t too worried.</p>
<p>Two days before the internship was scheduled to begin, I received an email requesting confirmation of my bank account details and my internship began!</p>
<h2 id="tips-and-observations">Tips and observations</h2>
<h3 id="plan">Plan</h3>
<p>Here’s a general plan that I would follow if I were to look for a programming-related internship.</p>
<ol>
<li>Get decently good at something
<ul>
<li>Create a few open-source, polished projects</li>
<li>It may help to volunteer your programming services at a community level</li>
</ul>
</li>
<li>Create a resume (ideally using Microsoft Word or LaTeX)
<ul>
<li>Try to keep it to one page</li>
<li><a href="https://vishnus.me/resume.pdf" target="_blank">My resume</a></li>
</ul>
</li>
<li>Create an email template, optimally two templates, one to email startups, another to email professors</li>
<li>Add a call to action in your email (don’t make it open-ended)
<ul>
<li>One example would be to use Calendly and create a personal meeting link where the recipient can schedule a meeting</li>
</ul>
</li>
<li>Find professors from university websites to email</li>
<li>Find startups from LinkedIn/general Google searches to email</li>
<li>Apply to internships on LinkedIn and other job sites as well, even if the internship states applicants must be in a post-secondary program</li>
</ol>
<p>In my opinion, it would be best to email at least 3-4 months before your intended internship period.</p>
<h3 id="observations">Observations</h3>
<ul>
<li>(Most) professors genuinely want to help students and are more responsive than startups (I received around three responses from startups and 15 responses from professors)</li>
<li>You don’t need to be the <em>absolute best</em> at anything
<ul>
<li>Don’t get too worked up if you make mistakes or struggle
<ul>
<li>It’s more about your communication and how you present yourself</li>
</ul>
</li>
<li>I wouldn’t even consider myself “good” at software development
<ul>
<li>There are a countless number of people that I know who are more skilled than me</li>
</ul>
</li>
</ul>
</li>
</ul>During the summer of 2021, I interned at the University of Waterloo developing a website for the Software Architecture Group (SWAG). This blog post will outline how I got the internship and general tips and observations that I made.Solving “Disjoint Set Test” on DMOJ2021-06-13T10:00:00-04:002021-06-13T10:21:49-04:00https://blog.vishnus.me/posts/ds2<p><a href="#"><img src="https://antique-fringe-fennel.glitch.me/badge?page_id=2021-06-13-ds2.md" /></a></p>
<h2 id="problem">Problem</h2>
<p>Problem link: <a href="https://dmoj.ca/problem/ds2" target="_blank">https://dmoj.ca/problem/ds2</a></p>
<p>Problem type: Graph theory</p>
<p>This problem asks us to implement a program that outputs the number of edges in the minimum spanning tree of a weighted, undirected graph. Though we are not given the weights of each edge, we are given that “an edge that shows up earlier in the input has a strictly less weight than an edge that shows up later in the input”. If there is no minimum spanning tree (i.e. the graph is not connected) we output “Disconnected Graph”.</p>
<h2 id="terminology">Terminology</h2>
<p>Node/vertex: an element in a graph</p>
<p>Edge: the connection between two nodes/vertices in a graph</p>
<p>Weight: the “cost” of travelling along an edge in a graph</p>
<p>Directed graph: a graph has that direction; every edge start from one nodes and goes to another</p>
<h2 id="solution">Solution</h2>
<h3 id="disjoint-set">Disjoint-set</h3>
<p>We will need to use the disjoint-set data structure to find the minimum spanning tree of the given graph. What is a disjoint-set data structure? It is a data structure that is used to store a collection of elements that are part of non-overlapping sets, with each set having a representative element.</p>
<p>A disjoint-set (with path compression optimization) has two main operations. The data structure can also be stored in an array, where the value with index <code class="language-plaintext highlighter-rouge">i</code> in the array represents <code class="language-plaintext highlighter-rouge">i</code>’s parent element’s index.</p>
<ul>
<li>Find
<ul>
<li>Returns the representative of a vertex’s set, and sets all vertices in between (including the vertex passed to the function) to be direct children of the representative</li>
</ul>
</li>
<li>Merge
<ul>
<li>Merges two sets (adds an edge between the representative of the sets of the vertices given)</li>
</ul>
</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
</pre></td><td class="rouge-code"><pre>int find(vertex v) {
if ds[v] != v:
ds[v] = find(ds[v])
return ds[v]
}
void merge(vertex v, vertex u) {
ds[find(v)] = find(u)
}
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Below is an example of how the disjoint-set data structure works.</p>
<p>Assume we have 10 elements to begin with, and all elements are part of their own set. Each set’s representative is the sole element in that set.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/disjoint-set-step1.png" alt="" width="50%" /></p>
<p>Let’s merge 1 and 2. An edge is added between 1 and 2.
<code class="language-plaintext highlighter-rouge">merge(1, 2)</code></p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/disjoint-set-step2.png" alt="" width="50%" /></p>
<p>Let’s now merge 4 and 1. An edge is added between 4 and 1’s representative, which is 2.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/disjoint-set-step3.png" alt="" width="50%" /></p>
<p>Now, let’s merge 2 and 3. An edge is added between each vertex’s representative.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/disjoint-set-step4.png" alt="" width="50%" /></p>
<p>If we were to call <code class="language-plaintext highlighter-rouge">find(1)</code> now (finding 1’s representative), it would return 3, and it would also make 1’s direct parent 3. This is known as the path compression optimization.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/disjoint-set-step5.png" alt="" width="50%" /></p>
<p>You might be wondering how the disjoint-set data structure relates to finding the minimum spanning tree of a graph. Finding the minimum spanning tree of a graph can be achieved by using either Prim’s or Kruskal’s algorithm. We’ll be using Kruskal’s algorithm for this problem.</p>
<h3 id="minimum-spanning-tree">Minimum spanning tree</h3>
<p>What is a minimum spanning tree? A minimum spanning tree, in a connected, undirected, weighted graph, is the series of edges that connect the entire graph, while using minimum total edge weight (sum of all weights of the edges visited by the MST).</p>
<p>Below is an example of a minimum spanning tree of a graph.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/b_rgb:ffffff/v1623076536/vishnu-blog/posts/2021-06-07-ds2/mst.png" alt="Minimum spanning tree" width="50%" /></p>
<p>The idea of Kruskal’s algorithm is to sort each edge in non-decreasing order by its weight (which is conveniently how the edges are given in the input), then add the current edge to the minimum spanning tree if the two vertices are not part of the same set. If we have added the current edge, then merge the sets of both of the vertices that are a part of the edge. Kruskal’s algorithm is an example of a greedy algorithm.</p>
<p>If a minimum spanning tree does not exist (if the graph is disconnected), we should output <code class="language-plaintext highlighter-rouge">Disconnected Graph</code>. We can check for a connected graph by determining if each element in the disjoint-set has the same representative element after Kruskal’s algorithm has been run. If there exists an element in the disjoint-set such that its representative is not equal to another element’s representative, then the graph is disconnected.</p>
<p>Let’s now test our strategy on the sample inputs.</p>
<h2 id="sample-case-1">Sample Case 1</h2>
<h5 id="input">Input</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
</pre></td><td class="rouge-code"><pre>4 4
1 2
1 3
2 3
3 4
</pre></td></tr></tbody></table></code></pre></div></div>
<h5 id="output">Output</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre>1
2
4
</pre></td></tr></tbody></table></code></pre></div></div>
<p>The graph can be represented as follows:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-step1-graph.png" alt="" width="50%" /></p>
<p>Since we can assume that any edge that comes before another edge in the input has a lesser weight than the edge that comes later, there is no need to sort the input. We will use an array to represent our disjoint-set.</p>
<p>Disjoint-set:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-start-dsu.png" alt="" width="50%" /></p>
<p>Array (index 0 will not be used):</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">index</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">value</code></td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Minimum spanning tree: <code class="language-plaintext highlighter-rouge">{}</code></p>
<h3 id="step-1">Step 1</h3>
<p>Edge: <code class="language-plaintext highlighter-rouge">1 2</code>.</p>
<p>Check if 1 and 2 are part of the same set. They are not, so we can merge them. <code class="language-plaintext highlighter-rouge">merge(1, 2)</code></p>
<p>Disjoint-set:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-step1-dsu.png" alt="" width="50%" /></p>
<p>Array:</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">index</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">value</code></td>
<td>0</td>
<td>2</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Minimum spanning tree: <code class="language-plaintext highlighter-rouge">{edge 1}</code></p>
<h3 id="step-2">Step 2</h3>
<p>Edge: <code class="language-plaintext highlighter-rouge">1 3</code>.</p>
<p>Check if 1 and 3 are part of the same set. They are not, so we can merge them. <code class="language-plaintext highlighter-rouge">merge(1, 3)</code></p>
<p>Disjoint-set:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-step2-dsu.png" alt="" width="50%" /></p>
<p>Array:</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">index</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">value</code></td>
<td>0</td>
<td>2</td>
<td>3</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Minimum spanning tree: <code class="language-plaintext highlighter-rouge">{edge 1, edge 2}</code></p>
<h3 id="step-3">Step 3</h3>
<p>Edge: <code class="language-plaintext highlighter-rouge">2 3</code>.</p>
<p>Check if 2 and 3 are part of the same set. They are, so do not add the current edge to the minimum spanning tree.</p>
<p>Disjoint-set:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-step2-dsu.png" alt="" width="50%" /></p>
<p>Array:</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">index</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">value</code></td>
<td>0</td>
<td>2</td>
<td>3</td>
<td>3</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Minimum spanning tree: <code class="language-plaintext highlighter-rouge">{edge 1, edge 2}</code></p>
<h3 id="step-4">Step 4</h3>
<p>Edge: <code class="language-plaintext highlighter-rouge">2 4</code>.</p>
<p>Check if 2 and 4 are part of the same set. They are not, so we can merge them. <code class="language-plaintext highlighter-rouge">merge(2, 4)</code></p>
<p>Disjoint-set:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/v1623592081/vishnu-blog/posts/2021-06-07-ds2/sampleinput1-step4-dsu.png" alt="" width="50%" /></p>
<p>Array:</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">index</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td><code class="language-plaintext highlighter-rouge">value</code></td>
<td>0</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>4</td>
</tr>
</tbody>
</table>
<p>Minimum spanning tree: <code class="language-plaintext highlighter-rouge">{edge 1, edge 2, edge 4}</code></p>
<p>We realize that each element is a part of the same set and has the same representative (4). We can then output the minimum spanning tree.</p>
<p>Now that we have devised a strategy and have confirmed it with the sample input, we can write the code for this problem.</p>
<h2 id="code">Code</h2>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="rouge-code"><pre><span class="cp">#include <bits/stdc++.h>
</span>
<span class="cp">#define el "\n"
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">MM</span> <span class="o">=</span> <span class="mi">100001</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">n</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">dsu</span><span class="p">[</span><span class="n">MM</span><span class="p">];</span>
<span class="n">vector</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">mst</span><span class="p">;</span>
<span class="n">set</span><span class="o"><</span><span class="kt">int</span><span class="o">></span> <span class="n">uni</span><span class="p">;</span>
<span class="kt">int</span> <span class="nf">find</span><span class="p">(</span><span class="kt">int</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">e</span> <span class="o">!=</span> <span class="n">dsu</span><span class="p">[</span><span class="n">e</span><span class="p">])</span> <span class="p">{</span>
<span class="n">dsu</span><span class="p">[</span><span class="n">e</span><span class="p">]</span> <span class="o">=</span> <span class="n">find</span><span class="p">(</span><span class="n">dsu</span><span class="p">[</span><span class="n">e</span><span class="p">]);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">dsu</span><span class="p">[</span><span class="n">e</span><span class="p">];</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">merge</span><span class="p">(</span><span class="kt">int</span> <span class="n">u</span><span class="p">,</span> <span class="kt">int</span> <span class="n">v</span><span class="p">)</span> <span class="p">{</span>
<span class="n">dsu</span><span class="p">[</span><span class="n">find</span><span class="p">(</span><span class="n">u</span><span class="p">)]</span> <span class="o">=</span> <span class="n">find</span><span class="p">(</span><span class="n">v</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">cin</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span><span class="n">ios</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="n">cin</span> <span class="o">>></span> <span class="n">n</span> <span class="o">>></span> <span class="n">m</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">dsu</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><=</span> <span class="n">m</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">;</span>
<span class="n">cin</span> <span class="o">>></span> <span class="n">u</span> <span class="o">>></span> <span class="n">v</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">find</span><span class="p">(</span><span class="n">u</span><span class="p">)</span> <span class="o">!=</span> <span class="n">find</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="p">{</span>
<span class="n">mst</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="n">merge</span><span class="p">(</span><span class="n">u</span><span class="p">,</span> <span class="n">v</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="n">uni</span><span class="p">.</span><span class="n">emplace</span><span class="p">(</span><span class="n">find</span><span class="p">(</span><span class="n">i</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">uni</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"Disconnected Graph"</span> <span class="o"><<</span> <span class="n">el</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="k">auto</span> <span class="n">e</span> <span class="o">:</span> <span class="n">mst</span><span class="p">)</span> <span class="p">{</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">e</span> <span class="o"><<</span> <span class="n">el</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>Blog post views on a static blog for free2021-06-07T20:50:00-04:002021-06-11T14:56:41-04:00https://blog.vishnus.me/posts/blog-views-badge<p><a href="#"><img src="https://antique-fringe-fennel.glitch.me/badge?page_id=a2021-06-07-blog-views-badge.md" /></a></p>
<h2 id="background">Background</h2>
<p>I wanted to create a blog, and do so for free without being bound by a service that holds my content. (GitHub doesn’t count, since the blog files and the posts are saved locally, and I can migrate easily to another git provider, or even a self-hosted git service if I wanted to).</p>
<p>I set up the blog using the <a href="https://github.com/cotes2020/jekyll-theme-chirpy" target="_blank">Chirpy</a> Jekyll theme and I wanted a method to show blog post views. The method that was suggested on various articles and forums was to use Google Analytics’ pageviews feature. I didn’t want to do this because (1) Google Analytics has privacy concerns and (2) Firefox’s Enhanced Tracking Protection feature (enabled by default) does not allow requests to Google Analytics to be made.</p>
<p>You might have noticed the “visitors” badge on every one of my posts. It looks something like this:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-blog-views-badge/badge_iay6su.svg" alt="" /></p>
<p>This is my method of showing page views, and here’s how it’s done (for free).</p>
<h2 id="visitors-badge">Visitors Badge</h2>
<p>There is a handy web application that allows you to embed a visitors badge in Markdown or HTML for free, and statically. The application itself is made using Flask.</p>
<p><a href="https://github.com/jwenjian/visitor-badge" target="_blank">GitHub Repo</a></p>
<p>I suggest that you don’t use the public instance available. Instead, host the code on your Glitch instance.</p>
<h2 id="hosting-the-application">Hosting the Application</h2>
<p>Glitch is a web application hosting platform, similar to Heroku, but it is easier to set up applications on Glitch.</p>
<p><a href="https://glitch.me" target="_blank">Glitch</a></p>
<p>First, create an account on Glitch (or login) then navigate</p>
<p>Then, navigate to your dashboard, and in the top-right corner, click “New Project” and “Import from GitHub” as is shown below.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-blog-views-badge/Screen_Shot_2021-06-08_at_7.12.34_PM_kxq7y2.png" alt="Step 1" width="50%" /></p>
<p>Paste the link “https://github.com/jwenjian/visitor-badge” into the dialogue the appears and wait for the project to load. Then, navigate to the project’s page by pressing the “Show” button in the top-left, then pressing “In a new window”.</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-blog-views-badge/Screen_Shot_2021-06-08_at_7.17.53_PM_uvbqmw.png" alt="Step 2" width="50%" /></p>
<h2 id="adding-the-badge">Adding the Badge</h2>
<p>Then, you’ll a page that looks like this:</p>
<p><img src="https://res.cloudinary.com/dnwczwamg/image/upload/vishnu-blog/posts/2021-06-07-blog-views-badge/Screen_Shot_2021-06-08_at_7.21.19_PM_eqspee.png" alt="Step 3" width="50%" /></p>
<p>Click on “Docs” in the top-right the follow the instructions to embed your badge using Markdown or HTML.</p>
<h2 id="recommended-keeping-application-awake">Recommended: Keeping Application Awake</h2>
<p>There is a catch though; if you’re using Glitch’s free tier (as I am), the application will go to sleep after five minutes of inactivity. You can use a cron job (a repeated task) to stop the application from going to sleep.</p>
<p>To read more about cron, you can read its <a href="https://en.wikipedia.org/wiki/Cron" target="_blank">Wikipedia article</a>.</p>
<p>We’ll be using cron to run a script every four minutes. That script will be a Python script that uses Selenium (a browser automation tool) to visit the Glitch application, therefore ensuring that it never goes to sleep, as long as your computer is awake.</p>
<p>You will need the following technical knowledge.</p>
<ul>
<li>Using the CLI</li>
<li>Python</li>
<li>A basic understanding of Selenium</li>
</ul>
<p>First, you need to download the Firefox browser and “geckodriver”, a browser automation driver that Selenium uses to interact with Firefox.</p>
<p>You can install “geckodriver” from the following link:</p>
<p><a href="https://github.com/mozilla/geckodriver/releases" target="_blank">Install geckodriver</a></p>
<p>Remember the path where “geckodriver” is installed.</p>
<p>Then, create a Python file with the following content:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
</pre></td><td class="rouge-code"><pre><span class="c1">#!/usr/local/bin/python3
</span><span class="kn">from</span> <span class="nn">selenium</span> <span class="kn">import</span> <span class="n">webdriver</span>
<span class="kn">from</span> <span class="nn">selenium.webdriver.firefox.options</span> <span class="kn">import</span> <span class="n">Options</span>
<span class="n">firefox_options</span> <span class="o">=</span> <span class="n">Options</span><span class="p">()</span>
<span class="n">firefox_options</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--headless'</span><span class="p">)</span>
<span class="n">driver</span> <span class="o">=</span> <span class="n">webdriver</span><span class="p">.</span><span class="n">Firefox</span><span class="p">(</span><span class="n">executable_path</span><span class="o">=</span><span class="s">'/path/to/geckodriver'</span><span class="p">,</span> <span class="n">options</span><span class="o">=</span><span class="n">firefox_options</span><span class="p">,</span> <span class="n">service_log_path</span><span class="o">=</span><span class="s">'/dev/null'</span> <span class="k">if</span> <span class="n">on</span> <span class="n">Linux</span><span class="o">/</span><span class="n">Mac</span> <span class="ow">or</span> <span class="s">'nul'</span> <span class="k">if</span> <span class="n">on</span> <span class="n">windows</span><span class="p">)</span>
<span class="n">driver</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'your Glitch application URL'</span><span class="p">)</span>
<span class="n">driver</span><span class="p">.</span><span class="n">quit</span><span class="p">()</span>
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Then, give the Python script the necessary permissions to be run as executable, like the following.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre><span class="nb">chmod</span> +x path/to/script.py
</pre></td></tr></tbody></table></code></pre></div></div>
<p>Use your cron tool to create a task that runs every four minutes. It can look like this on Mac (if you’re using crontab, the in-built cron tool on OS X).</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
</pre></td><td class="rouge-code"><pre><span class="nv">MAILTO</span><span class="o">=</span><span class="s2">""</span>
<span class="k">*</span>/4 <span class="k">*</span> <span class="k">*</span> <span class="k">*</span> <span class="k">*</span> <span class="nb">cd </span>path/to/directory/of/python/script <span class="o">&&</span> ./python_file_name.py 2>&1
</pre></td></tr></tbody></table></code></pre></div></div>
<p>If you’re using a Mac, there may be cron permissions issues, and if the task does not seem to work, you may need to drag the <code class="language-plaintext highlighter-rouge">cron</code> executable from <code class="language-plaintext highlighter-rouge">/usr/sbin</code> into “Full Disk Access” in the Security and Privacy section in System Preferences.</p>
<p>If you want to ensure that your cron job runs even when your computer is asleep or closed, you can run your cron on an online service (none of the free services seemed to work for me though, since I couldn’t run custom scripts).</p>
<p>And that’s it!</p>Solving “Appleby Contest ‘19 P5 - Matrix Operation” on DMOJ2021-06-06T15:02:00-04:002021-06-13T10:10:28-04:00https://blog.vishnus.me/posts/ac19p5<p><a href="#"><img src="https://antique-fringe-fennel.glitch.me/badge?page_id=2021-06-06-ac19p5.md" /></a></p>
<h2 id="problem">Problem</h2>
<p>Problem link: <a href="https://dmoj.ca/problem/ac19p5" target="_blank">https://dmoj.ca/problem/ac19p5</a></p>
<p>Problem type: Dynamic programming</p>
<p>This problem asks us to implement a program that outputs the longest strictly (i.e. can’t be equal) increasing path in an N x N matrix consisting of integers.</p>
<h2 id="solution">Solution</h2>
<p>This problem can be solved by using top-down dynamic programming. The idea is to use recursion (dividing a problem into sub-problems) with memoization (storing, then re-using calculated value for the sub-problems).</p>
<blockquote>
<p>Note that DP stands for dynamic programming.</p>
</blockquote>
<blockquote>
<p>the array <code class="language-plaintext highlighter-rouge">a</code> represents the matrix (input) values and <code class="language-plaintext highlighter-rouge">dp</code> represents the DP table values</p>
</blockquote>
<p>We then have to define a DP state (DP array/table representation) and a DP transition (how a problem relates to its sub-problems).</p>
<p>In this problem, the DP state is as follows.</p>
<p>Let <code class="language-plaintext highlighter-rouge">dp[i][j]</code> represent the longest strictly increasing path in the matrix that begins at <code class="language-plaintext highlighter-rouge">a[i][j]</code>. In this situation, <code class="language-plaintext highlighter-rouge">dp</code> is a two-dimensional array.</p>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">a[i][j]</code> represents the value at row <code class="language-plaintext highlighter-rouge">i</code> and column <code class="language-plaintext highlighter-rouge">j</code> in the matrix given in the input.</p>
</blockquote>
<p>A base case in dynamic programming represents specific DP states that can be pre-calculated without the input or any sub-problems having an impact.</p>
<p>In this case, the base case is as follows.</p>
<p><code class="language-plaintext highlighter-rouge">dp[i][j]</code> = 0 if <code class="language-plaintext highlighter-rouge">a[i][j]</code> has no neighbours that are strictly greater than itself.</p>
<blockquote>
<p>There are four neighbours to any value <code class="language-plaintext highlighter-rouge">a[i][j]</code> that is not in the corner, which are <code class="language-plaintext highlighter-rouge">a[i + 1][j]</code>, <code class="language-plaintext highlighter-rouge">a[i - 1][j]</code>, <code class="language-plaintext highlighter-rouge">a[i][j + 1]</code>, and <code class="language-plaintext highlighter-rouge">a[i][j - 1]</code>.</p>
</blockquote>
<p>Now, let’s think of how we can relate the DP state to other sub-problems. We know that a path must be strictly increasing, so we can only consider neighbours of <code class="language-plaintext highlighter-rouge">a[i][j]</code> if they are greater than <code class="language-plaintext highlighter-rouge">a[i][j]</code>.</p>
<p>Once we determine which neighbours are valid, we have to determine which neighbour to choose as part of the longest path. This is where we can use recursion. Our DP transition is as follows.</p>
<p><code class="language-plaintext highlighter-rouge">dp[i][j]</code> = maximum <code class="language-plaintext highlighter-rouge">dp</code> value of all valid neighbours + 1</p>
<p>There is also one more case we have to handle, which is if <code class="language-plaintext highlighter-rouge">dp[i][j]</code> does not have four neighbours that we can fix by one-indexing the <code class="language-plaintext highlighter-rouge">matrix</code> and <code class="language-plaintext highlighter-rouge">dp</code> arrays and checking whether the neighbours have a value that is not equal to 0.</p>
<p>We will also need to run our recursive function once from every element of the matrix.</p>
<p>Now that we have determined our DP state, base case, and transition, we can test our strategy on the sample case.</p>
<h2 id="sample-case">Sample Case</h2>
<h5 id="input">Input</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
</pre></td><td class="rouge-code"><pre>3
9 8 4
7 2 3
6 1 5
</pre></td></tr></tbody></table></code></pre></div></div>
<h5 id="output">Output</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
</pre></td><td class="rouge-code"><pre>5
</pre></td></tr></tbody></table></code></pre></div></div>
<p>We can test our strategy on this case.</p>
<p>Our matrix is as follows.</p>
<blockquote>
<p>The bolded numbers on the top row and leftmost column represent the <code class="language-plaintext highlighter-rouge">i</code> and <code class="language-plaintext highlighter-rouge">j</code> values</p>
</blockquote>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">a</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>0</td>
<td>9</td>
<td>8</td>
<td>4</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>0</td>
<td>7</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>0</td>
<td>6</td>
<td>1</td>
<td>5</td>
</tr>
</tbody>
</table>
<p>We start by initializing our <code class="language-plaintext highlighter-rouge">dp</code> array to -1. (<code class="language-plaintext highlighter-rouge">memset</code> in C++)</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">dp</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
</tr>
</tbody>
</table>
<blockquote>
<p><code class="language-plaintext highlighter-rouge">f(i, j)</code> represents the recursive function with start value <code class="language-plaintext highlighter-rouge">i</code> and <code class="language-plaintext highlighter-rouge">j</code>.</p>
</blockquote>
<p>We start by calling <code class="language-plaintext highlighter-rouge">f(1, 1)</code></p>
<h3 id="call-f1-1-value--9">Call: <code class="language-plaintext highlighter-rouge">f(1, 1)</code>, value = 9</h3>
<p>Since this value has no strictly greater neighbours (its neighbours are 8 and 7), we return 0. The <code class="language-plaintext highlighter-rouge">dp</code> array does not change.</p>
<p>Returned 0.</p>
<h3 id="call-f1-2-value--8">Call: <code class="language-plaintext highlighter-rouge">f(1, 2)</code>, value = 8</h3>
<p>There is one neighbour that is strictly greater than the current value, which is <code class="language-plaintext highlighter-rouge">i = 1, j = 1</code> with a value of 9. Since the value at <code class="language-plaintext highlighter-rouge">i = 1, j = 1</code> has already been computed, we return <code class="language-plaintext highlighter-rouge">dp[1][1]</code> + 1, which is 1.</p>
<p>Returned 1.</p>
<p><code class="language-plaintext highlighter-rouge">f(i, j)</code> is then called for each value for <code class="language-plaintext highlighter-rouge">i</code> and <code class="language-plaintext highlighter-rouge">j</code> from 1 to <code class="language-plaintext highlighter-rouge">N</code> (matrix size), and the largest value is outputted. At the end of all the calls, the <code class="language-plaintext highlighter-rouge">dp</code> array is as follows.</p>
<table>
<tbody>
<tr>
<td><code class="language-plaintext highlighter-rouge">dp</code></td>
<td><strong>0</strong></td>
<td><strong>1</strong></td>
<td><strong>2</strong></td>
<td><strong>3</strong></td>
</tr>
<tr>
<td><strong>0</strong></td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
<td>-1</td>
</tr>
<tr>
<td><strong>1</strong></td>
<td>-1</td>
<td>0</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td><strong>2</strong></td>
<td>-1</td>
<td>1</td>
<td>4</td>
<td>3</td>
</tr>
<tr>
<td><strong>3</strong></td>
<td>-1</td>
<td>2</td>
<td>5</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>We can now see that the longest strictly increasing path in the matrix has a length of 5 and begins at <code class="language-plaintext highlighter-rouge">i = 3, j = 2</code></p>
<p>Now that we have created a strategy for solving the problem and verified the strategy with our sample case, we can write the code for this problem.</p>
<h2 id="code">Code</h2>
<div class="language-c++ highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table class="rouge-table"><tbody><tr><td class="rouge-gutter gl"><pre class="lineno">1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
</pre></td><td class="rouge-code"><pre><span class="cp">#include <bits/stdc++.h>
</span>
<span class="cp">#define el "\n"
#define ll long long
</span>
<span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">MM</span> <span class="o">=</span> <span class="mi">1502</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">dp</span><span class="p">[</span><span class="n">MM</span><span class="p">][</span><span class="n">MM</span><span class="p">],</span> <span class="n">n</span><span class="p">;</span>
<span class="n">ll</span> <span class="n">a</span><span class="p">[</span><span class="n">MM</span><span class="p">][</span><span class="n">MM</span><span class="p">];</span>
<span class="kt">int</span> <span class="nf">f</span><span class="p">(</span><span class="kt">int</span> <span class="n">r</span><span class="p">,</span> <span class="kt">int</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">dp</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">];</span> <span class="c1">// If dp value has already been calculated, return it (memoization)</span>
<span class="kt">int</span> <span class="n">re</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">r</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">a</span><span class="p">[</span><span class="n">r</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">></span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">])</span> <span class="n">re</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">re</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">r</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">a</span><span class="p">[</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">></span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">])</span> <span class="n">re</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">re</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">r</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">></span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">])</span> <span class="n">re</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">re</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span> <span class="o">-</span> <span class="mi">1</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">></span> <span class="n">a</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">])</span> <span class="n">re</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">re</span><span class="p">,</span> <span class="mi">1</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="n">c</span> <span class="o">+</span> <span class="mi">1</span><span class="p">));</span>
<span class="k">return</span> <span class="n">dp</span><span class="p">[</span><span class="n">r</span><span class="p">][</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">re</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">cin</span><span class="p">.</span><span class="n">tie</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="n">ios</span><span class="o">::</span><span class="n">sync_with_stdio</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// Fast input/output</span>
<span class="n">cin</span> <span class="o">>></span> <span class="n">n</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">ans</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">memset</span><span class="p">(</span><span class="n">dp</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">dp</span><span class="p">));</span> <span class="c1">// Initialize dp array to -1</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">cin</span> <span class="o">>></span> <span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o"><=</span> <span class="n">n</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="n">ans</span> <span class="o">=</span> <span class="n">max</span><span class="p">(</span><span class="n">ans</span><span class="p">,</span> <span class="n">f</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">ans</span> <span class="o"><<</span> <span class="n">el</span><span class="p">;</span>
<span class="p">}</span>
</pre></td></tr></tbody></table></code></pre></div></div>About this blog (and me)2021-06-06T15:00:00-04:002021-06-08T20:01:05-04:00https://blog.vishnus.me/posts/about-me<p><a href="#"><img src="https://antique-fringe-fennel.glitch.me/badge?page_id=about.md" /></a></p>
<p>Hi there, I am Vishnu! I am a high school student who enjoys problem-solving and making an impact through programming.</p>
<p>In this blog, I’ll be exploring various topics relating to programming, such as full-stack development and competitive programming. Do note that I’m a competitive programming beginner and many of the posts I will write about it will mostly be to remember problem-solving techniques of interesting problems. I tend to forget how I solved problems, so to avoid forgetting, I’ll be writing the idea of the problem as a post. I’ll also mostly be solving 7-10 pointers on DMOJ (and the occasional 12-15 pointers).</p>
<p>My DMOJ account is available here: <a href="https://dmoj.ca/user/vishnus"><img src="https://mosesxu.ca/badges/dmoj/vishnus.svg" /></a></p>
<p>This blog is created using the Chirpy Jekyll theme. I didn’t want to use Medium or any other blogging platform since I enjoy the freedom that writing Markdown/HTML gives me in terms of customizability and content.</p>