<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mark Robert Henderson</title>
    <description>The latest articles on DEV Community by Mark Robert Henderson (@aphelionz).</description>
    <link>https://dev.to/aphelionz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1126371%2F263be77b-00df-4c50-ae18-397117160938.jpeg</url>
      <title>DEV Community: Mark Robert Henderson</title>
      <link>https://dev.to/aphelionz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aphelionz"/>
    <language>en</language>
    <item>
      <title>EXPOSED: The Leetcode C++ Cheat Code!!</title>
      <dc:creator>Mark Robert Henderson</dc:creator>
      <pubDate>Sun, 27 Aug 2023 18:13:45 +0000</pubDate>
      <link>https://dev.to/aphelionz/exposed-the-leetcode-c-cheat-code-4mfa</link>
      <guid>https://dev.to/aphelionz/exposed-the-leetcode-c-cheat-code-4mfa</guid>
      <description>&lt;p&gt;Here's a fun story about stdin, stdout, and how Leetcode users use C++'s dark power to game the system a bit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strange Things are Afoot at the Circle K
&lt;/h2&gt;

&lt;p&gt;A few days ago, I was minding my own business going through the &lt;a href="https://leetcode.com/studyplan/binary-search/" rel="noopener noreferrer"&gt;binary search study plan&lt;/a&gt; on Leetcode.&lt;/p&gt;

&lt;p&gt;I worked on my C++ submission, optimized it at the &lt;a href="https://godbolt.org" rel="noopener noreferrer"&gt;Compiler Explorer&lt;/a&gt;, and submitted it only to find that while my solution beat over 90% of others in terms of execution time, it only beat 15% of people in terms of memory usage.&lt;/p&gt;

&lt;p&gt;When checking the solutions that beat mine, I first saw this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjxy6c48ci0hiyod2de7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjxy6c48ci0hiyod2de7.png" alt="A graph showing other solutions beating mine in memory consumption by over 2x"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your placement in the rankings isn't normally a huge deal - especially in simpler challenges - due to fluctuations in Leetcode's runtime. Sometimes it uses 26.5MB or memory, and sometimes it takes 26.6. Your placement in the rankings is somewhat randomized due to this.&lt;/p&gt;

&lt;p&gt;But the difference in this graph is astounding. 26.7MB down to 5.9! That's somehow a &lt;strong&gt;77.1% reduction in RAM usage on a simple binary search&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;What is going on?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cheat Code
&lt;/h2&gt;

&lt;p&gt;Clicking into each of those &amp;lt; 10MB solutions above all revealed the same thing. The following code was written (likely pasted in), &lt;em&gt;above&lt;/em&gt; the actual submissions! &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

int init=[] {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  ofstream out("user.out");
  cout.rdbuf(out.rdbuf());

  for(string s; getline(cin,s); cout &amp;lt;&amp;lt; '\n'){
    string t;
    getline(cin,t);
    int tar = stoi(t);

    for(int i = 0, _i = 1, _n = s.length(); _i&amp;lt;_n; ++I, ++_i){
      bool _neg = false;
      if(s[_i]=='-')++_i, _neg = true;
      int v = s[_i++]&amp;amp;15;
      while((s[_i]&amp;amp;15)&amp;lt;10)v = v*10 + (s[_i++]&amp;amp;15);

      if(_neg)v= -v;
      if(v == tar){
        cout &amp;lt;&amp;lt; i;
        goto next;
      }

      if(v &amp;gt; tar)break;
    }

    cout &amp;lt;&amp;lt; -1;
    next:;
  }

  exit(0);
  return 0;
}();


&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;So what the heck is going on with this code? I had to figure it out myself, so let me try and explain it to you.&lt;/p&gt;
&lt;h3&gt;
  
  
  IIFE Syntax
&lt;/h3&gt;

&lt;p&gt;The first thing to note is that this code is an Immediately Invoked Function Expression or an IIFE. This means this function is executed (or invoked) &lt;em&gt;immediately after&lt;/em&gt; it's defined. &lt;/p&gt;

&lt;p&gt;In C++, the syntax is something like &lt;code&gt;[]{/* function stuff */}();&lt;/code&gt; You might recognize its counterpart from JavaScript: &lt;code&gt;(() =&amp;gt; {})()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Why assign it to &lt;code&gt;init&lt;/code&gt;? Long story short: so it will compile.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;ios_base::sync_with_stdio(false);&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;By default, the input and output streams in C++ are synchronized with those of its predecessor, C. The theory is not so important for this explanation, because in practice what this means is you're doing duplicate work. This line of code turns this synchronization off.&lt;/p&gt;

&lt;p&gt;Note that in this case the &lt;code&gt;ios&lt;/code&gt; is "inputs and outputs" and not "iOS". &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;cin.tie(nullptr);&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Similarly, C++'s own &lt;code&gt;cin&lt;/code&gt; and &lt;code&gt;cout&lt;/code&gt; streams are "tied" together in that flushing one will also flush the other. This disables that again preventing extra work.&lt;/p&gt;
&lt;h3&gt;
  
  
  Redirecting to &lt;code&gt;user.out&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The next two lines:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ofstream out("user.out");
cout.rdbuf(out.rdbuf());


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, we redirect &lt;code&gt;cout&lt;/code&gt; to a file called &lt;code&gt;user.out&lt;/code&gt;, removing the time requirement of actually displaying anything on the console.&lt;/p&gt;

&lt;h3&gt;
  
  
  The nested &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; loops
&lt;/h3&gt;

&lt;p&gt;This is the part that took me the longest to figure out - not only in terms of &lt;em&gt;what&lt;/em&gt; the code does, but &lt;em&gt;why&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What:&lt;/strong&gt; In simple terms this part of the code reads in two lines of text, converts the second to an integer, and then returns the index of the first string that matches that integer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Since all the I/O synchronization and features are turned off above, the code within these loops is responsible for the actual processing of text. &lt;/p&gt;

&lt;p&gt;I will admit that figuring out the bit shifting and integer casting of &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; is outside of my time box for writing this post, but if YOU know - explain it in the comments!&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>leetcode</category>
      <category>stdio</category>
      <category>hacks</category>
    </item>
    <item>
      <title>Neovim Config: from init.vim to init.lua</title>
      <dc:creator>Mark Robert Henderson</dc:creator>
      <pubDate>Tue, 22 Aug 2023 03:32:30 +0000</pubDate>
      <link>https://dev.to/aphelionz/neovim-config-from-initvim-to-initlua-53n4</link>
      <guid>https://dev.to/aphelionz/neovim-config-from-initvim-to-initlua-53n4</guid>
      <description>&lt;p&gt;It's 9:30PM, I'm on vacation, and I drank an energy drink an hour ago. It's time to shave some yaks as hard as possible.&lt;/p&gt;

&lt;p&gt;Of course I'm talking about my Neovim configuration file, and migrating it from the Vimscript-based &lt;code&gt;init.vim&lt;/code&gt; to a Lua-based &lt;code&gt;init.lua&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you do this to yourself?
&lt;/h2&gt;

&lt;p&gt;A few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;init.lua&lt;/code&gt; is backwards compatible with &lt;code&gt;init.vim&lt;/code&gt;, but not the other way around&lt;/li&gt;
&lt;li&gt;Lua has applications outside of Vim, and this is a good excuse to familiarize myself with Lua more.&lt;/li&gt;
&lt;li&gt;I haven't done any benchmarking whatsoever, but Lua is probably faster than Vimscript, right? I mean, Lua is pretty fast...&lt;/li&gt;
&lt;li&gt;I wanted to try some Lua-based plugins like NvimTree&lt;/li&gt;
&lt;li&gt;Oh, do &lt;em&gt;you&lt;/em&gt; know Vimscript? Yeah, didn't think so.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API docs for the Lua + Neovim are here: &lt;a href="https://neovim.io/doc/user/api.html"&gt;https://neovim.io/doc/user/api.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Migration Strategy
&lt;/h2&gt;

&lt;p&gt;My overall strategy was pretty simple: first wrap everything in &lt;code&gt;vim.cmd([[ ... ]])&lt;/code&gt; and then pluck things out individually as candidates for conversion to Lua.&lt;/p&gt;

&lt;p&gt;The code that follows exemplifies this process, and highlights certain categories of settings and what the Lua code looked like in the end.&lt;/p&gt;

&lt;h3&gt;
  
  
  vim.cmd
&lt;/h3&gt;

&lt;p&gt;Vim's Lua APIs provide a convenience function &lt;code&gt;vim.cmd&lt;/code&gt; that takes a string literal as its only argument. Anything in that string is evaluated as Vimscript. Kind of scary, but since we're controlling what goes into it it becomes extremely convenient for our migration.&lt;/p&gt;

&lt;p&gt;Just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cmd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;[[
    " the contents of your existing init.vim
]]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you're off to the races... but where's the fun in that? Where's the Lua?&lt;/p&gt;

&lt;h3&gt;
  
  
  Settings and Options
&lt;/h3&gt;

&lt;p&gt;The first low-hanging fruit is your Vimscript &lt;code&gt;set&lt;/code&gt; directives like &lt;code&gt;set wrap&lt;/code&gt;. You have three options here and it can be a little confusing as to which options live where. I hate to sound like one of those vim people, but &lt;code&gt;:help&lt;/code&gt; is really good here.&lt;/p&gt;

&lt;h4&gt;
  
  
  vim.g
&lt;/h4&gt;

&lt;p&gt;This is for global commands, basically anything in the &lt;code&gt;let g:***&lt;/code&gt; Vimscript namespace. For example, &lt;code&gt;let g:mapleader = " "&lt;/code&gt; becomes &lt;code&gt;vim.g.mapleader = " "&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  vim.o
&lt;/h4&gt;

&lt;p&gt;This will likely be the bread and butter of your migration, as it's the most consistent 1:1 mapping of &lt;code&gt;set&lt;/code&gt; options and Lua expressions. See for yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"yes"&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitbelow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitright&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;swapfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;synmaxcol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note they even kept the weird &lt;code&gt;"yes"&lt;/code&gt;-instead-of-&lt;code&gt;true&lt;/code&gt; convention.&lt;/p&gt;

&lt;h4&gt;
  
  
  vim.opt
&lt;/h4&gt;

&lt;p&gt;This is a special Lua table (read: hash map or associative array) that allows you to use more Lua-friendly syntax to set options.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;vim.opt.listchars&lt;/code&gt; is pretty nice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listchars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"» "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;trail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"·"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;extends&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"›"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;precedes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"‹"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;nbsp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"␣"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  vim.api: Keymapping and Autocommands
&lt;/h3&gt;

&lt;p&gt;For more advanced functionality like keymapping and autocommands, you have &lt;code&gt;vim.api&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_create_autocmd&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="s2"&gt;"FileType"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rust"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_buf_set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tabstop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_buf_set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"shiftwidth"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_buf_set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"softtabstop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_set_keymap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'n'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;leader&amp;gt;s'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':split&amp;lt;CR&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;noremap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These are just some of the ideas and examples I was able to pull out of my experience in migrating to a Lua-based Neovim config. What do you think?&lt;/p&gt;

&lt;p&gt;Another highlight of this adventure in yak-shaving is that it makes me review my old configuration code, allowing me to change, edit, and re-contextualize the ideas that I had and my previous intentions.&lt;/p&gt;

&lt;p&gt;How about you? Have you done this same migration? Did I miss anything? Have you shaved any good yaks recently? I'd love to hear from you.&lt;/p&gt;

</description>
      <category>neovim</category>
      <category>lua</category>
      <category>dotfiles</category>
      <category>vimscript</category>
    </item>
  </channel>
</rss>
