<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>asb&#x27;s corner</title>
    <link rel="self" type="application/atom+xml" href="https://abhamra.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://abhamra.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-02-18T00:00:00+00:00</updated>
    <id>https://abhamra.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Understanding Whole Program Paths and Path Profiling</title>
        <published>2026-02-18T00:00:00+00:00</published>
        <updated>2026-02-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/path-profiling/"/>
        <id>https://abhamra.com/blog/path-profiling/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/path-profiling/">&lt;p&gt;As a part of Georgia Tech’s Compiler Design course, the last &lt;em&gt;sliver&lt;&#x2F;em&gt; of HW1 was to implement part of the trace and compression algorithm from James Larus’ &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cs.cmu.edu&#x2F;afs&#x2F;cs&#x2F;academic&#x2F;class&#x2F;15745-f09&#x2F;www&#x2F;papers&#x2F;p259-larus.pdf&quot;&gt;“Whole Program Paths”&lt;&#x2F;a&gt; paper. I wanted to take some time today to go through the paper’s ideas, my implementation, and some realizations&#x2F;jumps I had to make along the way, partly because it’s interesting and partly because I had fun thinking about some of the problems and techniques introduced to me in this paper. Before this, I had never really conceptualized what actual profiling infrastructure would look like, and in ~2.5 weeks, I’d only gone and written code to do it myself! I will say, this post will probably not deal with the LLVM-isms as much as my thought process and algorithm design, save a few details.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-path-profiling&quot;&gt;What is path profiling?&lt;&#x2F;h2&gt;
&lt;p&gt;Before we begin learning how to path profile, we must begin by understanding what it is. I’m trying and failing not to sound like a wise old sensei.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway.&lt;&#x2F;p&gt;
&lt;p&gt;From one of Larus’ other papers, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;faculty.cc.gatech.edu&#x2F;~harrold&#x2F;6340&#x2F;cs6340_fall2009&#x2F;Readings&#x2F;micro96.pdf&quot;&gt;“Efficient Path Profiling”&lt;&#x2F;a&gt;, we get the following succinct definition:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A path profile determines how many times each acyclic
path in a routine executes&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Simple enough, and the abstract of the EPP paper goes on to say that this is better than basic block or edge profiling because those are “mere approximations of path frequencies” (sarcasm added). It makes sense - one surely has a better understanding of the dynamic behavior of a program if they have a full trace of the program at their fingertips, rather than frequency data on a per-{block, edge} basis.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ho-w-do-we-p-rofile-p-aths-then-wpp&quot;&gt;ho(W) do we (P)rofile (P)aths, then? (WPP)&lt;&#x2F;h2&gt;
&lt;p&gt;The idea of Whole Program Paths begins with the humble acyclic path itself. The procedure itself works in two phases (from §1.1):&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Produce a trace of acyclic paths executed by a program (at runtime)&lt;&#x2F;li&gt;
&lt;li&gt;Convert the trace into a more compact and usable form by finding its inherent regularity (i.e. repeated code).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The result of this procedure is a lossless, compressed DAG representation of the original CFG (control flow graph), that also lends itself nicely to analysis. All in all, this is a really fantastic deal, and even at the outset is a very cool idea that piqued my interest.&lt;&#x2F;p&gt;
&lt;p&gt;Part 1, the acyclic path trace generation, is largely handled by the EPP paper, with some crucial hurdles to overcome that we’ll discuss soon. Part 2 relies on the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.sequitur.info&#x2F;&quot;&gt;SEQUITUR compression algorithm&lt;&#x2F;a&gt;, which is a similarly fascinating algorithm that I didn’t have time to implement from scratch. The high level idea of this algorithm is to take the whole program path trace and convert it into a Context Free Grammar (the other CFG), from whence we can create our DAG.&lt;&#x2F;p&gt;
&lt;p&gt;While actually doing this project, our concrete goal was just to return the final compression ratio $$\frac{\text{old # of symbols in original trace}}{\text{new # of symbols in context free grammar}}$$
and so we didn’t actually need to implement the DAG-ification procedure, instead using the SEQUITUR website’s implementation largely wholesale to get our final results. This, of course, means that Part 1 of our problem is really all we have to focus on, so let’s get crackin’.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;efficient-path-profiling-suboptimal-is-bad&quot;&gt;Efficient Path Profiling (suboptimal is bad)&lt;&#x2F;h3&gt;
&lt;p&gt;In §2 of the WPP paper, “Producing an Acyclic Path Trace”, we learn how to produce an acyclic path trace. Except, we really don’t, because they say “hey just instrument the code like the EPP paper, with some slight modifications”, while making &lt;strong&gt;no attempt to delineate what modifcations those are&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Ironically my first thought was not realizing that they had never actually specified the procedure for generating the path traces in the paper (or its inevitable modifications), but also that they hadn’t defined instrumenting. To &lt;em&gt;instrument&lt;&#x2F;em&gt; a program is to insert code at certain points at compile time in a pass (such as an LLVM Analysis), such that at runtime the code runs correctly &lt;em&gt;&lt;strong&gt;and also&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; stores the trace data in a buffer of sorts, either in memory, by printing it out, or in some secret other way.&lt;&#x2F;p&gt;
&lt;p&gt;All that being said, lettuce now dive into the EPP paper, where our joys begin.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The Efficient Path Profiling paper works in a few key stages, and works on a function’s CFG:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Convert your function’s CFG into a DAG&lt;&#x2F;li&gt;
&lt;li&gt;Assign each acyclic path in the function to a unique natural number via path sums&lt;&#x2F;li&gt;
&lt;li&gt;Use a Max-Weight Spanning Tree to identify chords in the graph, then compute chord increments to maintain path sums when &lt;em&gt;only chords are incremented&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Do the actual code instrumentation!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We leave step 4 for later and focus on the first three steps, explicitly as written in the EPP paper.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-text-cfg-rightarrow-text-dag-text-joy&quot;&gt;(1) $\text{CFG} \rightarrow \text{DAG} = \text{joy}$&lt;&#x2F;h4&gt;
&lt;p&gt;Blissfully unawares of any looming complications, we dive headfirst into the CFG to DAG conversion. The paper is largely clear about this, and for that we all say “thank you”.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;For each vertex v that is the target of one or more
backedges, add a dummy edge $ENTRY \rightarrow v$. For
each vertex $w$ that is the source of one (or more)
backedges, add a dummy edge $w \rightarrow EXIT$. If one
of these edges is not in the spanning tree, it will be instrumented, which is efficient as the edge’s increment
can be combined with the code always added to a loop
backedge to record a path.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So yeah, split the backedge $(u, v)$ into $ENTRY \to v$ and $u \to EXIT$, which un-loops our CFG and makes it a DAG. Problem solved!&lt;&#x2F;p&gt;
&lt;p&gt;If this is all we were doing, we could use a &lt;code&gt;FunctionAnalysisManager&lt;&#x2F;code&gt; to get a &lt;code&gt;DominatorTree&lt;&#x2F;code&gt; from LLVM’s &lt;code&gt;DominatorTreeAnalysis&lt;&#x2F;code&gt;. From here, finding a backedge is as simple as checking if $B$ dominates $A$ for edge $(A, B)$. HOWEVER. Because of unforseen circumstances (&lt;del&gt;foreshadowing&lt;&#x2F;del&gt;), we instead can also do this with a simple DFS traversal, to see if we encounter a block we’ve already seen on our path at a certain point.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Also add a backedge $ENTRY \to EXIT$, which is useful for step 3.
Yeah, we’ll see this later.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h4 id=&quot;2-mapping-paths-to-uids-via-path-sums&quot;&gt;(2) Mapping paths to UIDs via path sums&lt;&#x2F;h4&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhamra&#x2F;personalsite&#x2F;blob&#x2F;master&#x2F;content&#x2F;Images&#x2F;pathsum.png?raw=true&quot; alt=&quot;Pathsum demonstration&quot; align=&quot;right&quot; width=&quot;40%&quot; &#x2F;&gt; 
&lt;p&gt;This is one of the cooler parts of the paper, and I may take a stab at formally verifying it with Lean soon. The core idea is that given some $NumPaths(r)$ paths in a given DAG rooted at $r$, each unique acyclic path is given a path identifier in $[0, NumPaths(r) - 1]$, and all we have to do is assign each edge to an inicrement value such that, at $EXIT$, we get the correct results! When I first saw this and walked through the algorithm, I was pretty excited, because it’s such an elegant idea. Here’s an example we can walk through from the paper, Fig 6 from EPP.&lt;&#x2F;p&gt;
&lt;p&gt;This is currently in its “final state”, with the path increments applied to each edge - check for yourself that there are indeed 6 paths with numberings in $[0, 5]$.&lt;&#x2F;p&gt;
&lt;p&gt;The algorithm, given in Fig 5, is as follows:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;color:#fdf4c1aa;&quot;&gt;&lt;code&gt;&lt;span&gt;foreach vertex v in reverse topological order {
&lt;&#x2F;span&gt;&lt;span&gt;  if v is a leaf vertex {
&lt;&#x2F;span&gt;&lt;span&gt;    NumPaths(v) = 1;
&lt;&#x2F;span&gt;&lt;span&gt;  } else {
&lt;&#x2F;span&gt;&lt;span&gt;    NumPaths(v) = 0;
&lt;&#x2F;span&gt;&lt;span&gt;    for each edge e = v-&amp;gt;w {
&lt;&#x2F;span&gt;&lt;span&gt;      Val(e) = NumPaths(v);
&lt;&#x2F;span&gt;&lt;span&gt;      NumPaths(v) = NumPaths(v) + NumPaths(w);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we first convert the given CFG to a DAG, then find the reverse topological order (perhaps using Kahn’s Algorithm, see my &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;abhamra.com&#x2F;blog&#x2F;aoc24day5&#x2F;&quot;&gt;Advent of Code blog&lt;&#x2F;a&gt; for an example), we get the node list &lt;code&gt;F, E, D, C, B, A&lt;&#x2F;code&gt;. Running the algorithm, we do the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;For &lt;code&gt;F&lt;&#x2F;code&gt;, since it is a leaf, let $NumPaths(F) = 1$.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;E&lt;&#x2F;code&gt; is not a leaf, so let $Numpaths(E) = 0$ to start; there is only one edge ($E \to F$), thus $Numpaths(E) = 1$ and $Val(E \to F) = 0$.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;D&lt;&#x2F;code&gt; is the first interesting case, with two edges coming out of it. We initialize $NumPaths(D) = 0$ as usual, then notice that depending on which order we iterate over the edges ${D \to E, ~D \to F}$, the edges can have different valuations. To stay consistent with the figure, we first handle $D \to F$, setting $Val(D \to F) = 0$, then updating $NumPaths$ and setting $Val(D \to E) = 1$. After this, $NumPaths(D) = 2$ as desired, and we’re done.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It may be helpful to manually follow through with the last three basic blocks, but the above should be sufficient to understand the path sum algorithm.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;3-reducing-instrumentation-via-spanning-trees-and-chords&quot;&gt;(3) Reducing instrumentation via Spanning Trees and Chords&lt;&#x2F;h4&gt;
&lt;p&gt;After we have our DAG &lt;em&gt;with&lt;&#x2F;em&gt; paths weighted according to the increment along them (such that each acyclic path has a unique path sum) (repetition!), we come to the perhaps obvious realization that if we instrmented (read: added extra profiling code) to each edge in the DAG, we would bloat the crap out of our program. This has been widely regarded as a bad move, so can we do better?&lt;&#x2F;p&gt;
&lt;p&gt;Duh, you say, having read the title of this section, to which I respond that you, stand-in reader, are a figment of my imagination and this is unhelpful for pedagogical purposes. Onward we go.&lt;&#x2F;p&gt;
&lt;p&gt;Our goal here is to go from “every edge is instrumented” to “only a few are instrumented”, and one way we can do that is with spanning trees. A spanning tree of a graph $G$ is a subgraph of $G$ that contains every vertex in $G$ and is a tree. It guarantees connectivity, acyclicity, and minimality (using the fewest # of edges to satisfy the previous two conditions, namely $n-1$ edges). All the edges that are in the DAG but not in the spanning tree are called &lt;em&gt;chords&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Chords have a very key property that, when you add any chord to the spanning tree, it creates a unique &lt;em&gt;fundamental&lt;&#x2F;em&gt; cycle; this is a property that we will exploit later to get chordal increment values.&lt;&#x2F;p&gt;
&lt;p&gt;For now, we want to get a Max-Weight Spanning Tree (perhaps with a Modified Kruskal’s algorithm that biases for larger weights rather than the typical min-weight formulation), such that we have min-weight chord edges. &lt;strong&gt;We are creating this spanning tree on an undirected version of the DAG. This will be important in approximately one minute&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;From there, for any chord $c, ~Inc(c)$ is presented as the sum of the edges in the fundamental cycle in Fig 7 of the EPP paper (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;faculty.cc.gatech.edu&#x2F;~harrold&#x2F;6340&#x2F;cs6340_fall2009&#x2F;Readings&#x2F;micro96.pdf&quot;&gt;linked again&lt;&#x2F;a&gt; for convenience), but there is a little more nuance than that. In writing this, I have realized that my attempts at implementing this were wrong, and while my hack works, it is not as elegant as the actual solution so I’ll try to do it justice below.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Let’s take the simple diamond graph $A \to B, ~A \to  C, ~B \to D, ~C \to D$ with backedge $D \to A$. This backedge is akin to our algorithm’s $ENTRY \to EXIT$ backedge. Then, say our original path sum algorithm assigns weights of 0 to every edge except $A\to C$, for which the weight is 1. This is a perfectly valid edge valuation; the two acyclic paths are uniquely identified as 0 and 1.&lt;&#x2F;p&gt;
&lt;p&gt;From here, let’s say our spanning tree is the following edges: ${A\to C, ~B\to D, ~C\to D}$. Then our chords are ${A \to B, ~D \to A}$. The algorithm for finding the increment of chord with spanning tree is as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Find the (&lt;strong&gt;&lt;u&gt;undirected&lt;&#x2F;u&gt;&lt;&#x2F;strong&gt;) fundamental cycle in the graph induced by the spanning tree and the chord&lt;&#x2F;li&gt;
&lt;li&gt;Sum the edges in the fundamental cycle, taking care to &lt;em&gt;invert the sign&lt;&#x2F;em&gt; when we are going against the direction of the flow.&lt;&#x2F;li&gt;
&lt;li&gt;Bob’s your uncle. Well, probably, for some of you. I have a few nice friends named Bob, no uncles though.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For our diamond-graph-with-backedge, let’s concretely check both cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For $D\to A$, $Inc(D\to A) = Val(D\to A)+Val(A\to C)+Val(C\to D) = 0 + 1 + 0 = 1$&lt;&#x2F;li&gt;
&lt;li&gt;For $A\to B$, the cycle in the graph is actually $A \to B \to D \to C \to A$, where the $D \to C$ and $C \to A$ edges are &lt;em&gt;backwards&lt;&#x2F;em&gt;. Thus, $Inc(A\to B) = Val(A\to B)+Val(B\to D)-Val(D\to C)-Val(C \to A) = 0+0-0-1 = -1$.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We can treat the increment on the backedge as “always happening at $EXIT$”, i.e. there’s a constant +1 at the end before storing the path identifier into the trace. Thus, we have increments for each chord, and we can set the increments for all other paths to 0, i.e. we can leave them uninstrumented! Hooray!&lt;&#x2F;p&gt;
&lt;p&gt;For additional reference, the paper cited in the EPP paper is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;186025.186027&quot;&gt;“Efficiently Counting Program Events with Support for On-Line Queries”&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;some-problems-with-naively-using-the-epp-algorithm&quot;&gt;Some problems with naively using the EPP algorithm&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;When using the LLVM framework, and working with an LLVM CFG, one needs to be careful to handle the overall control flow with care. As such, instead of directly converting the CFG into a DAG (which can ruin the control flow unless you use an &lt;code&gt;IRBuilder&lt;&#x2F;code&gt; to change the branching logic directly), we just create our own &lt;code&gt;DAGNode&lt;&#x2F;code&gt; and &lt;code&gt;DAG&lt;&#x2F;code&gt; structs to build and modify our DAG. We then use that DAG for steps 2 and 3 of the EPP paper, before applying our instrumentation logic “from the DAG to the CFG”, as we’ll discuss later.&lt;&#x2F;li&gt;
&lt;li&gt;The EPP paper describes instrumentation for counting the frequency with which each path is encountered (with something like &lt;code&gt;count[r]++&lt;&#x2F;code&gt;, where &lt;code&gt;r&lt;&#x2F;code&gt; represents the path identifier. We need to modify this to instead create a trace buffer, aka a huge array of ints that stores the path identifiers as they arrive in sequence. Paired with this trace buffer will be a trace index that needs to be incremented correctly at the $EXIT$ node so we keep track accurately.&lt;&#x2F;li&gt;
&lt;li&gt;In order to convert the path traces generated by the EPP algorithm on a per function basis into one unified Whole Program Path, you need to somehow distinguish each function’s path identifiers. The way I chose to do this was by using a “base + offset” idea; the first function’s base is 0, and its offset is the path identifier itself. Then, the second function’s base is $0 + NumPaths(\text{first function})$, and the offset is the same idea. You can see where we’re going with this - in general, since every path identifier is in the range $[0, ~NumPaths(\text{entry of func}) - 1]$, each range is cordoned off correctly. If function A has 2 paths, its paths are ${0, ~1}  $. Then, if function B has 3 paths, its paths will end up saved as ${2, ~3, ~4}  $. The base will be the sum of all of the previous functions.&lt;&#x2F;li&gt;
&lt;li&gt;Finally, we have the main disconnect between the paper and implementation. In the WPP paper §2, they mention the following:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Whole program profiling requires a slight redefinition of a path,
so edges leading into a basic block containing a procedure call
terminate acyclic paths&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;As it turns out, they never really quite say how they did this. Dang.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;terminating-acyclic-paths-at-calls&quot;&gt;Terminating acyclic paths at calls&lt;&#x2F;h3&gt;
&lt;p&gt;I spent a couple days of my free time drawing flowgraphs in contrived scenarios before a conversation with my TA initiated a eureka moment of sorts. At that point, I had been working on a very specific test case (Fig 2 in the WPP paper):
&lt;img src=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhamra&#x2F;personalsite&#x2F;blob&#x2F;master&#x2F;content&#x2F;Images&#x2F;initial_with_entry.png?raw=true&quot; alt=&quot;initial cfg&quot; align=&quot;right&quot; width=&quot;23%&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;bar&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;j&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; j;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;; i&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;++&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;bar(i)&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which admits the above original CFG for &lt;code&gt;main&lt;&#x2F;code&gt;, where block &lt;code&gt;C&lt;&#x2F;code&gt; has the call.
The CFG for &lt;code&gt;bar&lt;&#x2F;code&gt; is simple, just a diamond graph to start. As such, we’ll focus on &lt;code&gt;main&lt;&#x2F;code&gt;’s CFG for the call handling.&lt;&#x2F;p&gt;
&lt;p&gt;Before we discuss how to do the call handling, let’s first discuss our output expectations. For &lt;code&gt;main&lt;&#x2F;code&gt;’s CFG, we expect the following 3 paths to be output by the trace:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;$ENTRY\to A \to B\to C\to EXIT$ for the initial call to &lt;code&gt;bar&lt;&#x2F;code&gt; (somehow)&lt;&#x2F;li&gt;
&lt;li&gt;$ENTRY\to B\to C\to EXIT$ for the loop&lt;&#x2F;li&gt;
&lt;li&gt;$ENTRY\to B\to E\to EXIT$ for when we break out of the loop&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The first key realization was that we had to handle calls before handling backedges, as this made the resulting acyclic paths easier to handle while also removing some backedges from the equation during call handling.&lt;&#x2F;p&gt;
&lt;p&gt;The second (and more important) realization was that if we wanted a call to terminate an acyclic path, we needed a way to go from a block ending in a call directly to the $EXIT$ node. From a block &lt;em&gt;ending in a call&lt;&#x2F;em&gt;…&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;ah.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;The idea is simply to split blocks, such that you have an ordered list of blocks that corresponds to the original block, except each block either ends in a call or (in the case of the last one) may not have a call at all. In the above case, we can split block $C$ into the sequence $C_1;C_2$, where $C_1$ contains the call and $C_2$ contains the branching&#x2F;bookkeeping, as well as the for loop’s increment. Then, we can apply this algorithm of mine.
Given an ordered list of blocks $[C_{1}, C_{2}, \ldots , C_{n}]$, as well as $preds(C)$ and $succs(C)$:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;For all $i \in [0, n-2]$, add the edge $C_i \to EXIT$ and $ENTRY\to C_{i+1}$. This terminates the path at callsite $C_i$ while allowing the new path to be handled with “fresh” instrumentation from $ENTRY$ to the post-call code at $C_{i+1}$.&lt;&#x2F;li&gt;
&lt;li&gt;For $C_{n-1}$ (the last block), there are two cases:
&lt;ol&gt;
&lt;li&gt;If last block also ends in a call, then add $C_{n-1} \to EXIT$ and $ENTRY \to S ~\forall S \in succs(C)$. This connects the last block to $EXIT$ (as it has a call, so the path needs to be terminated) and connects all of $C$’s original successors to $ENTRY$ so the instrumentation works correctly.&lt;&#x2F;li&gt;
&lt;li&gt;If the last block &lt;em&gt;doesn’t&lt;&#x2F;em&gt; have a call, then add $ENTRY\to C_{n-1}$ and $C_{n-1} \to S ~\forall S \in succs(C)$. The last block is now a clean successor of the previous block with call. Itdoesn’t need to go to an $EXIT$, so it flows from $ENTRY$. Then, as before, all of the successors of the original block $C$ are connected to it, and we are done!&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhamra&#x2F;personalsite&#x2F;blob&#x2F;master&#x2F;content&#x2F;Images&#x2F;graph_after_transform.png?raw=true&quot; alt=&quot;transformed cfg&quot; align=&quot;right&quot; width=&quot;23%&quot; &#x2F;&gt; 
&lt;p&gt;To the right, you can see what the final DAG looks like. The call handling takes care of the backedge that was present originally! Just as a quick sanity check, let’s also list out the paths we expect to see, and check if they line up with your hopes and dreams from before.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;$ENTRY\to A\to B\to C_{1}\to EXIT$ (the initial)&lt;&#x2F;li&gt;
&lt;li&gt;$ENTRY\to C_{2}\to B\to C_{1}\to EXIT$ (the loop)&lt;&#x2F;li&gt;
&lt;li&gt;$ENTRY\to C_{2}\to B\to E\to EXIT$ (the end condition)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It seems like we’ve done a good job, give yourself a POTB.&lt;&#x2F;p&gt;
&lt;p&gt;It’s also important to remember that this complicates the backedge calculation in the DAG; now we can’t make use of the original CFG’s flow relationships, and need to traverse manually to find our pesky backedges.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;instrumenting-our-cfg-injecting-stuff-to-trace-stuff&quot;&gt;Instrumenting our CFG (injecting stuff to trace stuff)&lt;&#x2F;h2&gt;
&lt;p&gt;The last step in the arduous process of procuring but &lt;em&gt;one&lt;&#x2F;em&gt; trace of a silly little program is to write the code that actually, y’know, stores the trace. After figuring all the previous stuff out, this was way less fun, but here’s generally how the instrumentation procedure works:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;As a precursor to the actual instrumentation, create module level global variables for the trace buffer, trace index (a pointer into the buffer), and the path identifier.&lt;&#x2F;li&gt;
&lt;li&gt;$ENTRY$ Instrumentation: For each successor to the $ENTRY$ node, add a store to the &lt;code&gt;PathId&lt;&#x2F;code&gt; global variable, (re)initializing it at 0.&lt;&#x2F;li&gt;
&lt;li&gt;Chord Instrumentation: For every chord edge $(u, v)$, add a basic block in between with &lt;code&gt;llvm::SplitEdge&lt;&#x2F;code&gt; to get something like $(u, new), ~(new, v)$. In the $new$ block, load in the &lt;code&gt;PathId&lt;&#x2F;code&gt; then add the chord’s increment to it.&lt;&#x2F;li&gt;
&lt;li&gt;$EXIT$ Instrumentation and overflow handling and printing at the end: For this, check if the trace index has reached the length you set your buffer. If not, store the &lt;code&gt;PathId&lt;&#x2F;code&gt; in the trace buffer with a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.yossarian.net&#x2F;2020&#x2F;09&#x2F;19&#x2F;LLVMs-getelementptr-by-example&quot;&gt;GEP&lt;&#x2F;a&gt;, then increment your trace index and (optionally) reset your &lt;code&gt;PathId&lt;&#x2F;code&gt; after storing (although it will likely be done by $ENTRY$ handling anyway).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;heading-to-the-exit&quot;&gt;Heading to the $EXIT$&lt;&#x2F;h2&gt;
&lt;p&gt;And that’s pretty much it! We learned about the Whole Program Paths paper, Efficient Path Profiling, and some ideas necessary to jump from one to the other. I’m planning on trying to verify the path sum stuff, but beyond that I’m just glad I was exposed to this cool new idea and had the chance to think about it deeply.&lt;&#x2F;p&gt;
&lt;p&gt;Thank you for reading!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Proving bounds for the Randomized MaxCut Approximation algorithm in Lean4</title>
        <published>2025-12-19T00:00:00+00:00</published>
        <updated>2025-12-19T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/randomized-maxcut/"/>
        <id>https://abhamra.com/blog/randomized-maxcut/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/randomized-maxcut/">&lt;p&gt;For a given graph &lt;code&gt;G = (V, E)&lt;&#x2F;code&gt;, a cut &lt;code&gt;C&lt;&#x2F;code&gt; is a set of edges such that there is a partition &lt;code&gt;V = (A, B)&lt;&#x2F;code&gt; where all edges &lt;code&gt;e ∈ C&lt;&#x2F;code&gt; have one vertex in &lt;code&gt;A&lt;&#x2F;code&gt; and the other in &lt;code&gt;B&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;MaxCut is a very famous combinatorial optimization problem wherein we want to find the largest such cut. This is useful in scheduling, partitioning, financial portfolio optimization, and more! While the problem itself is NP-Complete, there exist a host of approximation algorithms that allow us to do “pretty good” in practice. To see a careful treatment of deterministic MaxCut algorithms, check out these &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pages.cs.wisc.edu&#x2F;~jyc&#x2F;02-810notes&#x2F;lecture19.pdf&quot;&gt;two&lt;&#x2F;a&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;courses.cs.cornell.edu&#x2F;cs4820&#x2F;2019sp&#x2F;handouts&#x2F;max-cut.pdf&quot;&gt;lecture&lt;&#x2F;a&gt; notes.&lt;&#x2F;p&gt;
&lt;p&gt;Some quick nomenclature: an α-approximation for a (maximization&#x2F;minimization) problem is when we:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;(max) Do as good as 1&#x2F;α * OPT&lt;&#x2F;li&gt;
&lt;li&gt;(min) Do as good as α * OPT&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For our purposes, lets say we don’t even care about doing good right now, just that we care about doing good in expectation. That is, while there exists a 1&#x2F;2-approximation for MaxCut, we want to create an algorithm such that the expected size of our output cut satisfies the 1&#x2F;2 approximation ratio.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;our-simple-algorithm&quot;&gt;Our simple algorithm&lt;&#x2F;h3&gt;
&lt;p&gt;For every vertex &lt;code&gt;v ∈ V = (A, B)&lt;&#x2F;code&gt;, choose with 50% probability whether it is in &lt;code&gt;A&lt;&#x2F;code&gt; or &lt;code&gt;B&lt;&#x2F;code&gt;. That’s it, that creates the cut.&lt;&#x2F;p&gt;
&lt;p&gt;Good job! Take a well-deserved break now.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;proving-it-informally&quot;&gt;Proving it informally&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you’re back from break, let’s get to proving this with words!&lt;&#x2F;p&gt;
&lt;p&gt;For any edge &lt;code&gt;e = (u, v) ∈ E&lt;&#x2F;code&gt;, we have &lt;code&gt;Pr[(u, v) ∈ C] = 1&#x2F;2&lt;&#x2F;code&gt;. For each edge &lt;code&gt;e&lt;&#x2F;code&gt;, create a random variable &lt;code&gt;Xₑ&lt;&#x2F;code&gt; such that &lt;code&gt;Xₑ = 1 if e ∈ C else 0&lt;&#x2F;code&gt;. Notice now that the size of the cut, &lt;code&gt;|C| = ∑ Xₑ&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The overall proof is then &lt;code&gt;E[|C|] = ∑ E[Xₑ] = ∑ Pr[e ∈ C] = |E|&#x2F;2 ≥ |C*|&#x2F;2&lt;&#x2F;code&gt;, for some optimal cut &lt;code&gt;C*&lt;&#x2F;code&gt;. Just throw linearity of expectation and use our previous facts - this, plus the fact that the size of the largest possible cut is bounded by the number of edges (that is, &lt;code&gt;|E| ≥ |C*|&lt;&#x2F;code&gt;), and we get the result we want. &lt;code&gt;|E| = |C*|&lt;&#x2F;code&gt; only when the graph &lt;code&gt;G&lt;&#x2F;code&gt; is bipartite; this follows basically by definition.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proving-it-with-lean&quot;&gt;Proving it with Lean&lt;&#x2F;h2&gt;
&lt;p&gt;Having encountered this simple and elegant algorithm + proof in my algorithms course, I wanted to see if I could formalize it in Lean. I’ve been getting more interested in formal verification, so this seemed like a fun challenge, especially w.r.t the randomization aspect of it! For the uninitiated, Lean is a programming language and proof assistant similar to Rocq. There has been a big movement in recent times to formalize mathematics and CS concepts within the Lean MathLib and CSLib, and I’m eager to see where it goes :)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;structures&quot;&gt;Structures&lt;&#x2F;h3&gt;
&lt;p&gt;The first step is always representing our key structures. Lean already has a &lt;code&gt;SimpleGraph&lt;&#x2F;code&gt;, so all we need to do is design a structure to store our &lt;code&gt;Cut&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- Given some graph G = (V, E)
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- a cut is defined as a set of edges C ⊆ E such that for each edge c = (u, v) ∈ C,
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- we have that u ∈ V₁ and v ∈ V₂, for V₁ ⊕ V₂ (disjoint union) = V
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;structure &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Cut &lt;&#x2F;span&gt;&lt;span&gt;(V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;) (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V) [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;  A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt; V
&lt;&#x2F;span&gt;&lt;span&gt;  B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt; V
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- below are proof obligations
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- propositions are types, proofs are values of those types!
&lt;&#x2F;span&gt;&lt;span&gt;  partition &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∪&lt;&#x2F;span&gt;&lt;span&gt; B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.univ
&lt;&#x2F;span&gt;&lt;span&gt;  disjoint  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Disjoint A B
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also create some helper functions, namely for:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Creating cuts from an assignment, a mapping from vertices to booleans (true in A, false in B)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;size&lt;&#x2F;code&gt; of the cut&lt;&#x2F;li&gt;
&lt;li&gt;Whether a given edge is in the cut at all.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- determine whether an edge is in the cut
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;edgeInCut &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] {G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V}
&lt;&#x2F;span&gt;&lt;span&gt;  (C &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Cut V G) (e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Sym2 V) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=
&lt;&#x2F;span&gt;&lt;span&gt;  e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;lift &lt;&#x2F;span&gt;&lt;span&gt;⟨&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; u v &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;(u &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∈&lt;&#x2F;span&gt;&lt;span&gt; C.A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∧&lt;&#x2F;span&gt;&lt;span&gt; v &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∈&lt;&#x2F;span&gt;&lt;span&gt; C.B) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∨ &lt;&#x2F;span&gt;&lt;span&gt;(u &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∈&lt;&#x2F;span&gt;&lt;span&gt; C.B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∧&lt;&#x2F;span&gt;&lt;span&gt; v &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∈&lt;&#x2F;span&gt;&lt;span&gt; C.A), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;simp &lt;&#x2F;span&gt;&lt;span&gt;[or_comm, and_comm]⟩
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;size &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] {G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V}
&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] (C &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Cut V G) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℕ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= 
&lt;&#x2F;span&gt;&lt;span&gt;  (G.edgeFinset.filter (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; C.edgeInCut e)).card
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- given some characteristic function, use char func to determine A, B
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;ofAssignment &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] {G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V}
&lt;&#x2F;span&gt;&lt;span&gt;  (f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Cut V G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.univ.filter (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; f e)
&lt;&#x2F;span&gt;&lt;span&gt;    B &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.univ.filter (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; v &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; !f v)
&lt;&#x2F;span&gt;&lt;span&gt;    partition &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span&gt; grind
&lt;&#x2F;span&gt;&lt;span&gt;    disjoint  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;simp only &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.disjoint_iff_inter_eq_empty, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;.not_eq_eq_eq_not, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;.not_true]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ext&lt;&#x2F;span&gt;&lt;span&gt; v
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;simp
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Some notable things&lt;&#x2F;strong&gt;:
The backbone of our &lt;code&gt;Cut&lt;&#x2F;code&gt; is the &lt;code&gt;Finset&lt;&#x2F;code&gt;, which is a type representing a finite set of elements of some type α. Since graphs are finite structures, we get a lot of free convenient properties from leveraging &lt;code&gt;Finset&lt;&#x2F;code&gt; here. We also use typeclass declarations for &lt;code&gt;Fintype&lt;&#x2F;code&gt; and &lt;code&gt;DecidableEq&lt;&#x2F;code&gt;. &lt;code&gt;Fintype α&lt;&#x2F;code&gt; lets our function know that α is finite, and &lt;code&gt;DecidableEq&lt;&#x2F;code&gt; knows that propositional equality is decidable for all elements of type α.&lt;&#x2F;p&gt;
&lt;p&gt;Generally, we also use the idea of an assignment function quite a bit, i.e. some mapping from &lt;code&gt;V -&amp;gt; Bool&lt;&#x2F;code&gt; that defines our cut.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;From here on out, I’ll skimp on some of the proof details and go over more of the overarching approaches for some of my lemmas, since that seems like a more economical use of time and article space.&lt;&#x2F;p&gt;
&lt;p&gt;First, we finalize our randomized cut instances and the edge containment indicator function, which basically represents our random variable &lt;code&gt;Χₑ&lt;&#x2F;code&gt; from the proof.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;randomizedMaxCut &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V]
&lt;&#x2F;span&gt;&lt;span&gt;    {G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;(V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;→ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;→&lt;&#x2F;span&gt;&lt;span&gt; Cut V G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; assignment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Cut.ofAssignment (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) assignment
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- use edgeInCut to create a characteristic function returning in {0, 1}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;edgeIndicator &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] {G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V}
&lt;&#x2F;span&gt;&lt;span&gt;  (C &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Cut V G) (e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Sym2 V) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℕ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; Cut.edgeInCut C e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;then &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;proofs&quot;&gt;Proofs&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, in the order I proved them, here are the lemmas and theorems!&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;cut_size_eq_sum_indicators&lt;&#x2F;code&gt;: &lt;code&gt;|C| = ∑ χₑ ∀ e ∈ E&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;lemma &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;cut_size_eq_sum_indicators &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V)
&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] (assignment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    (Cut.ofAssignment (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) assignment).size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    ∑ e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;∈&lt;&#x2F;span&gt;&lt;span&gt; G.edgeFinset, edgeIndicator (Cut.ofAssignment (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) assignment) e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we first unfold our relevant definitions. Then, we convert to using summation for both sides, and finally we simplify and show that our sets are equal; if the sets are equal, their cardinalities must be equal as well!&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;code&gt;count_diff_assignments&lt;&#x2F;code&gt;: half of the 2^N possible assignments have &lt;code&gt;f u ≠ f v&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;lemma &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;count_diff_assignments &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V]
&lt;&#x2F;span&gt;&lt;span&gt;  (u v &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V) (huv &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; u &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;≠&lt;&#x2F;span&gt;&lt;span&gt; v) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.univ.filter (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; f u &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;≠&lt;&#x2F;span&gt;&lt;span&gt; f v)).card &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt;.card (V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This proof is a behemoth of sorts, unexpectedly. The key thread here is to codify the fact that &lt;code&gt;f u ≠ f v&lt;&#x2F;code&gt; is half the space by creating a bijection and showing it is an involution (its own inverse). Then, if we know that the sets &lt;code&gt;f u ≠ f v&lt;&#x2F;code&gt; and &lt;code&gt;f u = f v&lt;&#x2F;code&gt; have the same cardinality, and that they equal &lt;code&gt;2^|V|&lt;&#x2F;code&gt;, we get our result.&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;code&gt;prob_edge_in_cut&lt;&#x2F;code&gt;: &lt;code&gt;Pr[e ∈ C] = 1&#x2F;2&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;lemma &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;prob_edge_in_cut &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V)
&lt;&#x2F;span&gt;&lt;span&gt;  (e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; Sym2 V) (h &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: ¬&lt;&#x2F;span&gt;&lt;span&gt;e.IsDiag) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  (∑ assignment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;, (edgeIndicator (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) (randomizedMaxCut assignment) e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℝ&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; 
&lt;&#x2F;span&gt;&lt;span&gt;  (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt;.card (V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For this proof we use induction on the edges to extract the vertices, then claim that the sum of the indicators when &lt;code&gt;u ≠ v&lt;&#x2F;code&gt; is equal to the cardinality of the &lt;code&gt;Finset&lt;&#x2F;code&gt; when &lt;code&gt;f u ≠ f v&lt;&#x2F;code&gt; (the count of “good” assignments, when not in same vertex set of partition). This, plus our result from the &lt;code&gt;count_diff_assignments&lt;&#x2F;code&gt; (counting lemma) plus some tiny polishing steps gives us our result.&lt;&#x2F;p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;code&gt;expected_cut_size&lt;&#x2F;code&gt;: &lt;code&gt;E[|C|] = |E|&#x2F;2&lt;&#x2F;code&gt; (the important one!)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;theorem &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;expected_cut_size &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V)
&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    (∑ assignment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ((randomizedMaxCut (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) assignment).size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℝ&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt;.card (V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=
&lt;&#x2F;span&gt;&lt;span&gt;      (G.edgeFinset.card &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℝ&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by&lt;&#x2F;span&gt;&lt;span&gt; ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This proof begins with our original expectation statement and chains together our previous proofs to give us our major result. First, we leverage &lt;code&gt;cut_size_eq_sum_indicators&lt;&#x2F;code&gt; to get our size in terms of the indicators. Next, we simulate our linearity of expectation via &lt;code&gt;Finset.sum_comm&lt;&#x2F;code&gt; and &lt;code&gt;Finset.sum_div&lt;&#x2F;code&gt; to move things around. Finally, we use the &lt;code&gt;calc&lt;&#x2F;code&gt; tactic to sequentially show equivalences with the &lt;code&gt;prob_edge_in_cut&lt;&#x2F;code&gt; lemma and summation results to give us our answer!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;a-brief-interlude-finding-the-max-cut&quot;&gt;A brief interlude: finding &lt;em&gt;the&lt;&#x2F;em&gt; Max Cut&lt;&#x2F;h4&gt;
&lt;p&gt;In order to wrap this up and prove things with respect to the actual maximum cut, we need to find a way to represent this. Today I learned about the &lt;code&gt;Finset.univ.sup&lt;&#x2F;code&gt;, meaning “supremum”. A supremum is the smallest quantity greater than or equal to each element of a given (sub)set. In effect, we iterate over all &lt;code&gt;Finset&lt;&#x2F;code&gt;s, create &lt;code&gt;Cut&lt;&#x2F;code&gt;s based off of each possible assignment, and pick the best&#x2F;max one!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;maxCutValue &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V)
&lt;&#x2F;span&gt;&lt;span&gt;  [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℕ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.univ.sup (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span&gt; f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;(Cut.ofAssignment (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) f).size)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Back to the proofs.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;&lt;code&gt;maxCut_le_edges&lt;&#x2F;code&gt;: Maximum cut is at most &lt;code&gt;|E|&lt;&#x2F;code&gt;. This proof is short enough to include in its entirety:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;lemma &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;maxCut_le_edges &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V]
&lt;&#x2F;span&gt;&lt;span&gt;    (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V) [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    maxCutValue G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;≤&lt;&#x2F;span&gt;&lt;span&gt; G.edgeFinset.card &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- notice that finset S&amp;#39;s max size is |E|
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- a Cut can contain at most |E| edges anyway
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unfold&lt;&#x2F;span&gt;&lt;span&gt; maxCutValue
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- sup cut sizes &amp;lt;= num edges
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;apply &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.sup_le
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;intro&lt;&#x2F;span&gt;&lt;span&gt; S &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;_
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- unfold to get finset and card
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unfold&lt;&#x2F;span&gt;&lt;span&gt; Cut.ofAssignment Cut.size
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;-- filtered subset of edges, so cardinality must be less
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;exact &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Finset&lt;&#x2F;span&gt;&lt;span&gt;.card_filter_le &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;_ _
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;&lt;code&gt;rand_approx_guarantee&lt;&#x2F;code&gt;: &lt;code&gt;E[|C|] &amp;gt;= |maxCut|&#x2F;2&lt;&#x2F;code&gt;. This proof is also short, because it stands tall on the backs of giants (the others).&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;Lean&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-Lean &quot;&gt;&lt;code class=&quot;language-Lean&quot; data-lang=&quot;Lean&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;theorem &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;rand_approx_guarantee &lt;&#x2F;span&gt;&lt;span&gt;{V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;} [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableEq&lt;&#x2F;span&gt;&lt;span&gt; V] [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt; V]
&lt;&#x2F;span&gt;&lt;span&gt;  (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;SimpleGraph&lt;&#x2F;span&gt;&lt;span&gt; V) [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;DecidableRel&lt;&#x2F;span&gt;&lt;span&gt; G.Adj] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    (∑ assignment &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ((randomizedMaxCut (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G) assignment).size &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℝ&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Fintype&lt;&#x2F;span&gt;&lt;span&gt;.card (V &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Bool&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;gt;=
&lt;&#x2F;span&gt;&lt;span&gt;    (maxCutValue G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;ℝ&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;by
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;rw &lt;&#x2F;span&gt;&lt;span&gt;[expected_cut_size]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;field_simp
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;norm_cast
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;exact&lt;&#x2F;span&gt;&lt;span&gt; maxCut_le_edges (G &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;:=&lt;&#x2F;span&gt;&lt;span&gt; G)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We basically just use the &lt;code&gt;expected_cut_size&lt;&#x2F;code&gt; and then simplify the division by two on either side, then use our inequality. Note that the expression &lt;code&gt;(∑ assignment : V -&amp;gt; Bool, ((randomizedMaxCut (G := G) assignment).size : ℝ)) &#x2F; (Fintype.card (V -&amp;gt; Bool))&lt;&#x2F;code&gt; accurately represents &lt;code&gt;E[|C|]&lt;&#x2F;code&gt;, because it is the cut size divided by the total number of possible assignments.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;learnings&quot;&gt;Learnings&lt;&#x2F;h3&gt;
&lt;p&gt;Lean is hard. Also, I have to learn to better speak the language; it was pretty challenging to learn how some tactics worked even with the reference (quite mathematically heavy, as is to be expected) and AI tools (more hand-wavy, imprecise at times), but this was a great learning experience and I’m happy I took the time to prove this! My original goal was to try proving something similar about randomized Quicksort, but that felt like too hard a challenge for a Lean novice.&lt;&#x2F;p&gt;
&lt;p&gt;The rest of my code (i.e. the full proofs and my silly comments) can be found at this Github repo: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhamra&#x2F;verif-randomized-maxcut&quot;&gt;verif-randomized-maxcut&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thank you for reading!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>talking</title>
        <published>2025-08-06T00:00:00+00:00</published>
        <updated>2025-08-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/talking/"/>
        <id>https://abhamra.com/blog/talking/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/talking/">&lt;p&gt;Art is a conversation.&lt;&#x2F;p&gt;
&lt;p&gt;It is weird to say without some faux-profundity that I think the goal of art is twofold; for an artist to express their emotions, ideas, reactions to something, and to create an opportunity for dialogue. It seems to me that the most successful artists, or at least the ones we know or perceive the strongest&#x2F;most&#x2F;best, tend to be successful at creating opportunities to discuss art. At the end of Sarah Thornton’s &lt;em&gt;Seven Days in the Art World&lt;&#x2F;em&gt;, she says, “After looking at art, you ask yourself: Is this intriguing? Deeply amusing? Do I want to spend time with it? Does it become more compelling the more I think about it?”&lt;&#x2F;p&gt;
&lt;p&gt;In mulling those words over, I don’t think I’ve felt very strongly about art before, and that is an interesting thing to verbalize because it feels so antithetical to how fascinating I believe it is. I went to the MoMA with my girlfriend recently, and I finally got to see van Gogh’s &lt;em&gt;Starry Nights&lt;&#x2F;em&gt;, as well as Monet’s &lt;em&gt;Water Lilies&lt;&#x2F;em&gt;. They were beautiful, and as an untrained non-artist myself, I can only imagine the sheer depth of technique that made their paintings amazing, both pedagogically and emotionally. And yet, while I enjoyed the aesthetics of these works, I don’t think I managed to feel strongly enough about them.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps I am not conversing with art, not asking the right questions, approaching the canvas as an investigative reporter would, and not as a traveler on the subway asking about your day. Part of me wants to examine an artist’s technique, understand the how, the color theory, the pressure, the composition, the scale. The other, seemingly smaller part of me maybe wants to ask what I’d do if I was there, or ask why I liked it. Perhaps if I was alone in the room, I could think about the water lilies again, think about the sounds there – water lapping at the lilies’ lips, a light breeze rippling across the pearly water and foiling around my ears, the soft ‘plip’ of a fish or frog breaking the surface – and the touch, and the taste of the air, and the water moving and the sun shining, reflecting, refracting, gently through the surface.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds nice.&lt;&#x2F;p&gt;
&lt;p&gt;I could have been there, then. The silence of an empty room with a swathe of canvas would have given way to a new world, or rather a lens into an old one. Perhaps I will go again.&lt;&#x2F;p&gt;
&lt;p&gt;–&lt;&#x2F;p&gt;
&lt;p&gt;When I talk with slightly more modern art, I think the conversation is harder for me, and perhaps for everyone, as it presumes context, which is a fickle thing. Each piece reflects its creator, and as such we first turn to them. As I write this I think about a shirt I have with an abstract, geometric, apparently constructivist piece called &lt;em&gt;Composition of Circles and Overlapping Angles&lt;&#x2F;em&gt; by Sophie Taeuber-Arp, a Swiss Dadaist.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;lh3.googleusercontent.com&#x2F;ci&#x2F;AL18g_RMzJUGJtHVpJ6N0k8eZfmBEtOwuNKjB9EM7bxdInUqvVZj_L9XCHdBK8zj3K5hbdGYUke777m6=s1200&quot; class=&quot;no-style&quot;&#x2F;&gt;
&lt;p&gt;Sophie Taeuber-Arp, &lt;em&gt;Composition of Circles and Overlapping Angles&lt;&#x2F;em&gt;, 1930.&lt;&#x2F;p&gt;
&lt;p&gt;The Museum of Modern Art, New York. The Riklis Collection of McCrory Corporation&#x2F;The Museum of Modern Art, Department of Imaging and Visual Resources&#x2F;©2019 Artists Rights Society (ARS), New York&#x2F;VG Bild-Kunst, Bonn&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;“I enjoy the contrast between the muted blue-grey background and the rest of the colors; in particular, the juxtaposition of the white with the deep orange-red (#FF2F08) and prussian blue (#023E99).”&lt;&#x2F;p&gt;
&lt;p&gt;“I’m drawn to the sandpaper-like texture in the top left, especially how it juts out in the intersections of various other colors”&lt;&#x2F;p&gt;
&lt;p&gt;“The three dots on the left, and three dots on the bottom, have interesting notions of symmetry”&lt;&#x2F;p&gt;
&lt;p&gt;“Why did you paint this? What did it make you feel when painting, and what did you feel while painting it?”&lt;&#x2F;p&gt;
&lt;p&gt;“What sort of techniques did you use to get even geometric shapes, and the sandpaper-esque texture of the brown-gold sections?”&lt;&#x2F;p&gt;
&lt;p&gt;“What do you think is the purpose of art? Is it to enjoy for beauty’s sake, is there any value in that? Should all art be beholden to some orthogonal perspective behind a veil, especially one that acts more as a steep step for many?”&lt;&#x2F;p&gt;
&lt;p&gt;“What is Dadaism? Did you know you were one of the pioneers of the movement, and foundational in the field of concrete art and geometric abstraction?”&lt;&#x2F;p&gt;
&lt;p&gt;“What made you choose the title you chose for this piece?”&lt;&#x2F;p&gt;
&lt;p&gt;“Why?”&lt;&#x2F;p&gt;
&lt;p&gt;–&lt;&#x2F;p&gt;
&lt;p&gt;The “intrinsic decorative urge should not be eradicated,” she wrote, “It is one of humankind’s deep-rooted, primordial urges.”&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;–&lt;&#x2F;p&gt;
&lt;p&gt;Thank you, Ms. Tauber-Arp; I’m glad to have spoken to you. I carry you with me when I walk around, pretending to be sophisticated, trying my hardest to prove my love for things I don’t understand.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps I will go again, and then I’ll get it. After all, it did look cool.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.artnews.com&#x2F;feature&#x2F;sophie-taeuber-arp-dada-why-is-she-important-1234579795&#x2F;&quot;&gt;ARTNews on Sophie Taeuber-Arp&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Are photos even real?</title>
        <published>2025-05-13T00:00:00+00:00</published>
        <updated>2025-05-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/are-photos-real/"/>
        <id>https://abhamra.com/blog/are-photos-real/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/are-photos-real/">&lt;p&gt;Word Count: 1427&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been wondering about this for a fair few months now, ever since I heard it mentioned in a Vergecast episode, or perhaps a video before that on computational photography, or perhaps even before that, when I was writing that joyous exposé into my thoughts on memory. Because that’s what it is for, isn’t it? We take photos largely to remember. Of course, there are those that take photos for art, to edit and beautify to evoke a nice mixture of emotions like Remy’s visualization of taste from Ratatouille, but even that style of photography bears its roots in the idea of remembrance, of giving someone a long-lasting feeling of a place they saw, or never saw but felt like they did because of you and your photo.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;granularity&quot;&gt;granularity.&lt;&#x2F;h2&gt;
&lt;p&gt;A photograph (colloquially referred to by everyone as a photo) has a few definitions, depending on the granularity; here is where the journey of the impostor photo begins. I’ll begin by stating some examples from reputable dictionaries, and will try to order them by pedantry or some other silly metric. Also, I feel it prudent to mention that this all sounds like the beginning of a cheesy wedding vow (“Merriam-Webster’s dictionary says that ‘love’ is defined as…”), but I hope that you, dear reader, will kindly ignore that point. Anywho.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-definitions&quot;&gt;some definitions.&lt;&#x2F;h2&gt;
&lt;p&gt;Cambridge Dictionary defines a photograph as a picture produced by a camera, and says that a camera is a device for taking photographs. Brilliant. The Collins dictionary shares this exact definition.&lt;&#x2F;p&gt;
&lt;p&gt;Merriam-Webster defines a photograph as a picture or likeness obtained by photography, which is immediately unhelpful because now we have to chase through several more definitions. We’ll skip picture, and likeness is relatively similar in nature, so the main one is photography, which they cite as being “the art or process of producing images by the action of radiant energy and especially light on a sensitive surface (such as film or an optical sensor)”. This! This is the good stuff, getting to the heart of the matter!&lt;&#x2F;p&gt;
&lt;p&gt;The Oxford English Dictionary does the most precise job, in my opinion, referring to a photograph as “A picture or image obtained by photography; (originally) a picture made using a camera in which an image is focused on to sensitive material and then made visible and permanent by chemical treatment; (later also) a picture made by focusing an image and then storing it digitally.” As an aside, it was insane that I had to use my Georgia Tech email to access a definition, otherwise I’d have had to use a subscription. Shocking, OED.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;history&quot;&gt;history.&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we’ve nicely sorted our definitions into the spectrum of insane to sane, we can begin discerning what we think a photo is, with a bit of history! The first known instance of development in this space is with the camera obscura, which leverages the property of light wherein it travels in a straight line to project an inverted image onto a wall after passing through a small hole. People later used mirrors to re-invert the image back to the correct orientation for viewing; it’s important to note that this is not technically a photo yet, as there was no way to “save” the state of this light image, it was simply a projection onto a surface. Next there were early photographs, which used the chemical properties of some materials (such as silver salts), notably that they reacted with sunlight. Scientists began devising methods to imprint images using the prior camera obscura work combined with this “storage” mechanism, creating the first rudimentary cameras and photographs! After this came a long series of developments in not only storage medium, but lens design, etc., all of which were chiefly analog in nature, at least by our standards today. Photographic film was the penultimate addition to the lineage of photographic development, and spurred by the modern age, took a life of its own. While the principle is the same, film is much more flexible as a medium and has much better precision in some ways, compared to the methods of yore. The ultimate development (finally, good riddance), is that of the digital camera, which takes the sensor data that was received and encodes it into data that is written onto a storage drive of some sort. Specialized semiconductor image sensors needed to be developed in order to do this, the two main types being Charge-Coupled Device (CCD) and active-pixel (CMOS) sensors, which translate the electromagnetic waves and their attenuation (variability through media) into signals (currents which encode information in circuitry). All that to say I have no real idea how they work, so please don’t ask. This is the type of technology being used in not just larger digital cameras, but also phone cameras. A sort of honorable mention, technological development wise, is the advent of computational photography, which we’ll surely get back to later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-our-foundations&quot;&gt;using our foundations.&lt;&#x2F;h2&gt;
&lt;p&gt;With all our expository rambling out of the way, we can begin examining some of our definitions and examples of photography. I think my qualms with photography are more modern than not, so let’s agree to safely call daguerreotypes, calotypes, and other pre 1900s photographs just that, photographs. I also see no reason why film cameras don’t count, as they still work on the same principles, using light based imaging onto a reactive surface to encode visual information at a specific time. Thusly, we have wandered into the den of the beasts, digital cameras and computational photography. Here, I think we get into the pedantry and semantics more than anything. By all good definitions, the journey of a photograph ends with the digital camera. One could probably better define a digital camera’s action as capturing and storing an image (by translating the light waves to data through specially designed sensors), rather than “capturing a photograph”, because no photograph is taken. So yeah, that’s one faux-photo down, on to the next.&lt;&#x2F;p&gt;
&lt;p&gt;In contrast with digital cameras as a development, which still require precious sensing and direct translation to data that’s stored, computational photography introduces an intermediary processing pipeline into the mix, which takes sensor data and “improves” it according to algorithms and usually to some particular end. For example, Google’s Pixel phones have a mode called “Night Sight” which uses certain computational techniques to drastically improve picture visibility and quality in low-light photography settings (well, as much as one can call it photography, I guess). I regularly watch videos from the MKBHD channel, which does tech reviews and has, in the past, conducted blind smartphone camera tests, which are always quite telling. In referencing this interview, Samsung EVP Patrick Chomet says this in a very nice &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.theverge.com&#x2F;2024&#x2F;2&#x2F;2&#x2F;24059955&#x2F;samsung-no-such-thing-as-real-photo-ai&quot;&gt;Verge article&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;There was a very nice video by Marques Brownlee last year on the moon picture. Everyone was like, ‘Is it fake? Is it not fake?’ There was a debate around what constitutes a real picture. And actually, there is no such thing as a real picture. As soon as you have sensors to capture something, you reproduce [what you’re seeing], and it doesn’t mean anything. There is no real picture. You can try to define a real picture by saying, ‘I took that picture’, but if you used AI to optimize the zoom, the autofocus, the scene – is it real? Or is it all filters? There is no real picture, full stop.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In addition to techniques to auto-balance exposure, saturation, ISO, aperture, etc., we also have techniques that automatically stitch images from multiple cameras for more information, for example. In many ways, what the one, two, or even three cameras on the back of our phone see is never what we see on the screen in front of us. Just like daguerreotypes and calotypes, which were two different types of early image storing mechanisms (i.e. photographs) when cameras were first being invented, nowadays different smartphones have their own camera styles, pros and cons, and features, almost entirely dependent on the computational photography techniques and algorithms used. It’s this insane level of preprocessing that makes me annoyed; more often than not, different phones taking comically different pictures frustrates me. Inane exposure makes photos more aesthetic at times, as do sharper photos on average, but this tends to over accentuate features of pictures, making them somehow less accurate than before.&lt;&#x2F;p&gt;
&lt;p&gt;All photos aren’t real, let’s just revel in the memories and the smiles we capture. Maybe I should buy a nice SLR camera and revel in my cool, hip back to the future analog resurgence. That sounds rather fun, honestly.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>tuesday</title>
        <published>2025-05-06T00:00:00+00:00</published>
        <updated>2025-05-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/tuesday/"/>
        <id>https://abhamra.com/blog/tuesday/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/tuesday/">&lt;p&gt;Today was interesting, an unassuming sort of day which walks past you on the trail, chirping up with a short “Hi” and a modest wave of the digits, ambling about at an average pace, not a care. He has places to be, to be sure, a being of righteous purpose and poise most days, but on this day his work is largely done, and he moves with the calm of the mid-afternoon lull that befits a job reasonably well done. This day carries notes of petrichor, of &lt;em&gt;just enough&lt;&#x2F;em&gt; of God’s own blood blessing us, as it is wont to do. The week has barely begun, and yet instead of a brusque and baleful bout of problems that tends to sink the ship, the bow of this week bursts &lt;em&gt;brightly&lt;&#x2F;em&gt;… with a light breeze and the sun peeking out gently from the clouds. This day wears well-worn jeans, of a slightly darker hue, but still well within the norm, and a nice clean black short-sleeves polo, wrinkles smarting the sides, perhaps a stain near the lower back. All in all, this is a fine day, certainly not &lt;em&gt;Monday&lt;&#x2F;em&gt;, or, God forbid, that horrid timeless moment at the end of Sunday where you realize you have work to contend with. No, today, like many before and many after, is a good, plain day. It keeps you company on the park bench, lets you take a brief moment of respite from the incessant houndings of the world, and then prods you awake when it’s time to return, waving its hand twice as goodbye as it saunters away, shoes thump thump thumping softly against the trail.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Attention</title>
        <published>2025-02-26T00:00:00+00:00</published>
        <updated>2025-02-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/attention/"/>
        <id>https://abhamra.com/blog/attention/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/attention/">&lt;p&gt;…is all you need, all you want, all you can eat, oh wait now there’s a discount, it’s cheap, and suddenly you’re transported into a world where you have it, a future image where you enjoy this thing, where its presence envelops you and comforts you and then the moment is lost and you’re back. back to where you were before, thumbs up and down on the screen, eyes glazed over, and you continue; those brief moments of respite are for the weak and decrepit, you don’t need a break, you need to&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;p style=&quot;text-align: center;&quot;&gt;FOCUS&lt;&#x2F;p&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;but the neurons in your brain disagree, complex chemical calculations crumbling your resolve and careening your consciousness to the Next Big Thing That Happened Just Now; es en todos los redes sociales grandes, you feel? someone died, someone’s alive, stocks up, rates down, hand up, in a roman salute they say, all these moments blending together in a dizzying crescendo they say, but what is really cacophonous and cantankerous and criminal and horrifying and all i want to do is&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;p style=&quot;text-align: center;&quot;&gt;BREATHE&lt;&#x2F;p&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;but it’s so hard, all these tendrils jutting out from screens, tearing my eyes away from my passions, my joys, my reasons to be alive, and honing in on the Next Big Thing – new show just dropped, seems like everything and everyone is recommending it, making me want to watch it, and then i’m forced to, locked into the ecosystem, the cycle, reminded of that one phineas and ferb episode where they’re locked up and re-educated, coerced into clearing their mind, no clamming up just clearing the mind and focusing on the Next Big Thing and then i blink and the video plays and i blink and the video keeps playing and i blink a little harder and my hand moves, largely of my own volition and the video stops.&lt;&#x2F;p&gt;
&lt;p&gt;well.&lt;&#x2F;p&gt;
&lt;p&gt;that’s nice.&lt;&#x2F;p&gt;
&lt;p&gt;a good sound.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;p style=&quot;text-align: center;&quot;&gt;SILENCE.&lt;&#x2F;p&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Untitled 1</title>
        <published>2025-02-05T00:00:00+00:00</published>
        <updated>2025-02-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/untitled-1/"/>
        <id>https://abhamra.com/blog/untitled-1/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/untitled-1/">&lt;p&gt;&lt;em&gt;Word Count: 194&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;It’s there, barely, but it’s there. A maple seed, drifting through the air, floating aimlessly as it swirls by my eyes. In that moment, I see what it could become; a tree with strong roots, quintessentially unique leaves, a beautiful rouge come fall. Brilliant, bountiful branches, each with their own special stories to tell, holding their own weight, an ecosystem of thought supported. And it floats by.&lt;&#x2F;p&gt;
&lt;p&gt;There are more seeds. They, too, float by, going beside me, soaring above me, streaking past me. Some land in my hair as I look up, and a bright light shines. As I look down to focus, pencil scratching on paper (or keys clacking on keyboard), a lossy transfer occurs. And then the seed falls off my head, and I stop.&lt;&#x2F;p&gt;
&lt;p&gt;I feel rooted, sometimes, arms out wide. I continually write my own story as I grow, and my arms support the weight of my dreams, but I only have two. Ten fingers, more granularity, a greater surface area. And the seeds float by.&lt;&#x2F;p&gt;
&lt;p&gt;One day, I will take a step, creak my branches definitively across my body, and catch a seed. Maybe today is that day.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Doing things because they are hard</title>
        <published>2025-02-04T00:00:00+00:00</published>
        <updated>2025-02-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/doing-things-because-theyre-hard/"/>
        <id>https://abhamra.com/blog/doing-things-because-theyre-hard/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/doing-things-because-theyre-hard/">&lt;p&gt;&lt;em&gt;Word Count: 1000&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In another instance of joyous self-therapizing, and because I am too busy to properly nerd out about a paper review or a fun, bite-sized project or topic, today I will be talking about doing things because they are hard.&lt;&#x2F;p&gt;
&lt;p&gt;(I think I started the last foray into my psyche &lt;em&gt;in medias res&lt;&#x2F;em&gt;, but sometimes it’s fun to switch it up; maybe one day I’ll write creatively, and you’ll see my propensity for it..)&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, it all started in 2019, when I really started playing video games.&lt;&#x2F;p&gt;
&lt;p&gt;(Anyway is correct, anyone who says “anyways“ should be taken out back for a stern talking to; colloquialisms are for the weak and imperiled, which you will be if you say “anyways”.)&lt;&#x2F;p&gt;
&lt;p&gt;Technically, one could argue it really started when I began playing Phantom Forces on Roblox in middle school, but for sake of image, I’m going to ask you, dear reader, to ignore that particular fact. Here, we take a brief detour into a fun segment I call&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-do-people-play-video-games&quot;&gt;Why do people play video games?&lt;&#x2F;h2&gt;
&lt;p&gt;For some (including me, at times), it can feel like an escape from reality, a way to space out and enjoy mindless activity. You can rest other parts of your brain and relax, truly let go with the right game, whether that be clicking heads in the latest CoD, wandering an unfamiliar wilderness in Firewatch, or grinding through levels in Celeste. It gives you something to occupy the hands and the mind.&lt;&#x2F;p&gt;
&lt;p&gt;Another great reason to play games is to stay connected with friends who are far away; multiplayer games are released by the hundreds each year, and provide a space to spend time doing the above mindless (or, in some cases, intense) activities with a cadre of capable cadets (that was fun alliteration)!&lt;&#x2F;p&gt;
&lt;p&gt;But really, even though these reasons are true enough, I find myself enjoying games for one particular reason more than the rest; mechanical mastery. Sometimes this may translate into winning games, sometimes not, but the truth of it all is that getting a combo in, or mentally outplaying an opponent, or out-duelling someone, is the peak of fun. The natural addendum to this, then, is to prove to myself that by mastering the most mechanically challenging characters in a game, I’m sick as hell. In Overwatch, this meant learning Genji one-shot combos, ghost dashes, etc., blink pulse’s with Tracer, how to juggle properly with Winston, in addition to all the regular gamesense considerations that make the game even more fun. In THE FINALS, it meant learning how to master sword dash combos on the Light class. In Marvel Rivals, it means getting pummeled while I try to learn Spiderman and Black Panther. It’s brutal, but an exhilarating experience when it works!&lt;&#x2F;p&gt;
&lt;p&gt;Aside: I think I use the rule of three too much. Note to self: revisit writing style.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;and-thus-ends-the-fun-segment&quot;&gt;And thus ends the fun segment&lt;&#x2F;h2&gt;
&lt;p&gt;For whatever reason, learning hard things has been enjoyable in some ways. Another good example from my personal life has been learning Vim, which I started because I thought it would be tough and cool, and now has turned into a sort of immutable mainstay in my life, mostly because now my muscle memory tends towards my Vim binds and it is highly embarrassing when I “hjkl” in textboxes. I have additionally read “Your problem with Vim is that you don’t grok vi” several times, which if you haven’t, you seriously should. It’s a fantastic read about the depth and breadth of stuff that stock Vim supports, and it inspired me to try stock Vim for a while.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-like-why-do-you-have-problems&quot;&gt;But like, why? Do you have problems?&lt;&#x2F;h2&gt;
&lt;p&gt;Yes. Probably. Next question.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;care-to-elaborate&quot;&gt;Care to elaborate?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;del&gt;No.&lt;&#x2F;del&gt; If you insist! There’s a sense of pride and accomplishment that comes with doing the hard thing; with going the distance to reach a height most people don’t get to. To separate yourself. A part of it likely stems from one’s self worth; I, for one, recognize that I measure my self worth frequently relative to those I deem similar to myself in demographic and intellectual capabilities. This is also where it goes wrong. Obviously. I once tried reading “War and Peace” just to say I’d read it – to be clear, probably a great book, but so incredibly dense and just not for me. It was something I’d deemed “hard”, something that I thought would make me seem cultured and cool, saying I’d read Tolstoy’s work. Phooey.&lt;&#x2F;p&gt;
&lt;p&gt;(Is that how you spell that? I’m not sure how much I care about its phoneticization.)&lt;&#x2F;p&gt;
&lt;p&gt;“Comparison is the thief of joy” is something that gets thrown around a lot. I’d argue that based on personal experience, it’s largely true, but not without its nuance. I find myself particularly motivated at times when I see others succeeding, as I’d imagine many others are. Toeing that line is probably the most challenging thing I do on a regular basis, because it forms the foundation for the rest of my day. But really, in its most pure form, I think I have just approached it wrong.&lt;&#x2F;p&gt;
&lt;p&gt;If we strive to do things because they are hard, don’t do it for the destination, do it for the journey. The struggle of learning, the grit and sweat spent in the process, is what makes it worth your while. If you do the hard thing to say you did it, what did you gain except another item on a list, at least in your mind? The recontextualization is tough, but I think it is a valuable journey in and of itself. Hopefully.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-do-we-go-from-here&quot;&gt;Where do we go from here?&lt;&#x2F;h2&gt;
&lt;p&gt;When I was doing things because they were hard for the achievement, I felt as though I’d lost the part of myself that enjoyed learning. It was performative. Assuming this ends up on my website, clearly that hasn’t changed too much, but I’m finally more cognizant of my approaches to self motivation, and I hope to continue learning new things not for others, but for myself. Take care, dear reader, and I’ll see you on Marvel Rivals playing Spiderman.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My relationship with memory</title>
        <published>2024-12-31T00:00:00+00:00</published>
        <updated>2024-12-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/relationship-with-memory/"/>
        <id>https://abhamra.com/blog/relationship-with-memory/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/relationship-with-memory/">&lt;p&gt;&lt;em&gt;Word Count: 2607&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;section-1-impermanence&quot;&gt;Section 1: Impermanence&lt;&#x2F;h3&gt;
&lt;p&gt;A couple days ago, I was in Dallas with my family, visiting family friends for a series of birthdays and Christmas celebrations. At the end of this day, my cousin’s grandmother wanted to play the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Saraswati_veena&quot;&gt;Saraswati veena&lt;&#x2F;a&gt; for us all, a stringed instrument typically used in Carnatic Indian classical music. She started playing when she was nine years old, and when she played for us three days ago, she was 77. For thirty minutes, I was reminded of my 6th grade trip to South India, eating with my hands off a banana leaf plate with my classmates, revelling in the humid heat of Kerala. Her eyes were closed, but her worn hands were true and for that half hour, I was mesmerised. And yet, three days later, I remember her face, her eyes, her hands, her posture, but precious little of the music itself. It’s interesting; the one thing that I cared about the most in that moment was what I remembered the least.&lt;&#x2F;p&gt;
&lt;p&gt;Over the summer, I went to Jazz at Lincoln Center Orchestra in New York to watch Wynton Marsalis and his band play with traditional Indian instrumentalists from both Hindustani and Carnatic backgrounds, in a performance called “The Rhythms of India”. What I remember was that it was fantastic, and I felt moved. Clearly, live music tends to have that effect on me. There was one particular drum solo that I recall being ingrained in my memory for a month after the performance, but as it stands, it’s disappeared, replaced by what feels like a cheap imitation conjured by the mind, even if the memory of the emotions I felt at the performance remain intact. As an aside, if you can, try your best to watch Wynton Marsalis; he’s a fantastic performer and cultivator of the jazz arts, and his “Big Band Holidays” albums are fantastic.&lt;&#x2F;p&gt;
&lt;p&gt;In the seventh grade, I was on a bit of a tear with reading; I had gotten through most of Agatha Christie’s works, and was moving on to sci-fi. My young mind got through a couple books of Frank Herbert’s “Dune”, “Brave New World”, and some of Asimov’s seminal works, like “Foundation” and “I, Robot”. Last week, I went to Barnes and Noble with my friend and stumbled upon “Foundation” again, and picked it up. Now, given my fantastic use of the rule of three here, I’m sure you can see where I’m going with this. But what good is it to say I’ve read “Foundation” if I can’t recall it? Is there any pride, any sense of accomplishment, to be had with saying, “I’ve read all of Poirot!”, if one has a scant recollection regardless? Or is it the emotions we carry on after the fact, the sensations that linger in the mind and perhaps the body, that are of value or import?&lt;&#x2F;p&gt;
&lt;p&gt;As a further extension of that idea, and a brief detour from the overall point, I feel as though this discussion lends itself nicely to tackling the idea of impermanence. Take jazz, for example; I can go to a jazz bar and listen to a wholly unique rendition of a standard, by virtue of improvisation and a skilled band. I can play with my friends, and feel alive as we enable and push each other to grow as musicians. But in the same vein, I can listen to the great &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=zqNTltOGh5c&amp;amp;ab_channel=MilesDavisVEVO&quot;&gt;Miles Davis’ solo on So What&lt;&#x2F;a&gt; again and again, replaying what was, to him, a single moment in 1959. Does this permanence dull its impact on us? Does experiencing something live, but having to deal with the fallibility of memory change its effect on us? To be sure, I prefer live music, and I’d be remiss in saying it doesn’t have its own special way of brightening my day, but I can just as easily get a vinyl of an album I love, and have the sound pour through good speakers, close my eyes, and teleport myself. Glenn Stallcop says on his &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;compandimprov.wordpress.com&#x2F;tag&#x2F;impermanence&#x2F;&quot;&gt;blog&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ideas are only pure in their abstract form.  In reality, they are fleeting and fragile events.  Plato thought that Concepts were the only true reality, and life was just an imperfect reflection or shadow.  But actually, it is the reverse which is true.  Reality is messy and in constant flux.  It is Concepts which are the simple approximations of fleeting moments.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It’s a sobering thought, that everything is technically destined for decay. Some day, there will come a time when Miles Davis’ So What recording from 1959 is played for the last time. Some day, the last page of Tintin will be turned. Some day, someone will watch Grey’s Anatomy for the last time (thank god). My evidently muddled thoughts on (im)permanence have informed a fair few aspects of how I approach the world, and these thoughts are intimately tied to how I approach memory, or the art of remembering things with intentionality.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;section-2-memory-loving-and-knowing&quot;&gt;Section 2: Memory, Loving, and Knowing&lt;&#x2F;h3&gt;
&lt;p&gt;My memory is interesting. I tend to remember vivid flashes of memory from various points in my life – I can, for example, recall when I dropped a die-cast model Discovery Space Shuttle on my foot when I was four years old, at our old house a couple miles from where I’m writing this. I can remember my first (and I believe only) goal in my high school soccer career, running into the box and sliding into the ball, watching it sail past the keeper into the mid left of the net. Being shocked, happy, pumping my fist. I can remember deciding whether or not to take a nap during my APUSH exam (I ended up napping for 10 minutes and then taking the exam anyway). But on the flipside, my short term memory sucks. I forget what I did a couple hours ago, yesterday, last week. It takes an insane amount of effort to remember if I took a shower, or I ate, or I did a task. I have a calendar which I rely on for almost everything, and I mean everything. It has the usual – classes, birthdays (we will come back to this later), tasks, but it also has things like “Call Parents”, “eat”, “go to bed, dumbass”, “check in with friends”, etc. This calendar acts as a storage for some of my mental load, for better or worse. Whether a function of my brain or other factors, I seem to thrive off of regularity, and my calendar is a vehicle for that. I guess in some ways, regularity can make each day seem less meaningful? If the same thing happens each day, the days may blend together. Alternatively, having regularity can make the bright interjections even brighter; going for lunch with my friends, having a nice dinner with my family, visiting Dallas to see my cousins.&lt;&#x2F;p&gt;
&lt;p&gt;A related thought I had, which has come up with my family and partner before, is the idea of memory specifically as it relates to spontaneity. To me, spontaneity is formulaic. You begin by remembering someone or something, and from there you can plan out how to act on it. Some studies do show that spontaneity can be triggered by the reactivation of stored memories, so at least in some sense, my approach isn’t unfounded, but this sort of naturally begs the question: if I offset the mental load of tasks to a calendar, does that make them less meaningful to others? This is something I continue to struggle with, and not something I have the answer to, although it helps to verbalize it here.&lt;&#x2F;p&gt;
&lt;p&gt;“To be loved is to be known” is a quote that resonates quite a bit with me. I don’t really know why, but there’s something warm and sweet in being able to coexist around others, knowing they understand you fundamentally, and it’s changed how I love and show love, in some ways. Interestingly enough, the way I first realized this about myself was through my love of NBC sitcoms. At the time of writing, I’ve watched The Office around 3 or 4 times all the way through, and the first 4 seasons even more. I’ve watched Parks and Recreation at least twice, and I could, at one point, give you the season and episode number of any episode of the first three seasons of Community if you gave me a plot point or two. These shows have shaped who I am in some way, and taught me pop culture, made me appreciate certain styles of humor, and made me glean more about myself in many ways. I will always love them. As it does, however, time passes, and I find it harder to remember the shows’ intimate details, even though I retain the emotions of watching them, and the vibes and enjoyment I had. As an aside, a point of pride for me is feeling as though I know the characters, even if I forget the content. I am almost always able to get into the frame of mind of characters I care about. These shows have clearly impacted me permanently (I make far too many references to count, these days), but it scares me.&lt;&#x2F;p&gt;
&lt;p&gt;Should love be constant and uniform, then? What do we say about the friend we talk to every day, compared to the friend we reach out to once a year and pick up immediately where we left off? Another thing with shows, and media more generally, is the preservation of the image in my mind. As I mentioned earlier, sometimes all I remember of a piece of media is the emotion it brought to me, some memories of the feelings naturally stronger than others (whether by virtue of recency or otherwise). There occasionally exists this tension between my desire to re-up my memory of the content, and my fear of tarnishing the memory of the feeling. Take Avatar: The Last Airbender, for example. I first watched Avatar my sophomore year of high school, and I loved it. Truly; the plot and characters were moving, and I still follow along with the Darkhorse comics and other content that’s released (original movie notwithstanding). That was 5 years ago, though. I’ve grown and hopefully matured as a person, my perspectives have changed, and my humor has changed as well. Watching Avatar now could very well taint my enjoyment of it, past, present, and future. This idea has stopped me from (re)watching a handful of shows that I know I loved, but couldn’t bear the thought of losing the feelings for. Something to work on, or maybe let be.&lt;&#x2F;p&gt;
&lt;p&gt;Continuing with the maxim of loving as knowing, we turn back to interpersonal relationships (oh joy)! This is something I have a curious relationship with (heh), and it stems from an unintentionally strict application of our aforementioned maxim. Similar to characters, I love people by knowing them. Their hobbies, their strengths, their character (for lack of a better word), but also the facts. Their birthdays, their addresses, their families, their accomplishments. I take some pride in being able to wish someone a Happy Birthday early in the day, because I knew it was their birthday! In a very “treat others as you’d like to be treated” way, I imagine that others appreciate being remembered and known just as I would, which is a slight misconception. Sometimes, birthdays feel sad for this reason; it feels as though the people that matter most seem to forget, but I try my best to remind myself that even though I treat this as a maxim, it’s local to me. I don’t really think “love language” categorizations are fair or really accurate, but it’s certainly the case that the act of love is unique to each individual. In any case, I’ve thought about how I love and how it ties in to remembering for quite a bit, and once again it’s nice to put an idea to paper (GDocs).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;section-3-permanence&quot;&gt;Section 3: Permanence&lt;&#x2F;h3&gt;
&lt;p&gt;Pictures and I go way back. I used to want to be a photographer, actually; I got pretty good at Photoshop and Lightroom (as well as a middle schooler could be, at least), and took lots of photographs of landscapes, animals, et cetera. Crucially, I feel the need to point out here that I pirated both, and I vehemently despise Adobe for their subscription model and insane AI practices over the last few years. End minirant. The other side of photography was actually being photographed. For whatever reason, being photographed and thereby being perceived is, or at least was, kind of terrifying to me. A possible reason for this is that by immortalizing a part of me that I didn’t want you to know or see, I feel worse. I do distinctly remember feeling worse about my figure and face growing up; I didn’t like how skinny I was and I didn’t like my smile. This seems to have translated in some way to an aversion to being photographed. It’s gotten a bit better recently, as has my smile (at least I seem to think so, which is what really matters), but the foundations of the fear were quite curious in my opinion. Of course, the other perspective that arises with photographs ties back to our discussion of permanence. There will inevitably be a time when your loved ones leave you – it could even be you first. What do you do when they’re gone? Will you remember them faithfully, and how can you guarantee that? More pointedly, will the memory of the feelings they incited and the emotions surrounding your cumulative interactions be valuable enough to offset the inevitable decay of memory? I don’t remember my Dadu’s voice or face, because I wasn’t really conscious then. We have precious few pictures of him, and he exists primarily in the consciousness of my father and my Dadi. It’s sobering. For all the reasons above, having pictures, videos, and other means of permanence make for a safe back-up of one’s memory.&lt;&#x2F;p&gt;
&lt;p&gt;In the vein of permanence, another thing to think about is sentimentality and one’s legacy; the ways in which we’re remembered, either in the minds of others, through actions making their mark, or objects of significance. For example, I recently had a conversation with my father about watches. He wears an Apple watch most days, but has a few assorted watches that are particularly important to him, including a few gifts from my Nanu, which he cherishes. Through this watch, the memory of my Nanu is shared long after he’s gone (although we hope that isn’t soon), and in it is a special reminder of the relationship between my Nanu and my father as well. As for legacy, that’s a little more involved. What goal do I want when it comes to my legacy? Do I want to be remembered as a good worker, a visionary, a great family man? How consciously should I think about the image of me in others’ minds, and how to form and shape that image? I suppose realistically, only time will tell, and hopefully I can remember to check in on this treatise of sorts and reflect on it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-end-and-beginning&quot;&gt;The end and beginning&lt;&#x2F;h3&gt;
&lt;p&gt;All this started because I asked the question, “If I say I like(d) something, but I don’t remember the content, did I ever really”? I still don’t really know. I think maturing will be realizing eventually that although the decay and fallibility of the mind is inevitable, we can respect that, enjoy the emotions as they pass and linger, and move on. I’m not sure if that’s currently satisfying to me, but it’s what I’ve landed on and I’ve also been typing for about 4 hours, give or take, so there.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you enjoyed,
&lt;br &#x2F;&gt;
– Arjun&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rewriting Rust&#x27;s zip (poorly)</title>
        <published>2024-12-15T00:00:00+00:00</published>
        <updated>2024-12-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/rewriting-zip/"/>
        <id>https://abhamra.com/blog/rewriting-zip/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/rewriting-zip/">&lt;p&gt;Betwixt all of the Marvel Rivals and drumming I’ve been doing since I finished my fall semester, I thought it’d be a good idea to try rewriting &lt;code&gt;std::iter::zip&lt;&#x2F;code&gt;; in the past, I’ve followed along with Jon Gjengset’s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?app=desktop&amp;amp;v=yozQ9C69pNs&amp;amp;t=0s&amp;amp;ab_channel=JonGjengset&quot;&gt;Crust of Rust on Iterators&lt;&#x2F;a&gt; (to make &lt;code&gt;Flatten&lt;&#x2F;code&gt;) and tried my hand at &lt;code&gt;FlatMap&lt;&#x2F;code&gt; as well (see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.eltonpinto.me&#x2F;blog&#x2F;posts&#x2F;implementing_flatmap_in_rust&#x2F;&quot;&gt;Elton Pinto’s blog&lt;&#x2F;a&gt; as a nice insight). This article is inspired by his, although will probably less involved as I found &lt;code&gt;zip&lt;&#x2F;code&gt; to be easier to implement, largely because &lt;code&gt;FlatMap&lt;&#x2F;code&gt;, for example, involves nested iterators and &lt;code&gt;FnMut&lt;&#x2F;code&gt; and other such fancy traits, while &lt;code&gt;Zip&lt;&#x2F;code&gt; is a more intuitive operation. There were only a few hiccups along the way.
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
As an aside, did you know that hiccough is a valid spelling, and hiccup is the more modernized version? English is dumb.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-the-hell-is-a-zip&quot;&gt;What the hell is a zip?&lt;&#x2F;h3&gt;
&lt;p&gt;Rust’s &lt;code&gt;std::iter::zip&lt;&#x2F;code&gt; has one simple goal; when calling &lt;code&gt;zip&lt;&#x2F;code&gt; on two items that can be turned into iterators, we want &lt;code&gt;zip&lt;&#x2F;code&gt; to return pairs of each subsequent entry in each input! That’s a mouthful, but a simple example from the docs will likely help:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; xs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; ys &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; iter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(xs, ys);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;assert!&lt;&#x2F;span&gt;&lt;span&gt;(iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that you hopefully understand what’s happening a bit better, the next step is&lt;&#x2F;p&gt;
&lt;h3 id=&quot;figuring-out-how-to-make-this-shit&quot;&gt;Figuring out how to make this shit&lt;&#x2F;h3&gt;
&lt;p&gt;Most things in the standard library are designed as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Have a function to do a thing (&lt;code&gt;zip&lt;&#x2F;code&gt;), and create a struct that represents the thing you want the result to be &lt;code&gt;Zip&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Use traits, associated types, and generics to implement functionality on top of said resulting thing &lt;code&gt;impl Iterator for ...&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Profit&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So, let’s get started with all of this, beginning with our &lt;code&gt;zip&lt;&#x2F;code&gt; function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: A, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: B) -&amp;gt; Zip&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;A::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;B::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;    B: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    Zip::new(a, b)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We haven’t quite implemented the &lt;code&gt;Zip&lt;&#x2F;code&gt; struct yet, but we will soon. For now, notice that intuitively we need both &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; to be able to be converted to Iterators; thus, we can place the &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; &lt;em&gt;&lt;strong&gt;trait&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; bound on them. Having the bound be &lt;code&gt;Iterator&lt;&#x2F;code&gt; would be “too strict”, in a sense, and would functionally require us to call &lt;code&gt;.into_iter()&lt;&#x2F;code&gt; on everything we’d pass in to &lt;code&gt;zip&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Also, while &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; is a trait, &lt;code&gt;IntoIter&lt;&#x2F;code&gt; is an &lt;em&gt;&lt;strong&gt;associated type&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;! Associated types are type aliases associated with another type&#x2F;trait. You may be thinking, this sounds a lot like generics, and yeah they’re kind of similar, but the crucial difference is that associated types are specific to an implementation (i.e. in the &lt;code&gt;impl&lt;&#x2F;code&gt; block) of a trait, while generics allow multiple implementations. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;waxk1l&#x2F;what_is_the_difference_between_associated_types&#x2F;&quot;&gt;This thread&lt;&#x2F;a&gt; has a good explanation, which I’ll attempt to summarize.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;IntoIterator &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;IntoIter&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Item = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Required method
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the definition of the &lt;code&gt;IntoIterator&lt;&#x2F;code&gt; trait, with the subsequent definition of the &lt;code&gt;IntoIter&lt;&#x2F;code&gt; type as well. Notice here that the type &lt;code&gt;IntoIter&lt;&#x2F;code&gt; resolves to a &lt;em&gt;&lt;strong&gt;concrete type&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;, as IntoIterator is implemented on a specific type. For example, if we call &lt;code&gt;into_iter()&lt;&#x2F;code&gt; on an object of type &lt;code&gt;Vec&amp;lt;u32&amp;gt;&lt;&#x2F;code&gt;, then the &lt;code&gt;Item&lt;&#x2F;code&gt; is of type &lt;code&gt;u32&lt;&#x2F;code&gt;, and thus we create an &lt;code&gt;Iterator&amp;lt;Item = u32&amp;gt;&lt;&#x2F;code&gt;, which is exactly as desired.&lt;&#x2F;p&gt;
&lt;p&gt;Clearly, for each implementation of a given trait for a given type, we have a unique resolution for the associated type, which makes intuitive sense. On the flipside, something like &lt;code&gt;Add&amp;lt;Rhs&amp;gt;&lt;&#x2F;code&gt; can be implemented multiple times for a variety of types of &lt;code&gt;Rhs&lt;&#x2F;code&gt;, i.e. parametric polymorphism (generics).&lt;&#x2F;p&gt;
&lt;p&gt;Now that that’s out of the way, let’s get back to&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zipping-it-time-for-structs&quot;&gt;Zipping it! Time for structs&lt;&#x2F;h3&gt;
&lt;p&gt;Our &lt;code&gt;zip&lt;&#x2F;code&gt; function wants an output of type &lt;code&gt;Zip&amp;lt;A::IntoIter, B::IntoIter&amp;gt;&lt;&#x2F;code&gt;, so let’s do that.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Zip&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;    B: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;A::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;B::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Well. That was easy.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing we’re missing is the &lt;code&gt;new&lt;&#x2F;code&gt; function that we used in &lt;code&gt;zip&lt;&#x2F;code&gt;, but that shouldn’t be too hard:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Zip&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;    B: IntoIterator,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;: A, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span&gt;: B) -&amp;gt; Zip&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;A::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;B::&lt;&#x2F;span&gt;&lt;span&gt;IntoIter&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        Zip {
&lt;&#x2F;span&gt;&lt;span&gt;            a: a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;            b: b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span&gt;(),
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how the return type matches our &lt;code&gt;zip&lt;&#x2F;code&gt; function signature; the rest is pretty reasonable.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;implementing-iterators-interestingly-not&quot;&gt;Implementing Iterators Interestingly (not)&lt;&#x2F;h3&gt;
&lt;p&gt;The last thing we need to do is to make our &lt;code&gt;Zip&lt;&#x2F;code&gt; struct actually somewhat useful, so we need to implement the &lt;code&gt;Iterator&lt;&#x2F;code&gt; trait for it, which will get us all sorts of goodies for free (please do consult the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;standard library&lt;&#x2F;a&gt; if you forget). The only thing we really need to implement for iterators is &lt;code&gt;next&lt;&#x2F;code&gt; (it’s the “required method” they mention in the docs); here’s the code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt; Iterator &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Zip&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;A, B&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where
&lt;&#x2F;span&gt;&lt;span&gt;    A: Iterator,
&lt;&#x2F;span&gt;&lt;span&gt;    B: Iterator,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Item &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;(A::Item, B::Item);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;Self::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt; {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.a.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;.b.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;((x, y))
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we notice that &lt;code&gt;Item&lt;&#x2F;code&gt; is an associated type for &lt;code&gt;Iterator&lt;&#x2F;code&gt;; crucially, it’s not predefined, and so we can set it to whatever we need. Here, since our goal is to get tuples of items from our two iterators, we simply do as described. The function implementation itself is also largely trivial – just get the next values of both iterators, and return a tuple of them. If either is &lt;code&gt;None&lt;&#x2F;code&gt;, the &lt;code&gt;?&lt;&#x2F;code&gt; operator will gracefully handle this and return &lt;code&gt;None&lt;&#x2F;code&gt; for the overall iterator as desired.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;we-re-done&quot;&gt;We’re done??&lt;&#x2F;h3&gt;
&lt;p&gt;Yes.
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
Have a happy holidays and see you next time!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Advent of Code Day 5: Topological Sort!</title>
        <published>2024-12-05T00:00:00+00:00</published>
        <updated>2024-12-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/aoc24day5/"/>
        <id>https://abhamra.com/blog/aoc24day5/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/aoc24day5/">&lt;p&gt;As before with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;abhamra.com&#x2F;blog&#x2F;aoc24day3&#x2F;&quot;&gt;Day 3&lt;&#x2F;a&gt;, I won’t be redescribing the puzzles in full; please check out &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2024&quot;&gt;Advent of Code&lt;&#x2F;a&gt; for more.&lt;&#x2F;p&gt;
&lt;p&gt;This problem was fun to solve, and allows me to do a quick explainer on topological sorting (see part 2), hope you enjoy!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-1-osha-would-be-very-mad&quot;&gt;Part 1: OSHA would be very mad&lt;&#x2F;h3&gt;
&lt;p&gt;The pages of the safety manuals are out of order, oh fie! Whatever shall we do to verify their validity???&lt;&#x2F;p&gt;
&lt;p&gt;(Tragic, I know.)&lt;&#x2F;p&gt;
&lt;p&gt;Histrionics aside, the basis of this problem is simple; we have lines that give us a &lt;code&gt;before|after&lt;&#x2F;code&gt; relation between pages, and then we have lines of pages as a list, and we have to verify that they work. A sample input is as follows:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;color:#fdf4c1aa;&quot;&gt;&lt;code&gt;&lt;span&gt;47|53
&lt;&#x2F;span&gt;&lt;span&gt;97|13
&lt;&#x2F;span&gt;&lt;span&gt;97|61
&lt;&#x2F;span&gt;&lt;span&gt;97|47
&lt;&#x2F;span&gt;&lt;span&gt;75|29
&lt;&#x2F;span&gt;&lt;span&gt;61|13
&lt;&#x2F;span&gt;&lt;span&gt;75|53
&lt;&#x2F;span&gt;&lt;span&gt;29|13
&lt;&#x2F;span&gt;&lt;span&gt;97|29
&lt;&#x2F;span&gt;&lt;span&gt;53|29
&lt;&#x2F;span&gt;&lt;span&gt;61|53
&lt;&#x2F;span&gt;&lt;span&gt;97|53
&lt;&#x2F;span&gt;&lt;span&gt;61|29
&lt;&#x2F;span&gt;&lt;span&gt;47|13
&lt;&#x2F;span&gt;&lt;span&gt;75|47
&lt;&#x2F;span&gt;&lt;span&gt;97|75
&lt;&#x2F;span&gt;&lt;span&gt;47|61
&lt;&#x2F;span&gt;&lt;span&gt;75|61
&lt;&#x2F;span&gt;&lt;span&gt;47|29
&lt;&#x2F;span&gt;&lt;span&gt;75|13
&lt;&#x2F;span&gt;&lt;span&gt;53|13
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;75,47,61,53,29
&lt;&#x2F;span&gt;&lt;span&gt;97,61,53,29,13
&lt;&#x2F;span&gt;&lt;span&gt;75,29,13
&lt;&#x2F;span&gt;&lt;span&gt;75,97,47,61,53
&lt;&#x2F;span&gt;&lt;span&gt;61,13,29
&lt;&#x2F;span&gt;&lt;span&gt;97,13,75,29,47
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our end goal for part 1 is to sum up the middle pages of all of the “correctly ordered” lines, but I will mostly be focusing on how we can check for that, rather than the overall solution.&lt;&#x2F;p&gt;
&lt;p&gt;To begin, I create a &lt;code&gt;rule_map&lt;&#x2F;code&gt; that contains, for every &lt;code&gt;before&lt;&#x2F;code&gt; page, a &lt;code&gt;HashSet&lt;&#x2F;code&gt; of all of the pages that must come after it! For example, in the above input, notice that &lt;code&gt;13&lt;&#x2F;code&gt; must come after &lt;code&gt;29&lt;&#x2F;code&gt;, so that gets placed in our &lt;code&gt;rule_map&lt;&#x2F;code&gt;. This is populated as follows:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;rule_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;entry&lt;&#x2F;span&gt;&lt;span&gt;(before)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;and_modify&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;after_pages&lt;&#x2F;span&gt;&lt;span&gt;| { 
&lt;&#x2F;span&gt;&lt;span&gt;        after_pages.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(after); 
&lt;&#x2F;span&gt;&lt;span&gt;    }).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;or_insert&lt;&#x2F;span&gt;&lt;span&gt;(HashSet::from([after]));
&lt;&#x2F;span&gt;&lt;span&gt;rule_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;entry&lt;&#x2F;span&gt;&lt;span&gt;(after).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;or_insert&lt;&#x2F;span&gt;&lt;span&gt;(HashSet::new());
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We add an entry for after to make it easier to handle cases later.&lt;&#x2F;p&gt;
&lt;p&gt;Then, the real checking begins when we encounter the lines, and the logic here is that since we have a mapping (for a given page number) of all of the pages that should come after it, if we have seen a page that should come after our current page, we know we’ve found an incorrect list.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;&amp;#39;outer&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(file).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Do some stuff here that isn&amp;#39;t relevant to this code block
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; ...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; seen &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;HashSet::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;::with_capacity(nums.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;());
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; num &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;nums {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; after_pages &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; rule_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;num).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; checks for the bad thing
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; found &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; after_pages.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;any&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span&gt;| seen.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(val));
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; found {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;continue &amp;#39;outer &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; skip this entire line, basically
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        seen.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;num);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A small nifty thing here is the &lt;code&gt;continue &#x27;outer&lt;&#x2F;code&gt; syntax; if we are in a for loop that is nested, but we want to break out of the outer for loop, we can tag the outer for loop with &lt;code&gt;&#x27;outer: for ... in ...&lt;&#x2F;code&gt;, and then use the &lt;code&gt;continue &#x27;outer&lt;&#x2F;code&gt; syntax! This also works with &lt;code&gt;break&lt;&#x2F;code&gt; as well.&lt;&#x2F;p&gt;
&lt;p&gt;After this, if we haven’t found an error, then we just add the middle page values up with &lt;code&gt;sum += nums[nums.len()&#x2F;2]&lt;&#x2F;code&gt; (simple as).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-2-topo-sort-is-inevitable&quot;&gt;Part 2: Topo-sort is inevitable&lt;&#x2F;h3&gt;
&lt;p&gt;There are 100% other ways to do part 2.&lt;&#x2F;p&gt;
&lt;p&gt;However.&lt;&#x2F;p&gt;
&lt;p&gt;I could not find them.&lt;&#x2F;p&gt;
&lt;p&gt;It was 2 AM again.
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
&lt;br &#x2F;&gt;
Anywho.&lt;&#x2F;p&gt;
&lt;p&gt;So the basis of this problem is that for all of the incorrect rows we marked previously, we now want to fix them and find the sum of &lt;em&gt;their&lt;&#x2F;em&gt; middle pages, a la part 1. Originally I was thinking of some sort of bubble sort esque swapping solution, but I couldn’t intuit it nicely, so I went with topological sorting instead since it felt somewhat natural.&lt;&#x2F;p&gt;
&lt;p&gt;As a brief aside, it felt natural primarily because we’ve been dealing with what is essentially a dependency graph this entire time, and it’d be a shame not to leverage that structure with a nicely made DAG just sitting there, yknow?&lt;&#x2F;p&gt;
&lt;p&gt;So the rest of this section is going to basically just be an introduction to topological sorting because you can probably fill in the gaps as to how the rest of part 2 is done.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;topological-sorting-for-dummies&quot;&gt;Topological Sorting, for dummies&lt;&#x2F;h4&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;github.com&#x2F;abhamra&#x2F;personalsite&#x2F;blob&#x2F;master&#x2F;content&#x2F;Images&#x2F;toposort.jpg?raw=true&quot; alt=&quot;Topological Sort&quot; align=&quot;right&quot; width=&quot;40%&quot; &#x2F;&gt; 
&lt;p&gt;Simply put, given a directed acyclic graph (DAG), a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Topological_sorting&quot;&gt;topological sort&lt;&#x2F;a&gt; is a linear ordering of vertices such that for all edges from &lt;em&gt;u&lt;&#x2F;em&gt; to &lt;em&gt;v&lt;&#x2F;em&gt;, &lt;em&gt;u&lt;&#x2F;em&gt; is “before” &lt;em&gt;v&lt;&#x2F;em&gt; in the linear ordering.&lt;&#x2F;p&gt;
&lt;p&gt;A good example is in this image which is for this original list &lt;code&gt;[97,13,75,29,47]&lt;&#x2F;code&gt; (thank you to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vedthiru.com&quot;&gt;Ved&lt;&#x2F;a&gt; for the graph).&lt;&#x2F;p&gt;
&lt;p&gt;There are a few ways to implement toposort, but the most intuitive to me is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Topological_sorting#Kahn&amp;#x27;s_algorithm&quot;&gt;Kahn’s Algorithm&lt;&#x2F;a&gt;, which goes as follows:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;(Prior to doing much of anything) For the list you are trying to sort, calculate the “in degree” of each vertex; this is just the number of nodes that have edges flowing into the current node.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; in_degree: HashMap&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;HashMap::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;node &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;input {
&lt;&#x2F;span&gt;&lt;span&gt;    in_degree.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span&gt;(node, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; from &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;input {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(neighbors) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; rule_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;from) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; neighbors {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; input.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;to) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;in_degree.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;entry&lt;&#x2F;span&gt;&lt;span&gt;(to).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;or_insert&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;+= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that we have to be careful to do our in degree calculation locally, and not over the whole list, since the whole list may not have a valid topological sort (may not be an acyclic graph).&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Now that we have our in degree calculated for all relevant nodes, we can create a queue of zero in degree nodes. Intuitively, we want to start at the nodes that have no other nodes as dependencies. This can be done easily with:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; zero_in_degree: VecDeque&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; in_degree
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;(_, &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;deg&lt;&#x2F;span&gt;&lt;span&gt;)| deg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|(&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;node&lt;&#x2F;span&gt;&lt;span&gt;, _)| node)
&lt;&#x2F;span&gt;&lt;span&gt;    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Do the actual topological sort. This is arguably best explained with the code itself, so take a look below and I’ll explain in bits and pieces after:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; sorted &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(node) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; zero_in_degree.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;pop_front&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    sorted.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(node);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(neighbors) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; rule_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;node) {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; neighbor &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in&lt;&#x2F;span&gt;&lt;span&gt; neighbors {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(count) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; in_degree.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;get_mut&lt;&#x2F;span&gt;&lt;span&gt;(neighbor) {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;count &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;-= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;count &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;                    zero_in_degree.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push_back&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;neighbor);
&lt;&#x2F;span&gt;&lt;span&gt;                }
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;First, we take a node from the zero in degree queue and add it to the sorted list.&lt;&#x2F;li&gt;
&lt;li&gt;Then, for all of the neighbors of the popped node, decrement their in degree. You can think of this as deleting a node that feeds into the neighbors, so decrementing is natural.&lt;&#x2F;li&gt;
&lt;li&gt;If the new in degree of any of the neighbors is 0, they get added to the zero in degree queue, and we repeat until done!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;life-s-sorted-again&quot;&gt;Life’s sorted again&lt;&#x2F;h3&gt;
&lt;p&gt;And there you have it, done with day 5! This was a pretty fun problem to solve, and I’m somewhat happy with how my solution turned out. See you next time :D&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Advent of Code Day 3: Overengineering</title>
        <published>2024-12-03T00:00:00+00:00</published>
        <updated>2024-12-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/aoc24day3/"/>
        <id>https://abhamra.com/blog/aoc24day3/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/aoc24day3/">&lt;p&gt;So I’m doing Advent of Code this year, and hopefully we can stick through all 25 days. Day 3’s problem was particularly interesting to me, and I did some silly (and hopefully somewhat clever) stuff that I think would be fun to write about.&lt;&#x2F;p&gt;
&lt;p&gt;Here we are.&lt;&#x2F;p&gt;
&lt;p&gt;I likely won’t redescribe the puzzles in full - for that, just head over to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2024&quot;&gt;Advent of Code&lt;&#x2F;a&gt; - but I will summarize the parts briefly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-1-this-is-where-the-fun-begins&quot;&gt;Part 1: This is where the fun begins&lt;&#x2F;h3&gt;
&lt;p&gt;So the main goal of this problem is to, within a single line&#x2F;string, find matches of &lt;code&gt;mul(num1, num2)&lt;&#x2F;code&gt; and sum up all of the multiplication operations, giving you your answer. The sample text they provide for this is:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;color:#fdf4c1aa;&quot;&gt;&lt;code&gt;&lt;span&gt;xmul(2,4)%&amp;amp;mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which will eventually output &lt;code&gt;(2*4 + 5*5 + 11*8 + 8*5) = 161&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I thought I could do it with Regex, and you certainly could, but that didn’t feel like a satisfying enough solution to me. One of my friends also challenged me to use just Rust’s standard library and nothing else, so that removed the &lt;code&gt;regex&lt;&#x2F;code&gt; crate from contention entirely. My next idea, which is what I ended up going with, was to basically handwrite a lexer and do some nifty sliding window magic.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-1-defining-tokens&quot;&gt;Step 1: Defining Tokens&lt;&#x2F;h4&gt;
&lt;p&gt;First thing’s first, we have to define the tokens we’re going to be using. With a little bit of inspiration from the fantastic &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;craftinginterpreters.com&#x2F;scanning.html&quot;&gt;Crafting Interpreters&lt;&#x2F;a&gt;, I ended up with the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;Token &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;LPAREN&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;RPAREN&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;COMMA&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;MUL&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;OTHER&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; throwaway
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(To be clear, Crafting Interpreters also helped elsewhere)&lt;&#x2F;p&gt;
&lt;p&gt;Clearly, the only tokens that make up something like &lt;code&gt;mul(num1, num2)&lt;&#x2F;code&gt; are &lt;code&gt;mul&lt;&#x2F;code&gt;, &lt;code&gt;(&lt;&#x2F;code&gt;, &lt;code&gt;,&lt;&#x2F;code&gt;, &lt;code&gt;)&lt;&#x2F;code&gt;, and numbers. Anything else is captured as &lt;code&gt;OTHER&lt;&#x2F;code&gt; and thrown away (handled, admittedly, in quite a disgraceful way. I wonder what my future employers would think).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-2-lexing-the-damn-thing&quot;&gt;Step 2: Lexing the damn thing&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Warning: there’s gonna be a shitload of code below. I will explain it in a moment&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;First, we set up the file reading and the iterator over our characters:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span&gt;(file).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; iter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; line.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;peekable&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; tokens: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;Token&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;::new();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We call &lt;code&gt;peekable()&lt;&#x2F;code&gt; on our iterator because the &lt;code&gt;Peekable&lt;&#x2F;code&gt; struct provides us the &lt;code&gt;peek&lt;&#x2F;code&gt; method, which allows us to look at the next character without consuming it. This is particularly advantageous when we want to look ahead just once or twice in a controlled manner.&lt;&#x2F;p&gt;
&lt;p&gt;Now, here’s where the magic happens!&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;while let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(ch) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; ch {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;(&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;LPAREN&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;)&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;RPAREN&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;,&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;COMMA&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;1&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;9&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;once&lt;&#x2F;span&gt;&lt;span&gt;(ch)
&lt;&#x2F;span&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;chain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;from_fn&lt;&#x2F;span&gt;&lt;span&gt;(|| iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;by_ref&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_if&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_ascii_digit&lt;&#x2F;span&gt;&lt;span&gt;())))
&lt;&#x2F;span&gt;&lt;span&gt;                .collect::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()
&lt;&#x2F;span&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(n));
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;m&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;u&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;l&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;                tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;MUL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;_ =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;OTHER&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a lot, so I’ll break it down for the relevant chunks. We’ve also removed the part 2 code from here as well (and it will return soon). Naturally, we start by iterating until there are no more characters to yield. In each match arm, we handle a specific character case.&lt;&#x2F;p&gt;
&lt;p&gt;The parentheses and the comma are pretty self-explanatory - just add the corresponding token variant to the vector - but the number and &lt;code&gt;mul&lt;&#x2F;code&gt; keyword handling are slightly more involved.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;1&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;9&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; n: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;once&lt;&#x2F;span&gt;&lt;span&gt;(ch)
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;chain&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;from_fn&lt;&#x2F;span&gt;&lt;span&gt;(|| iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;by_ref&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_if&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;| s.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_ascii_digit&lt;&#x2F;span&gt;&lt;span&gt;())))
&lt;&#x2F;span&gt;&lt;span&gt;        .collect::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(n));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This seems like a bit of word vomit, but is nicer with a few choice words explaining it, I hope. It’s also largely lifted from &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;brunocalza.me&#x2F;writing-a-simple-lexer-in-rust&#x2F;&quot;&gt;this post&lt;&#x2F;a&gt; by Bruno Calza, so thank you Bruno. Here, we essentially chain together &lt;code&gt;iter::once(ch)&lt;&#x2F;code&gt; (i.e., a single repetition of the first&#x2F;matched character, to make sure it’s included in the resulting String), followed by all of the following characters that are digits, using &lt;code&gt;Peekable&lt;&#x2F;code&gt;’s &lt;code&gt;next_if&lt;&#x2F;code&gt; function, which takes in a function that returns a boolean and allows us to continue based on a condition. I won’t go into much more depth, but this is an interesting construction that I did not entirely come up with.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, there’s the &lt;code&gt;mul&lt;&#x2F;code&gt; keyword match. The idea is simple, if we see an &lt;code&gt;m&lt;&#x2F;code&gt;, let’s check the two following characters and see if they are u and l! I don’t think this is a safe assumption to make all the time, but this design choice was selected in order to optimize developer implementation efficiency (it was 2 AM).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;m&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;u&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;l&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;        tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;MUL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Rust standard library has a &lt;code&gt;next_chunk&lt;&#x2F;code&gt; function in nightly, and when I was originally implementing this, I used many a &lt;code&gt;iter.peek()&lt;&#x2F;code&gt;, &lt;code&gt;is_some()&lt;&#x2F;code&gt;, &lt;code&gt;next_if_eq()&lt;&#x2F;code&gt;, and other nested gems. However, after &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vedthiru.com&quot;&gt;Ved&lt;&#x2F;a&gt; correctly pointed out that nothing was stopping me from writing my own wannabe replacement, I got to work. It’s quite simple (with a more complicated extension), and I’ll talk about them more towards the end.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;step-3-whatever-shall-we-do-with-this-token-stream-parse-it-kinda&quot;&gt;Step 3: Whatever shall we do with this token stream?? (parse it [kinda])&lt;&#x2F;h4&gt;
&lt;p&gt;The last major piece of the puzzle is as follows; now that we have our very cool token stream, how the hell do we make it useful? The fun way I thought of doing this was by using a sliding window over the tokens; since we know the structure of the &lt;code&gt;mul&lt;&#x2F;code&gt; operation quite well, we can just pass a window of the necessary size and check if it contains the necessary elements! For each slice, if there’s a match, we add the product of the values contained within, otherwise just add 0.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; sum:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;u32 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; tokens[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;windows&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;MUL&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;LPAREN&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(a),
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;COMMA&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;NUMBER&lt;&#x2F;span&gt;&lt;span&gt;(b),
&lt;&#x2F;span&gt;&lt;span&gt;            Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;RPAREN
&lt;&#x2F;span&gt;&lt;span&gt;        ] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; slice { 
&lt;&#x2F;span&gt;&lt;span&gt;        a &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; b
&lt;&#x2F;span&gt;&lt;span&gt;    } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;{sum}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This was quite fun to solve, and for all its flaws and overengineering, it was an enjoyable experience.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-2-to-multiply-or-not-to-multiply&quot;&gt;Part 2: To Multiply or Not to Multiply&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;it-s-a-toss-up-who-knows&quot;&gt;(it’s a toss-up, who knows)&lt;&#x2F;h4&gt;
&lt;h5 id=&quot;we-know-see-below&quot;&gt;(we know, see below)&lt;&#x2F;h5&gt;
&lt;p&gt;The second problem centers around &lt;code&gt;do()&lt;&#x2F;code&gt; and &lt;code&gt;don&#x27;t()&lt;&#x2F;code&gt; within a code fragment:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#282828;color:#fdf4c1aa;&quot;&gt;&lt;code&gt;&lt;span&gt;xmul(2,4)&amp;amp;mul[3,7]!^don&amp;#39;t()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When a &lt;code&gt;don&#x27;t()&lt;&#x2F;code&gt; is encountered, until a &lt;code&gt;do()&lt;&#x2F;code&gt; is encountered after, all multiplications in between are invalidated. In order to support this, we make 3 major additions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;DO&lt;&#x2F;code&gt; and &lt;code&gt;DONT&lt;&#x2F;code&gt; as variants to the &lt;code&gt;Token&lt;&#x2F;code&gt; enum&lt;&#x2F;li&gt;
&lt;li&gt;Add lexing support for &lt;code&gt;DO&lt;&#x2F;code&gt; and &lt;code&gt;DONT&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Find out a way to remove the correct &lt;code&gt;mul&lt;&#x2F;code&gt;s from consideration before using our sliding window technique&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;(1) is trivial, so let’s look at (2) just a bit closer.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;d&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; next &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;by_ref&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_if_eq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;o&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; next.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_some&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;        iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; next &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;by_ref&lt;&#x2F;span&gt;&lt;span&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_if_eq&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;n&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; next.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;is_some&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;\&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;t&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;                tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;DONT&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; rest &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;(&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b8bb26;&quot;&gt;&amp;#39;)&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] {
&lt;&#x2F;span&gt;&lt;span&gt;                tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;DO&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We add this to the &lt;code&gt;match&lt;&#x2F;code&gt; statement from before, and it follows the same principle as &lt;code&gt;mul&lt;&#x2F;code&gt;. If we see a d, then we check if we have an o. After that, we branch based on whether or not the next value is n or not, and Bob’s your uncle or something. Before we explain &lt;code&gt;next_chunk&lt;&#x2F;code&gt; (finally), let’s look at (3), which was also cool.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Goal: Remove all entries &amp;quot;between&amp;quot; a Token::DONT and a Token::DO
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; delete &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;tokens.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;retain&lt;&#x2F;span&gt;&lt;span&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;| {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span&gt; token {
&lt;&#x2F;span&gt;&lt;span&gt;        Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;DONT &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            delete &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;false &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; don&amp;#39;t want to retain
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; Check if we have encountered a DONT before
&lt;&#x2F;span&gt;&lt;span&gt;        Token::&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;DO &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; delete &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            delete &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;false &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; don&amp;#39;t want to retain
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;_ =&amp;gt; !&lt;&#x2F;span&gt;&lt;span&gt;delete, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; keep elts if not in delete mode
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I hadn’t really used &lt;code&gt;retain&lt;&#x2F;code&gt; before, but it’s conceptually quite simple; we pass in a function on an iterator, and it will retain all elements that return &lt;code&gt;true&lt;&#x2F;code&gt;.
The way this relates to our construction is as follows: if we hit a &lt;code&gt;DONT&lt;&#x2F;code&gt;, we want to begin deleting, and we also want to delete &lt;code&gt;DONT&lt;&#x2F;code&gt; so we return &lt;code&gt;false&lt;&#x2F;code&gt;. If we hit &lt;code&gt;DO&lt;&#x2F;code&gt;, we want to set delete to &lt;code&gt;false&lt;&#x2F;code&gt;, but we want to clear away the &lt;code&gt;DO&lt;&#x2F;code&gt; as well. For any other elements, keep them if not in &lt;code&gt;delete&lt;&#x2F;code&gt; mode. This action allows us to maintain the invariant of not having &lt;code&gt;DO&lt;&#x2F;code&gt; or &lt;code&gt;DONT&lt;&#x2F;code&gt; at sliding window matching time (see part 1 step 3).&lt;&#x2F;p&gt;
&lt;p&gt;I found this quite elegant, and the whole thing works as well.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;next-chunk-d&quot;&gt;&lt;code&gt;next_chunk&lt;&#x2F;code&gt; :D&lt;&#x2F;h3&gt;
&lt;p&gt;Now it’s finally time to showcase my darling boy; &lt;code&gt;next_chunk&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;I&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Peekable&amp;lt;I&amp;gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;num&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;I::&lt;&#x2F;span&gt;&lt;span&gt;Item&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; I: Iterator
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; chunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;::with_capacity(num);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;_ in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;num {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(item) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            chunk.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(item);
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;break
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    chunk
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Pretty self-explanatory, but the real kicker is when we try to use const generics and return something with type &lt;code&gt;[I::Item; N]&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8ec07c;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;I, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; N:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span&gt;Peekable&amp;lt;I&amp;gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;I::&lt;&#x2F;span&gt;&lt;span&gt;Item; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;where&lt;&#x2F;span&gt;&lt;span&gt; I: Iterator, &amp;lt;I&amp;gt;::Item: Copy,
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; SAFETY: We are initializing an N elt length array, using MaybeUninit
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; for now
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span&gt; chunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{ [MaybeUninit::uninit().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;assume_init&lt;&#x2F;span&gt;&lt;span&gt;();N] };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;N {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(item) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; iter.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span&gt;() {
&lt;&#x2F;span&gt;&lt;span&gt;            chunk[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;MaybeUninit::new(item);
&lt;&#x2F;span&gt;&lt;span&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; SAFETY: Convert uninit array to regular with transmute,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#928374;&quot;&gt;&#x2F;&#x2F; since they are the same size
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; chunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;unsafe &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;      std::mem::transmute_copy::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;I::&lt;&#x2F;span&gt;&lt;span&gt;Item;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdf4c1;&quot;&gt;N&lt;&#x2F;span&gt;&lt;span&gt;]&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;chunk) 
&lt;&#x2F;span&gt;&lt;span&gt;    };
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(chunk)
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This bad boy right here is a bit crazier, although after digesting it, it becomes much more manageable.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We use const generic &lt;code&gt;const N: usize&lt;&#x2F;code&gt; for our sizing, and return an array&lt;&#x2F;li&gt;
&lt;li&gt;Because we can’t initialize an empty array, we use &lt;code&gt;std::mem::MaybeUninit&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;We populate said array&lt;&#x2F;li&gt;
&lt;li&gt;We can now “safely” convert the array of &lt;code&gt;MaybeUninit&lt;&#x2F;code&gt;s to an array of &lt;code&gt;I::Item&lt;&#x2F;code&gt;s instead, with &lt;code&gt;std::mem::transmute&lt;&#x2F;code&gt; (see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;jack.wrenn.fyi&#x2F;blog&#x2F;safety-goggles-for-alchemists&#x2F;&quot;&gt;this article&lt;&#x2F;a&gt; for a great discussion on transmute)&lt;&#x2F;li&gt;
&lt;li&gt;We can rest easy knowing we can now call the function like&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;next_chunk::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;, some_num&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;instead of&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#282828;color:#fdf4c1aa;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#fabd2f;&quot;&gt;next_chunk&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fe8019;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fa5c4b;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; iter, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d3869b;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(&lt;strong&gt;nice work buddy, the array comparison is more space efficient than the vector equivalence check, at least :D&lt;&#x2F;strong&gt;)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;that-s-all-folks&quot;&gt;That’s all, folks!&lt;&#x2F;h3&gt;
&lt;p&gt;I hope you guys enjoyed my first real blog and this assault on the English language. Thanks for reading!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Other Blogs I like!</title>
        <published>2024-11-30T00:00:00+00:00</published>
        <updated>2024-11-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/other-blogs/"/>
        <id>https://abhamra.com/blog/other-blogs/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/other-blogs/">&lt;p&gt;I guess I can’t call this a brief detour from our regularly scheduled programming, since I have yet to establish what regularly scheduled programming looks like, but I wanted to have a blogpost that I update on occasion to store some of my favorite other blogs, and people who I know! This list will forever be incomplete.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;people-i-know&quot;&gt;People I know:&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.vedthiru.com&quot;&gt;Ved Thiru&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h3 id=&quot;blogs-i-like&quot;&gt;Blogs I Like:&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;matklad.github.io&#x2F;&quot;&gt;matklad&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.vedthiru.com&quot;&gt;Ved Thiru&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bernsteinbear.com&#x2F;&quot;&gt;Max Bernstein&lt;&#x2F;a&gt;, particularly his &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;bernsteinbear.com&#x2F;pl-resources&#x2F;&quot;&gt;PL Resources&lt;&#x2F;a&gt; page (and his great articles)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.scattered-thoughts.net&#x2F;&quot;&gt;Scattered Thoughts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why do we blog?</title>
        <published>2024-11-18T00:00:00+00:00</published>
        <updated>2024-11-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Arjun Bhamra
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://abhamra.com/blog/why-blog/"/>
        <id>https://abhamra.com/blog/why-blog/</id>
        
        <content type="html" xml:base="https://abhamra.com/blog/why-blog/">&lt;p&gt;&lt;em&gt;Word Count: 279&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As my first actual blog post, I feel like it’s fitting to discuss why I want to write a blog at all, as well as some expectations for content going forward (if I ever get around to it, that is). I think what initially inspired me was joining GT’s programming languages and compilers club, dependently-typed. The first few talks I attended were fascinating, and the club chairs pointed me to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&quot;&gt;lobste.rs&lt;&#x2F;a&gt; as a great resource for tech blogs. Through that, I’ve spent much more time reading and learning about some of my favorite technical topics! I’ve since had the motivation to begin organizing my learning about some of these topics, particularly ones that I believe I’m either not well versed in, or those that I would like to master.&lt;&#x2F;p&gt;
&lt;p&gt;The core idea here is that starting off, my blog is for me. It will be a place for me to document my journey through programming language theory, language design and implementation, and quantum computing. As I begin to get more and more confident, it may yet become a place for me to broaden my horizons or, perhaps, try my hand at teaching&#x2F;explaining things. Time and time again, I’ve found myself collating several sources into a patchwork of knowledge in my mind, and this amalgamation of unique perspectives makes my understanding deeper; it would be awesome to one day see some of my work help another in a similar vein.&lt;&#x2F;p&gt;
&lt;p&gt;That’s basically it for this blog (article?) I think. For future posts, I have no real expectation of min&#x2F;max length, and I may also intersperse the technical talk with some more personal drabbles as well.&lt;&#x2F;p&gt;
&lt;p&gt;I hope you enjoyed,&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Arjun&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
</feed>
