Jekyll2023-05-17T11:12:32+00:00https://www.mourtada.se/feed.xmlMourtada.seI'm a developer. I love coding.Cherry-pick a range of commits with git2023-05-17T00:00:00+00:002023-05-17T00:00:00+00:00https://www.mourtada.se/cherry-pick-range-of-commits-with-git<p>When working in a feature branch I often find code that needs fixing or refactoring which I would like to keep regardless of the outcome of the feature I’am working on. So I make my changes in atomic commits then I use git rebase interative to put the commits first in the feature branch I’m on. The reason for that is so that I can see that the changes apply cleanly without my other changes in my branch.</p>
<p>When I have collected a bunch of these commits I either cherry-pick them directly in to the main branch or another feature branch. Because I put all the commits in the beginning and in line I can cherry-pick a range of commits. To do this use</p>
<p><code class="language-plaintext highlighter-rouge">git cherry-pick <the_first_commit>^..<the_last_commit></code></p>
<p>Notice the <code class="language-plaintext highlighter-rouge">^</code> which will make the <code class="language-plaintext highlighter-rouge">the_first_commit</code> point to the parent commit. The effect of <code class="language-plaintext highlighter-rouge"><the_first_commit>^</code> will be that the changes of <code class="language-plaintext highlighter-rouge">the_first_commit</code> is included, otherwise it will only include the child of that commit.</p>When working in a feature branch I often find code that needs fixing or refactoring which I would like to keep regardless of the outcome of the feature I’am working on. So I make my changes in atomic commits then I use git rebase interative to put the commits first in the feature branch I’m on. The reason for that is so that I can see that the changes apply cleanly without my other changes in my branch.Run command for every commit in your git branch2023-04-22T00:00:00+00:002023-04-22T00:00:00+00:00https://www.mourtada.se/run-command-for-every-commit-in-your-git-branch<p>When working on a branch and your are rewriting your history often it’s easy to come to a state when a commit doesn’t compile. It’s not obvious because your latest commit does compile. But it’s good hygiene for your application to compile at every commit. Fortunately an interative rebase can help you with this:</p>
<p>For example: <code class="language-plaintext highlighter-rouge">git rebase -i master --exec "clear && yarn build"</code> will run the command specified for each commit since master. In this example I have script in my <code class="language-plaintext highlighter-rouge">package.json</code> which builds the application. If the build fails git rebase will stop and ask me to fix the error and do a <code class="language-plaintext highlighter-rouge">git rebase --continue</code>.</p>When working on a branch and your are rewriting your history often it’s easy to come to a state when a commit doesn’t compile. It’s not obvious because your latest commit does compile. But it’s good hygiene for your application to compile at every commit. Fortunately an interative rebase can help you with this:Making atomic commits2023-03-24T00:00:00+00:002023-03-24T00:00:00+00:00https://www.mourtada.se/making-atomic-commits<h2 id="what-is-an-atomic-commit">What is an atomic commit</h2>
<p>An atomic commit about is about a single, small focused change. Other names for atomic commits are small commits, focused commits, self contained commits or deliberate commits. If you’re trying to figure out if the commit you’re working on is to big, it probably is.</p>
<h2 id="why-atomic-commits">Why atomic commits</h2>
<h3 id="1-helps-plan-your-work">1. Helps plan your work</h3>
<p>With atomic commits you are forced to split up your large task into smaller pieces. This is helpful because you’ll have to think in detail about what you’re going to do. This will help with cognitive load and you wont be afraid about getting interrupted and forget your current state. Small commits also helps with the feeling of making progress.</p>
<h3 id="2-easier-to-review">2. Easier to review</h3>
<p>Atomic commits is a win both for you and the reviewer. Going through a code review with atomic commits is much easier. Each commit is about a single change and all small commits together tells a story. When every change is small and focused it’s easier to explain your change with a good commit message. For the reviewer each small commit can be handled one at a time making it easier to find bugs, typos and things to improve.</p>
<h3 id="3-easy-to-revert-cherry-pick-and-drop">3. Easy to revert, cherry-pick and drop</h3>
<p>A small commit is simple to revert or drop because it just one small focused change. If you find something to refactor that is not related to the task your working on it should be cherry-picked to another branch. When rebasing your branch again git will automatically see the change already applied and remove it from your branch.</p>
<h3 id="4-easier-merge-conflicts">4. Easier merge conflicts</h3>
<p>When handling merge conflicts small commits will be a lot simpler.</p>
<h3 id="5-good-for-debugging-with-git-bisect">5. Good for debugging with git bisect</h3>
<p>Using <code class="language-plaintext highlighter-rouge">git bisect</code> it will help you to find the specific change which introduced a bug. If the commit is small the change introduced will be easy to spot.</p>
<h3 id="6-good-documentation">6. Good documentation</h3>
<p>Small focused commits are great for documentation. They explain the what, the why and at the time the change was made. Its’ documnetation that doesn’t lie.</p>
<h2 id="useful-tools">Useful tools</h2>
<h3 id="interactive-rebase">Interactive rebase</h3>
<p>Use <code class="language-plaintext highlighter-rouge">git rebase --interactive</code> early and often to revise your history and get the latest changes from upstream branches.</p>
<h3 id="amend">Amend</h3>
<p><code class="language-plaintext highlighter-rouge">git commit --amend</code> for quickly fixing up the latest commit with extra files or change the commit message.</p>
<h3 id="partially-stage-files">Partially stage files</h3>
<p>If multiple changes is made to a file which should be in separate commits use <code class="language-plaintext highlighter-rouge">git add --patch</code> which will let you add specific lines from a file.</p>
<h3 id="commit-verbose">Commit verbose</h3>
<p>When writing the commit message it’s useful to see the changes directly in the editor. This can be done with <code class="language-plaintext highlighter-rouge">git commit --verbose</code> or setting it as a default value with <code class="language-plaintext highlighter-rouge">git config --global commit.verbose true</code>.</p>
<h2 id="good-reading-materials">Good reading materials</h2>
<ul>
<li><a href="https://www.aleksandrhovhannisyan.com/blog/atomic-git-commits">Make Atomic Git Commits</a></li>
<li><a href="https://tekin.co.uk/2021/01/how-atomic-commits-make-you-a-better-coder">How focused commits make you a better coder</a></li>
<li><a href="https://tekin.co.uk/2019/02/a-talk-about-revision-histories">A Branch in Time (a story about revision histories)</a></li>
<li><a href="https://www.youtube.com/watch?v=mE8DZUfhdm4">Simplify writing code with deliberate commits</a></li>
</ul>What is an atomic commit An atomic commit about is about a single, small focused change. Other names for atomic commits are small commits, focused commits, self contained commits or deliberate commits. If you’re trying to figure out if the commit you’re working on is to big, it probably is.Writing good commit messages2023-03-19T00:00:00+00:002023-03-19T00:00:00+00:00https://www.mourtada.se/writing-good-commit-messages<h2 id="why-doesnt-everyone-write-good-commit-messages">Why doesn’t everyone write good commit messages</h2>
<p>This is what I think:</p>
<ul>
<li>Lack of motivation</li>
<li>Lack of time</li>
<li>The organization or coworkers doesn’t value good git history hygiene</li>
<li>Never learned to do it</li>
<li>Doesn’t see the value</li>
</ul>
<h2 id="writing-good-commit-messages-is-important">Writing good commit messages is important</h2>
<ul>
<li>It forces you to really think about and understand your change which makes you a better developer</li>
<li>It makes reviewing your code easier which improves the quality of the code</li>
<li>It spreads knowledge. Someone may never know as much about this change that you do right now</li>
<li>It is documentation that doesn’t lie. A good investment for the future</li>
<li>It makes your git history easier to search with <code class="language-plaintext highlighter-rouge">git log --grep</code> and <code class="language-plaintext highlighter-rouge">git log -S</code></li>
<li>It makes it easier to automatically generate a changelog</li>
<li>It can save tremendous amount of time for anyone trying to understand a piece of code</li>
</ul>
<h2 id="what-should-a-commit-message-look-like">What should a commit message look like</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># (50-character subject line)
#
# 72-character wrapped longer description. This should answer:
#
# * Why was this change necessary?
# * How does it address the problem?
# * Were there any alternative solutions that you thought about?
</code></pre></div></div>
<h2 id="tips-for-writing-a-good-commit-message">Tips for writing a good commit message</h2>
<ul>
<li>When writing the subject line say “If applied, this commit will…”. This will help you get the correct grammatical mood which forms a command or a request</li>
<li>Don’t use <code class="language-plaintext highlighter-rouge">git commit -m</code> as it don’t let you write more than one line. Without specifying <code class="language-plaintext highlighter-rouge">-m</code> git will open your text editor of choice for writing the message</li>
<li>Use a helpful commit message template <code class="language-plaintext highlighter-rouge">git config --global commit.template ~/.gitmessage</code>. Like the one above.</li>
<li>Use <code class="language-plaintext highlighter-rouge">git config --global commit.verbose true</code> option. It lets you see the diff which will help you when writing your commit message.</li>
<li>Think about the developers in your team. What questions would they have and try to answer them</li>
<li>If your commit is a bugfix write about the bug, when it happens and why.</li>
<li>If it’s a feature write about the process of implementing it</li>
<li>If it’s a refactor. Write why it improves code</li>
</ul>
<h2 id="good-reading-materials">Good reading materials</h2>
<ul>
<li><a href="https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html">A Note About Git Commit Messages</a></li>
<li><a href="https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message">5 Useful Tips For A Better Commit Message</a></li>
<li><a href="https://cbea.ms/git-commit/">How to Write a Git Commit Message</a></li>
<li><a href="https://git-scm.com/book/en/v2">Pro Git</a></li>
</ul>Why doesn’t everyone write good commit messagesSQL server statistics2023-02-26T00:00:00+00:002023-02-26T00:00:00+00:00https://www.mourtada.se/sql-server-statistics<p>The query optimizer in SQL server uses statistics to improve query performance. Statistics are large BLOBs containing statistical information about the distribution of values in one or more columns of a table or indexed view. This is done using a histogram which measures the frequency of distinct values in a data set. Statistics is based on a sample of the rows or by doing a full scan of all the rows. The query optimizer uses statistics to estimate the cardinality(number of rows) in the query result to find the optimal query plan.</p>
<p>To enhance cardinality estimates the query optimizer uses densities for queries that return multiple columns from the same table or index view. Density gives information about the number of duplicates in a given column and is calculated as <code class="language-plaintext highlighter-rouge">1/number of distinct values</code>. Lower density means more unique values.</p>
<p>Statistics is auto updated when <code class="language-plaintext highlighter-rouge">AUTO_UPDATE_STATISTICS</code> is on. If you want to update statistics more frequently than the automatic thresholds you can do so with the <code class="language-plaintext highlighter-rouge">UPDATE STATISTICS</code> statement or the stored procedure <code class="language-plaintext highlighter-rouge">sp_updatestats</code>. Updating statistics may cause query plans to recompile therefore it’s not recommended to update statistics too frequently.</p>
<p>The query optimizer automatically create statistics on the key column for index on tables or views when the index is created. When <code class="language-plaintext highlighter-rouge">AUTO_CREATE_STATISTICS</code> is on the query optimizer automatically creates statistics for single columns in query predicates.</p>
<p>In some cases you may want to create your own statistics object.</p>
<ul>
<li>The query predicates contains multiple correlated columns that are not in the same index</li>
<li>The query selects from a subset of data</li>
</ul>
<p>Creating a statistics object manually is done with the <code class="language-plaintext highlighter-rouge">CREATE STATISTICS</code> statement.</p>
<p><code class="language-plaintext highlighter-rouge">DBCC SHOW_STATISTICS</code> is useful for displaying the header, histogram and density vector for a statistics object. The header contains info about when the statistics was last updated, how many rows the table had when it was last updated and how many rows that was sampled. It also shows detailed information about the histogram which can be used to compare against actual query plans.</p>The query optimizer in SQL server uses statistics to improve query performance. Statistics are large BLOBs containing statistical information about the distribution of values in one or more columns of a table or indexed view. This is done using a histogram which measures the frequency of distinct values in a data set. Statistics is based on a sample of the rows or by doing a full scan of all the rows. The query optimizer uses statistics to estimate the cardinality(number of rows) in the query result to find the optimal query plan.SQL server bacpac export is not transactionally consistent2023-02-18T00:00:00+00:002023-02-18T00:00:00+00:00https://www.mourtada.se/sql-server-bacpac-export-is-not-transactionally-consistent<p>The other day I needed a copy of a production database which was running in Azure SQL. The only simple way to export data from Azure SQL is through a bacpac export. Azure manages the ordinary backups and they cannot be accessed for download. The can only be restored within Azure.</p>
<p>I exported the backup with Azure cli <code class="language-plaintext highlighter-rouge">az sql db export</code> command and exported directly to Azure blob storage. Everything went fine and I could then download the export to my local computer where I was running the SQL server as container on linux.</p>
<p>But when restoring the bacpac file with SQL server management studio the import operation never completed. It got stuck on of the biggest tables in the database when creating the clustered index which was also the primary key. Nothing was shown in the UI. I then tried using the <code class="language-plaintext highlighter-rouge">sqlpackage</code> command line tool which was kind to tell me that there was a duplicate key that was preventing the creation of the index. But it didn’t fail it just tried again…and again…and again.</p>
<p>This seemed very strange. After a short search on the web I realized that bacpac exports are not transactionally consistent. It is very easy to find this if you read the documentation https://learn.microsoft.com/en-us/azure/azure-sql/database/database-export?view=azuresql.</p>
<p>So I made a copy of the database in Azure SQL and exported that one instead. Now the bacpac file imported without problems!</p>The other day I needed a copy of a production database which was running in Azure SQL. The only simple way to export data from Azure SQL is through a bacpac export. Azure manages the ordinary backups and they cannot be accessed for download. The can only be restored within Azure.Tee (command)2023-01-29T00:00:00+00:002023-01-29T00:00:00+00:00https://www.mourtada.se/tee<p>Tee is a command which reads standard input and writes it both to standard output and one or more files. It is named after the T-splitter used in plumbing. The command is available on most popular operating systems.</p>
<h2 id="example-usages">Example usages</h2>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Displays and writes the output to file.txt</span>
<span class="nb">ls</span> <span class="nt">-lah</span> |tee file.txt
<span class="c"># Displays and appends the output to file.txt</span>
<span class="nb">ls</span> <span class="nt">-lah</span> |tee <span class="nt">-a</span> file.txt
<span class="c"># Displays and writes the output to file1.txt and file2.txt</span>
<span class="nb">ls</span> <span class="nt">-lah</span> |tee file1.txt file2.txt
<span class="c"># tee supports process substitution.</span>
<span class="c"># Displays and writes the output to file.txt and the md5sum to md5.txt</span>
<span class="nb">ls</span> <span class="nt">-lah</span> | <span class="nb">tee </span>file.txt <span class="o">>(</span><span class="nb">md5sum</span> <span class="o">></span> md5.txt<span class="o">)</span>
</code></pre></div></div>
<h2 id="using-tee-with-vim">Using tee with vim</h2>
<p>If you opened a protected file with <code class="language-plaintext highlighter-rouge">vim</code> and your current user is missing permissions to write to the file you could use <code class="language-plaintext highlighter-rouge">:w !sudo tee %</code>. This will write the file as super user. In this case <code class="language-plaintext highlighter-rouge">%</code> is replaced with the name of the current file. The <code class="language-plaintext highlighter-rouge">!</code> means that what comes after is a command which will get the current buffer via standard input.</p>Tee is a command which reads standard input and writes it both to standard output and one or more files. It is named after the T-splitter used in plumbing. The command is available on most popular operating systems.Merge sort2023-01-18T00:00:00+00:002023-01-18T00:00:00+00:00https://www.mourtada.se/merge-sort<p>Merge sort is a divide-and-conquer algorithm. It’s an effecient general-purpose and comparison-based sorting algorithm. The average and worst-case performance is O(n logn).</p>
<p>It works by dividing the unsorted list into <code class="language-plaintext highlighter-rouge">n</code> sublists. When there is only element in the list that list is considered sorted. Sublists are then merged to produce new sorted sublists. When there is only one sublist left the list is sorted.</p>
<p>Merge sort can be implemented with an Top-down or a bottom-up algorithm. Here is a top-down implementation in typescript.</p>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>
<span class="kd">const</span> <span class="nx">sorted</span> <span class="o">=</span> <span class="nx">sort</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">sorted</span><span class="p">));</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">sort</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nx">ReadonlyArray</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">):</span> <span class="nx">ReadonlyArray</span><span class="o"><</span><span class="kr">number</span><span class="o">></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">concat</span><span class="p">());</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">):</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">arr</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">mid</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">/</span> <span class="mi">2</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">left</span> <span class="o">=</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">mid</span><span class="p">));</span>
<span class="kd">const</span> <span class="nx">right</span> <span class="o">=</span> <span class="nx">mergeSort</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">mid</span><span class="p">));</span>
<span class="k">return</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">left</span><span class="p">,</span> <span class="nx">right</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">merge</span><span class="p">(</span><span class="nx">left</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">,</span> <span class="nx">right</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">):</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span> <span class="p">{</span>
<span class="kd">const</span> <span class="na">result</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">left</span><span class="p">.</span><span class="nx">length</span> <span class="o">||</span> <span class="nx">right</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">left</span><span class="p">.</span><span class="nx">length</span> <span class="o">&&</span> <span class="nx">right</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">left</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o"><</span> <span class="nx">right</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">left</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">right</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">left</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">left</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">right</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>Merge sort is a divide-and-conquer algorithm. It’s an effecient general-purpose and comparison-based sorting algorithm. The average and worst-case performance is O(n logn).All blog posts of 20222022-12-30T00:00:00+00:002022-12-30T00:00:00+00:00https://www.mourtada.se/all-blog-posts-of-2022<p>2022 has been a good blogging year for me. I kept at it and made at least two blog posts each month. This post contains a list of all the posts from 2022. Let’s continue with the same amount in 2023. Happy new year!</p>
<ul>
<li><a href="/most-popular-posts-of-2021/">Most popular posts of 2021</a></li>
<li><a href="/what-is-opentelemetry/">What is OpenTelemetry?</a></li>
<li><a href="/the-opentelemetry-collector/">The OpenTelemetry collector</a></li>
<li><a href="/how-to-deploy-an-aks-cluster-in-azure/">How to deploy an aks cluster in azure</a></li>
<li><a href="/add-an-azure-static-disk-with-azure-disk-csi-driver-in-kubernetes/">Add an Azure static disk with Azure disk CSI driver in Kubernetes</a></li>
<li><a href="/how-to-setup-opentelemetry-instrumentation-in-aspnet-core/">How to setup OpenTelemetry instrumentation in ASP.NET core</a></li>
<li><a href="/create-a-simple-azure-function/">Create a simple azure function</a></li>
<li><a href="/opentelemetry-tracing-with-nodejs-and-express/">OpenTelemetry tracing with nodejs and express</a></li>
<li><a href="/how-to-get-wsl2-working-inside-a-hyper-v-virtual-machine/">How to get WSL2 working inside a Hyper-V virtual machine</a></li>
<li><a href="/installing-multiple-instances-of-ubuntu-in-wsl2/">Installing multiple instances of Ubuntu in WSL2</a></li>
<li><a href="/checking-kubernetes-api-access-with-kubectl/">Checking Kubernetes API access with kubectl</a></li>
<li><a href="/nice-grpc-client-and-ts-proto-with-typescript-and-nodejs/">nice-grpc client and ts-proto with typescript and nodejs</a></li>
<li><a href="/setup-grpc-ingress-with-nginx/">Setup gRPC ingress with nginx</a></li>
<li><a href="/dotnet-memory-generations/">Dotnet memory generations</a></li>
<li><a href="/incorrect-wsl2-date-after-sleep/">Incorrect date in WSL2 after waking up from sleep</a></li>
<li><a href="/maven-basics/">Maven basics</a></li>
<li><a href="/azure-blob-storage-tiers/">Azure blob storage tiers</a></li>
<li><a href="/using-dotnet-dump/">Using dotnet-dump</a></li>
<li><a href="/list-failed-kubernetes-jobs/">List failed kubernetes jobs</a></li>
<li><a href="/what-is-big-o-notation/">What is Big O notation</a></li>
<li><a href="/connect-to-a-kubernetes-linux-node-with-kubectl-debug/">Connect to a kubernetes linux node with kubectl debug</a></li>
<li><a href="/push-a-commit-without-triggering-a-pipeline-in-gitlab/">Push a commit without triggering a pipeline in gitlab</a></li>
<li><a href="/restarting-multiple-deployments-in-kubernetes/">Restarting multiple deployments in kubernetes</a></li>
<li><a href="/configure-a-wireless connection-on-raspbian/">Configure a wireless connection on raspbian</a></li>
<li><a href="/postscript/">PostScript</a></li>
<li><a href="/common-unix-printing-system/">Common Unix Printing System(CUPS)</a></li>
<li><a href="/containerd-fails-to-start-on-windows/">“containerd fails to start on windows with failed to recover state: failed to reserve sandbox name”</a></li>
<li><a href="/dotnet-7-sdk/builtin-container-support/">.NET 7 SDK builtin container support</a></li>
<li><a href="/dotnet-generic-host-and-app-configuration/">.NET Generic host configuration</a></li>
<li><a href="/using-ephemeral-disks-in-azure-aks/">Using ephemeral disks in Azure AKS</a></li>
<li><a href="/kubernetes-server-side-apply/">Kubernetes server-side apply</a></li>
<li><a href="/bubble-sort/">Bubble sort</a></li>
<li><a href="/quick-sort/">Quick sort</a></li>
</ul>2022 has been a good blogging year for me. I kept at it and made at least two blog posts each month. This post contains a list of all the posts from 2022. Let’s continue with the same amount in 2023. Happy new year!Quick sort2022-12-28T00:00:00+00:002022-12-28T00:00:00+00:00https://www.mourtada.se/quick-sort<p>Quick sort is an efficient divide-and-conquer algorithm(breaks the problem into sub-problems until they become simple enough to be solved) which is sometimes also called partition-exchange sort.</p>
<p>The Quick sort algorithm works by taking a pivot which divides the list in to two sub list and repeats this process recursively. Any element can be the pivot but the simplest implementation is to take the last element of the list. Taking the last element is slower for already sorted lists O(n<sup>2</sup>). Best case is O(n logn).</p>
<p>An implementation in typescript</p>
<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="mi">10</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">3</span><span class="p">];</span>
<span class="nx">sort</span><span class="p">(</span><span class="nx">arr</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">arr</span><span class="p">));</span>
<span class="k">export</span> <span class="kd">function</span> <span class="nx">sort</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
<span class="nx">quicksort</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">arr</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">quicksort</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">,</span> <span class="nx">low</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span> <span class="nx">high</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
<span class="c1">// We're at the bottom (only one element). Do nothing</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">low</span> <span class="o">>=</span> <span class="nx">high</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">const</span> <span class="nx">pIndex</span> <span class="o">=</span> <span class="nx">partition</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">low</span><span class="p">,</span> <span class="nx">high</span><span class="p">);</span>
<span class="c1">// We now have the index of the pivot. Sort</span>
<span class="c1">// the left and the right elements of the pivot.</span>
<span class="nx">quicksort</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">low</span><span class="p">,</span> <span class="nx">pIndex</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="nx">quicksort</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">pIndex</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">high</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">partition</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">,</span> <span class="nx">low</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span> <span class="nx">high</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="kr">number</span> <span class="p">{</span>
<span class="c1">// In this implementation we have chosen</span>
<span class="c1">// the last element in the slice as the pivot.</span>
<span class="kd">const</span> <span class="nx">pivot</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">high</span><span class="p">];</span>
<span class="kd">let</span> <span class="nx">pIndex</span> <span class="o">=</span> <span class="nx">low</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">// Loop through all elements in the current slice</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">j</span> <span class="o">=</span> <span class="nx">low</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><=</span> <span class="nx">high</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// If the element is less than the pivot we know</span>
<span class="c1">// that it should go left of the pivot. Therefore</span>
<span class="c1">// we increase the partionIndex because we know that the</span>
<span class="c1">// current element comes before the pivot. We then swap the element</span>
<span class="c1">// at pIndex with the current element at j.</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">arr</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o"><=</span> <span class="nx">pivot</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">pIndex</span><span class="o">++</span><span class="p">;</span>
<span class="nx">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">pIndex</span><span class="p">,</span> <span class="nx">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// We have now found all elements less than</span>
<span class="c1">// the pivot and placed them first in this slice.</span>
<span class="c1">// The last thing that is needed is to</span>
<span class="c1">// place the pivot at the right place(pIndex + 1) and return the pIndex</span>
<span class="c1">// so the next subtrees can do their thing.</span>
<span class="nx">pIndex</span><span class="o">++</span><span class="p">;</span>
<span class="nx">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">,</span> <span class="nx">pIndex</span><span class="p">,</span> <span class="nx">high</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">pIndex</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">swap</span><span class="p">(</span><span class="nx">arr</span><span class="p">:</span> <span class="nb">Array</span><span class="o"><</span><span class="kr">number</span><span class="o">></span><span class="p">,</span> <span class="nx">i1</span><span class="p">:</span> <span class="kr">number</span><span class="p">,</span> <span class="nx">i2</span><span class="p">:</span> <span class="kr">number</span><span class="p">):</span> <span class="k">void</span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">i1</span><span class="p">];</span>
<span class="nx">arr</span><span class="p">[</span><span class="nx">i1</span><span class="p">]</span> <span class="o">=</span> <span class="nx">arr</span><span class="p">[</span><span class="nx">i2</span><span class="p">];</span>
<span class="nx">arr</span><span class="p">[</span><span class="nx">i2</span><span class="p">]</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>Quick sort is an efficient divide-and-conquer algorithm(breaks the problem into sub-problems until they become simple enough to be solved) which is sometimes also called partition-exchange sort.