<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shreyash Rai</title><description>Things I learn and projects I build, a running log of TILs and writeups by Shreyash Rai.</description><link>https://shreyashrai.com</link><item><title>size_t is unsigned, so counting down past zero wraps around</title><link>https://shreyashrai.com/til/cpp-size-t-underflow</link><guid isPermaLink="true">https://shreyashrai.com/til/cpp-size-t-underflow</guid><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had a loop that walked a vector backwards and it never terminated. The bug is
that &lt;code&gt;size_t&lt;/code&gt; is &lt;strong&gt;unsigned&lt;/strong&gt;, so it can never be negative — subtracting past
zero wraps to a huge positive number instead.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Broken: when i == 0, --i wraps to SIZE_MAX, so i &amp;gt;= 0 is always true.
for (size_t i = v.size() - 1; i &amp;gt;= 0; --i) {
    use(v[i]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same trap hides in any &lt;code&gt;v.size() - 1&lt;/code&gt; when the vector is empty: &lt;code&gt;0u - 1&lt;/code&gt;
is &lt;code&gt;SIZE_MAX&lt;/code&gt;, not &lt;code&gt;-1&lt;/code&gt;, so a &quot;last index&quot; computed that way points way off the
end.&lt;/p&gt;
&lt;p&gt;One fix is to offset the index by one and count the &lt;em&gt;other&lt;/em&gt; variable down, so
the loop variable stays in valid unsigned territory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Fixed: i is the count remaining; the real index is i - 1.
for (size_t i = v.size(); i &amp;gt; 0; --i) {
    use(v[i - 1]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The general rule: if a value can go negative, don&apos;t store it in an unsigned
type. Reach for a signed index (or C++20&apos;s &lt;code&gt;std::ssize&lt;/code&gt;) when you need to count
below zero.&lt;/p&gt;
</content:encoded><category>c++</category><category>gotchas</category></item><item><title>How this site works</title><link>https://shreyashrai.com/blog/how-this-site-works</link><guid isPermaLink="true">https://shreyashrai.com/blog/how-this-site-works</guid><description>A static, Markdown-driven site built with Astro — why it exists and how publishing a new post is just adding a file.</description><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This site is a running log of things I learn and the projects I build. The most
important property it has is that publishing is frictionless: writing a new post
is exactly as much work as creating a Markdown file and pushing to git. No CMS,
no dashboard, no database.&lt;/p&gt;
&lt;h2&gt;The stack&lt;/h2&gt;
&lt;p&gt;It&apos;s built with &lt;a href=&quot;https://astro.build&quot;&gt;Astro&lt;/a&gt; as a fully static site. Every TIL
and every post is a Markdown file with a little frontmatter block at the top —
a title, a date, some tags. Astro reads those files at build time, validates the
frontmatter against a schema, and turns each one into a page. The output is
plain HTML and CSS with essentially no client-side JavaScript, so pages load
instantly and there&apos;s nothing to break.&lt;/p&gt;
&lt;p&gt;There are two kinds of writing here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TILs&lt;/strong&gt; (&quot;Today I Learned&quot;) — short, dated, tagged notes. This is the heart
of the site and where most of the activity is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Posts&lt;/strong&gt; — longer writeups and essays, like this one.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Why no JavaScript framework&lt;/h2&gt;
&lt;p&gt;Because the content is the product. A personal site that&apos;s mostly text doesn&apos;t
need a rendering framework shipped to the browser; it needs good typography, a
readable column width, and fast loads. Keeping the build static means the whole
site is a folder of HTML files that any host can serve, and there&apos;s no runtime
to patch or attack.&lt;/p&gt;
&lt;h2&gt;Following along&lt;/h2&gt;
&lt;p&gt;Everything is available as a feed. There&apos;s a
&lt;a href=&quot;/rss.xml&quot;&gt;combined feed&lt;/a&gt; of TILs and posts, and if you only want one or the
other, each has its own. Feeds carry the full text, so you can read without ever
visiting the site — that&apos;s the point of them.&lt;/p&gt;
&lt;p&gt;If you want to see how the sausage is made, the source is on
&lt;a href=&quot;https://github.com/ItsMat78&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>meta</category><category>astro</category></item><item><title>Simon Willison&apos;s link blog — the format worth stealing</title><link>https://shreyashrai.com/links/the-original-link-blog</link><guid isPermaLink="true">https://shreyashrai.com/links/the-original-link-blog</guid><pubDate>Thu, 02 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kicking off a link blog here, the way &lt;a href=&quot;https://simonwillison.net/&quot;&gt;Simon Willison&lt;/a&gt;
does it: short posts that point at something worth your time with a line on why.
Less pressure than an essay, and over a year it becomes the most useful thing on
the site. This is the first one.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://simonwillison.net/&quot;&gt;https://simonwillison.net/&lt;/a&gt;&lt;/p&gt;</content:encoded><category>meta</category><category>blogging</category></item><item><title>“…” — Simon Willison</title><link>https://shreyashrai.com/quotes/willison-on-writing</link><guid isPermaLink="true">https://shreyashrai.com/quotes/willison-on-writing</guid><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;You should blog about things you&apos;ve learned, even if you don&apos;t think anyone will
read it. The act of writing it up is what cements your own understanding.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;— Simon Willison&lt;/p&gt;</content:encoded><category>blogging</category><category>meta</category></item><item><title>Astro&apos;s Content Layer API</title><link>https://shreyashrai.com/links/astro-content-layer</link><guid isPermaLink="true">https://shreyashrai.com/links/astro-content-layer</guid><pubDate>Sun, 28 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The &lt;code&gt;glob()&lt;/code&gt; loader plus Zod schemas are what make every TIL, post, link, and
quote on this site type-checked at build — a malformed frontmatter block fails
&lt;code&gt;astro build&lt;/code&gt; instead of shipping a broken page. Worth a read if you run any
kind of content site.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://docs.astro.build/en/guides/content-collections/&quot;&gt;https://docs.astro.build/en/guides/content-collections/&lt;/a&gt;&lt;/p&gt;</content:encoded><category>astro</category><category>meta</category></item><item><title>Linked Lists</title><link>https://shreyashrai.com/til/linked-lists</link><guid isPermaLink="true">https://shreyashrai.com/til/linked-lists</guid><pubDate>Mon, 22 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Array stores data in continuous or contiguous memory.&lt;/li&gt;
&lt;li&gt;All accessible in O(1) time, because it directly reaches address of elements inside by simple arithmetic, BECAUSE they are all stored together.&lt;/li&gt;
&lt;li&gt;But, there&apos;s problems with this contiguous memory is that when there&apos;s no space for the next element you must copy the elements to a new location, wasting time.&lt;/li&gt;
&lt;li&gt;That&apos;s why we use linked lists because it stores it&apos;s data in random places of the memory and each are connected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Linked Lists&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stores data in Nodes that are spread out in memory but all nodes are storing address of the next node in the list.&lt;/li&gt;
&lt;li&gt;Traversal time complexity: O(n)&lt;/li&gt;
&lt;li&gt;Insertion time complexity: O(n)
&lt;img src=&quot;/public/images/Pasted%20image%2020260622201004.png&quot; alt=&quot;&amp;quot;Meow&amp;quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Arrays vs linkedlists&lt;/h2&gt;
&lt;h3&gt;a) Cost of Accessing an element&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Array needs constant time O(1) because simple arithmetic leads to the next element.&lt;/li&gt;
&lt;li&gt;Address of i th element = Base_address + i * Size_of_data_type&lt;/li&gt;
&lt;li&gt;Linked List needs O(n) where is n is number of elements in the list.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;B) Memory Requirement&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Array has a fixed size, so partially filled array takes as much space as it was full.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;So there&apos;s a lot of unused space in memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sometimes, memory may not be available all the time since contiguous memory so it requires copying of data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Linked List requires extra memory for pointer variables. They are 4 bytes each (in 32bit system). But 8 bytes in 64bit system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But it does not leave unused memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&apos;s usually better than array when the datatype being stored has higher size. But depends on the case on which performs better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nodes being stored at random places in memory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;C) Cost of insertion&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;In the beginning&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays have to shift all elements by one and then insert the value at starting. So O(n)&lt;/li&gt;
&lt;li&gt;Linked List disconnects head node and reattaches new node in the beginning. So O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In the end&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays: Just insert element at the new free location, or copy into new array if it is full. So O(1) or O(n)&lt;/li&gt;
&lt;li&gt;Linked List needs to traverse until the end then attach new node. So O(n)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;At i-th location (average case)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays: Shift some elements forward. So O(n)&lt;/li&gt;
&lt;li&gt;Linked list: Traverse i elements, so O(n)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Implementation in both C and C++&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Making a node&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typedef struct Node{
	int data;
	struct Node* next;
} Node;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;struct Node{
	int data;
	Node* next;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Initializing Linked List&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Node* A; //initialising empty LL
A = NULL; //Setting it as Null initially
Node* temp = (Node*) malloc(sizeof(struct Node)) //typecasting required, creating a new temporary node
(*temp).data = 2; //Filling data in node
(*temp).next = NULL; //Attaching it to null address
A = temp; //Setting A as temp node
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Node* A;
A = NULL;
Node* temp = new Node();
temp-&amp;gt;data = 2;           // -&amp;gt; is basically short form of the deferencing (*) and accessing structure with .
temp-&amp;gt;next = NULL;
A = temp;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Node* temp1 = A;
while (temp-&amp;gt;next != NULL){
	temp1 - temp1 -&amp;gt; next;
}

temp = new Node();
temp-&amp;gt;data = 4;
temp-&amp;gt;next = NULL;
temp1-&amp;gt;next = temp;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

typedef struct Node {
	int data;
	struct Node* next;
} Node;

void Insert(Node** pointerToHead, int x);
void Print(Node* head);

int main(){
	struct Node* head = NULL;
	int n,x;
	printf(&quot;Enter number of nodes: &quot;)
	scanf(&quot;%d&quot;, &amp;amp;n);
	for (int i=0; i &amp;lt; n; i++){
		printf(&quot;Enter a number: &quot;);
		scanf(&quot;%d&quot;, &amp;amp;x);
		Insert(&amp;amp;head, x);
		Print(head);
	}
	printf(&quot;\n&quot;);
}

void Insert(Node** pointerToHead, int x){
	Node* temp = (Node*) malloc(sizeof(struct Node));
	temp-&amp;gt;data = x;
	temp-&amp;gt;next = *pointerToHead;
	*pointerToHead = temp;
}

void Print(Node* head){
	while (head != NULL){
		printf(&quot;%d &quot;,head-&amp;gt;data);
		head = head-&amp;gt;next;
	}
	printf(&quot;\n&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node** is a pointer to pointer. Dereferencing it gives us the pointer to a Node. Then we can use -&amp;gt; to grab its data and next&lt;/li&gt;
&lt;li&gt;We used pointer-to-pointer so that we can modify what is at the address of the memory. If we used pointer directly, that would not work because this new argument inside Insert would be a COPY of the pointer and not the one we want to modify.&lt;/li&gt;
&lt;li&gt;Insert function handles both empty and non-empty linked list as if it is empty then head is null which the new temp node takes anyways.&lt;/li&gt;
&lt;li&gt;For C++ we can use classes and the new function (Node* temp = new Node();) for easy.&lt;/li&gt;
&lt;li&gt;This code still doesn&apos;t free up memory.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>C++</category><category>DSA</category></item><item><title>“…” — Donald Knuth</title><link>https://shreyashrai.com/quotes/knuth-optimization</link><guid isPermaLink="true">https://shreyashrai.com/quotes/knuth-optimization</guid><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;Premature optimization is the root of all evil.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;— Donald Knuth&lt;/p&gt;</content:encoded><category>programming</category></item></channel></rss>