all repos — gemini-redirect @ fcd5db0bbb4bb9fe310c1507e91664de87765514

blog/atom.xml (view raw)

   1<feed xmlns="http://www.w3.org/2005/Atom"><title>pagong</title><id>pagong</id><updated>2020-07-02T22:00:00+00:00</updated><entry><title>University posts</title><id>dist/university/index.html</id><updated>2020-07-02T22:00:00+00:00</updated><published>2020-07-02T22:00:00+00:00</published><summary>During university, there were a few subjects where I had to write blog posts for (either as</summary><content type="html" src="dist/university/index.html">&lt;!DOCTYPE html&gt;
   2&lt;html&gt;
   3&lt;head&gt;
   4&lt;meta charset=&quot;utf-8&quot; /&gt;
   5&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
   6&lt;title&gt;University posts&lt;/title&gt;
   7&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
   8&lt;/head&gt;
   9&lt;body&gt;
  10&lt;main&gt;
  11&lt;h1 class=&quot;title&quot; id=&quot;university_posts&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#university_posts&quot;&gt;¶&lt;/a&gt;University posts&lt;/h1&gt;
  12&lt;div class=&quot;date-created-modified&quot;&gt;2020-07-03&lt;/div&gt;
  13&lt;p&gt;During university, there were a few subjects where I had to write blog posts for (either as
  14evaluable tasks or just for fun). Currently, these are:&lt;/p&gt;
  15&lt;ul&gt;
  16&lt;li&gt;&lt;a href=&quot;/blog/mdad&quot;&gt;Data Mining and Data Warehousing&lt;/a&gt;&lt;/li&gt;
  17&lt;li&gt;&lt;a href=&quot;/blog/ribw&quot;&gt;Information Retrieval and Web Search&lt;/a&gt;&lt;/li&gt;
  18&lt;/ul&gt;
  19&lt;/main&gt;
  20&lt;/body&gt;
  21&lt;/html&gt;
  22 </content></entry><entry><title>Atemporal Blog Posts</title><id>dist/posts/index.html</id><updated>2020-07-02T22:00:00+00:00</updated><published>2020-07-02T22:00:00+00:00</published><summary>These are some interesting posts and links I've found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.</summary><content type="html" src="dist/posts/index.html">&lt;!DOCTYPE html&gt;
  23&lt;html&gt;
  24&lt;head&gt;
  25&lt;meta charset=&quot;utf-8&quot; /&gt;
  26&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
  27&lt;title&gt;Atemporal Blog Posts&lt;/title&gt;
  28&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
  29&lt;/head&gt;
  30&lt;body&gt;
  31&lt;main&gt;
  32&lt;h1 class=&quot;title&quot; id=&quot;atemporal_blog_posts&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#atemporal_blog_posts&quot;&gt;¶&lt;/a&gt;Atemporal Blog Posts&lt;/h1&gt;
  33&lt;div class=&quot;date-created-modified&quot;&gt;2020-07-03&lt;/div&gt;
  34&lt;p&gt;These are some interesting posts and links I've found around the web. I believe they are quite interesting and nice reads, so if you have the time, I encourage you to check some out.&lt;/p&gt;
  35&lt;h2 id=&quot;algorithms&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#algorithms&quot;&gt;¶&lt;/a&gt;Algorithms&lt;/h2&gt;
  36&lt;ul&gt;
  37&lt;li&gt;http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/. Image Dithering: Eleven Algorithms and Source Code. What does it mean and how to achieve it?&lt;/li&gt;
  38&lt;li&gt;https://cristian.io/post/bloom-filters/. Idempotence layer on bloom filters. What are they and how can they help?&lt;/li&gt;
  39&lt;li&gt;https://en.wikipedia.org/wiki/Huffman_coding. Huffman coding. This encoding is a simple yet interesting way of compressing information.&lt;/li&gt;
  40&lt;li&gt;https://github.com/mxgmn/WaveFunctionCollapse. Wave Function Collapse. Bitmap &amp;amp; tilemap generation from a single example with the help of ideas from quantum mechanics.&lt;/li&gt;
  41&lt;li&gt;https://blog.nelhage.com/2015/02/regular-expression-search-with-suffix-arrays/. Regular Expression Search with Suffix Arrays. A way to efficiently search large amounts of text.&lt;/li&gt;
  42&lt;/ul&gt;
  43&lt;h2 id=&quot;culture&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#culture&quot;&gt;¶&lt;/a&gt;Culture&lt;/h2&gt;
  44&lt;ul&gt;
  45&lt;li&gt;https://www.wired.com/story/ideas-joi-ito-robot-overlords/. Why Westerners Fear Robots and the Japanese Do Not. Explains some possible reasons for this case.&lt;/li&gt;
  46&lt;li&gt;http://catb.org/~esr/faqs/smart-questions.html. How To Ask Questions The Smart Way. Some bits of hacker culture and amazing tips on how to ask a question.&lt;/li&gt;
  47&lt;li&gt;http://apenwarr.ca/log/?m=201809#14. XML, blockchains, and the strange shapes of progress. Some of history about XML and blockchain.&lt;/li&gt;
  48&lt;li&gt;https://czep.net/17/legion-of-lobotomized-unices.html. Legion of lobotomized unices. A time where computers are treated a lot more nicely.&lt;/li&gt;
  49&lt;li&gt;https://eli.thegreenplace.net/2016/the-expression-problem-and-its-solutions/.  The Expression Problem and its solutions. What is it and what can we do to solve it?&lt;/li&gt;
  50&lt;li&gt;http://allendowney.blogspot.com/2015/08/the-inspection-paradox-is-everywhere.html. The Inspection Paradox is Everywhere. Interesting and very common phenomena.&lt;/li&gt;
  51&lt;li&gt;https://github.com/ChrisKnott/Algojammer. An experimental code editor for writing algorithms. Contains several links to different tools for reverse debugging.&lt;/li&gt;
  52&lt;li&gt;http://habitatchronicles.com/2017/05/what-are-capabilities/. What Are Capabilities? Good ideas with great security implications.&lt;/li&gt;
  53&lt;li&gt;https://blog.aurynn.com/2015/12/16-contempt-culture. Contempt Culture. Or why you should not speak crap about your non-favourite programming languages.&lt;/li&gt;
  54&lt;li&gt;https://www.lesswrong.com/posts/tscc3e5eujrsEeFN4/well-kept-gardens-die-by-pacifism. Well-Kept Gardens Die By Pacifism. Risks any online community can run into.&lt;/li&gt;
  55&lt;li&gt;https://ncase.me/. It's Nicky Case! They make some cool things worth checking out, I really like &amp;quot;we become what we behold&amp;quot;.&lt;/li&gt;
  56&lt;/ul&gt;
  57&lt;h2 id=&quot;debate&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#debate&quot;&gt;¶&lt;/a&gt;Debate&lt;/h2&gt;
  58&lt;ul&gt;
  59&lt;li&gt;https://steemit.com/opensource/@crell/open-source-is-awful. Open Source is awful. Has some points about why is it bad and how it could improve.&lt;/li&gt;
  60&lt;li&gt;http://www.mondo2000.com/2018/01/17/pink-lexical-goop-dark-side-autocorrect/. Pink Lexical Goop: The Dark Side of Autocorrect. It can shape how you think.&lt;/li&gt;
  61&lt;li&gt;http://blog.ploeh.dk/2015/08/03/idiomatic-or-idiosyncratic/. Idiomatic or idiosyncratic? Can porting code constructs from other languages have a positive effect?&lt;/li&gt;
  62&lt;li&gt;https://gamasutra.com/view/news/169296/Indepth_Functional_programming_in_C.php. In-depth: Functional programming in C++. Is it useful to bother with functional concepts in a language like C++?&lt;/li&gt;
  63&lt;li&gt;https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/. Notes on structured concurrency, or: Go statement considered harmful.&lt;/li&gt;
  64&lt;li&gt;https://queue.acm.org/detail.cfm?id=3212479. C Is Not a Low-level Language. Could there be alternative programming models designed for more specialized CPUs?&lt;/li&gt;
  65&lt;/ul&gt;
  66&lt;h2 id=&quot;food_for_thought&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#food_for_thought&quot;&gt;¶&lt;/a&gt;Food for Thought&lt;/h2&gt;
  67&lt;ul&gt;
  68&lt;li&gt;https://www.hillelwayne.com/post/divide-by-zero/. 1/0 = 0. Explores why it makes sense to redefine mathemathics under some circumstances, and why it is possible to do so.&lt;/li&gt;
  69&lt;li&gt;https://jeremykun.com/2018/04/13/for-mathematicians-does-not-mean-equality/. For mathematicians, = does not mean equality. What other definitions does the equal sign have?&lt;/li&gt;
  70&lt;li&gt;https://www.lesswrong.com/posts/2MD3NMLBPCqPfnfre/cached-thoughts. Cached Thoughts. How is it possible that our brains work at all?&lt;/li&gt;
  71&lt;li&gt;http://tonsky.me/blog/disenchantment/. Software disenchantment. Faster hardware and slower software is a trend.
  72&lt;ul&gt;
  73&lt;li&gt;https://blackhole12.com/blog/software-engineering-is-bad-but-it-s-not-that-bad/. Software Engineering Is Bad, But That's Not Why. This post has some good counterpoints to Software disenchantment.&lt;/li&gt;
  74&lt;/ul&gt;
  75&lt;/li&gt;
  76&lt;li&gt;http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/. What Color is Your Function? Spoiler: can we approach asynchronous IO better?&lt;/li&gt;
  77&lt;li&gt;https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5. I'm harvesting credit card numbers and passwords from your site. A word of warning when mindlessly adding dependencies.&lt;/li&gt;
  78&lt;li&gt;https://medium.com/message/everything-is-broken-81e5f33a24e1. Everything Is Broken. Some of the (probable) truths about our world.&lt;/li&gt;
  79&lt;/ul&gt;
  80&lt;h2 id=&quot;funny&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#funny&quot;&gt;¶&lt;/a&gt;Funny&lt;/h2&gt;
  81&lt;ul&gt;
  82&lt;li&gt;http://thedailywtf.com/articles/We-Use-BobX. We Use BobX. BobX.&lt;/li&gt;
  83&lt;li&gt;http://thedailywtf.com/articles/the-inner-json-effect. The Inner JSON Effect. For some reason, custom languages are in.&lt;/li&gt;
  84&lt;li&gt;https://thedailywtf.com/articles/exponential-backup. Exponential Backup. Far better than git.&lt;/li&gt;
  85&lt;li&gt;https://thedailywtf.com/articles/ITAPPMONROBOT. ITAPPMONROBOT. Solving software problems with hardware.&lt;/li&gt;
  86&lt;li&gt;https://thedailywtf.com/articles/a-tapestry-of-threads. A Tapestry of Threads.More threads must mean faster code, right?&lt;/li&gt;
  87&lt;li&gt;https://medium.com/commitlog/a-brief-totally-accurate-history-of-programming-languages-cd93ec806124. A Brief Totally Accurate History Of Programming Languages. Don't take offense for it!&lt;/li&gt;
  88&lt;/ul&gt;
  89&lt;h2 id=&quot;graphics&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#graphics&quot;&gt;¶&lt;/a&gt;Graphics&lt;/h2&gt;
  90&lt;ul&gt;
  91&lt;li&gt;http://shaunlebron.github.io/visualizing-projections/. Visualizing Projections. Small post about different projection methods.&lt;/li&gt;
  92&lt;li&gt;http://www.iquilezles.org/www/index.htm. A &lt;em&gt;lot&lt;/em&gt; of useful and quality articles regarding computer graphics.&lt;/li&gt;
  93&lt;/ul&gt;
  94&lt;h2 id=&quot;history&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#history&quot;&gt;¶&lt;/a&gt;History&lt;/h2&gt;
  95&lt;ul&gt;
  96&lt;li&gt;https://twobithistory.org/2018/08/18/ada-lovelace-note-g.html. What Did Ada Lovelace's Program Actually Do?. And other characters that took part in the beginning's of programming.&lt;/li&gt;
  97&lt;li&gt;https://chrisdown.name/2018/01/02/in-defence-of-swap.html. In defence of swap: common misconceptions. Swap is still an useful concept.&lt;/li&gt;
  98&lt;li&gt;https://www.pacifict.com/Story/. The Graphing Calculator Story. A great classic Apple tale.&lt;/li&gt;
  99&lt;li&gt;https://twobithistory.org/2018/10/14/lisp.html. How Lisp Became God's Own Programming Language. Lisp as a foundational programming language.&lt;/li&gt;
 100&lt;/ul&gt;
 101&lt;h2 id=&quot;motivational&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#motivational&quot;&gt;¶&lt;/a&gt;Motivational&lt;/h2&gt;
 102&lt;ul&gt;
 103&lt;li&gt;https://www.joelonsoftware.com/2002/01/06/fire-and-motion/. Fire And Motion. What does actually take to get things done?&lt;/li&gt;
 104&lt;li&gt;https://realmensch.org/2017/08/25/the-parable-of-the-two-programmers/. The Parable of the Two Programmers. This tale is about two different types of programmer and their respective endings in a company, illustrating how the one you wouldn't expect to actually ends in a better situation.&lt;/li&gt;
 105&lt;li&gt;https://byorgey.wordpress.com/2018/05/06/conversations-with-a-six-year-old-on-functional-programming/. Conversations with a six-year-old on functional programming. Little kids today can be really interested in technological topics.&lt;/li&gt;
 106&lt;li&gt;https://bulletproofmusician.com/how-many-hours-a-day-should-you-practice/. How Many Hours a Day Should You Practice?. While the article is about music, it applies to any other areas.&lt;/li&gt;
 107&lt;li&gt;http://nathanmarz.com/blog/suffering-oriented-programming.html. Suffering-oriented programming. A possibly new approach on how you could tackle your new projects.&lt;/li&gt;
 108&lt;li&gt;https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/. Things You Should Never Do, Part I. There is no need to rewrite your code.&lt;/li&gt;
 109&lt;/ul&gt;
 110&lt;h2 id=&quot;optimization&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#optimization&quot;&gt;¶&lt;/a&gt;Optimization&lt;/h2&gt;
 111&lt;ul&gt;
 112&lt;li&gt;http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html. What Every C Programmer Should Know About Undefined Behavior #1/3. Explains what undefined behaviour is and why it makes sense.&lt;/li&gt;
 113&lt;li&gt;http://ridiculousfish.com/blog/posts/labor-of-division-episode-i.html. Labor of Division (Episode I). Some tricks to divide without division.&lt;/li&gt;
 114&lt;li&gt;http://blog.moertel.com/posts/2013-12-14-great-old-timey-game-programming-hack.html. A Great Old-Timey Game-Programming Hack. Abusing instructions to make games playable even on the slowest hardware.&lt;/li&gt;
 115&lt;li&gt;https://web.archive.org/web/20191213224640/https://people.eecs.berkeley.edu/~sangjin/2012/12/21/epoll-vs-kqueue.html. Scalable Event Multiplexing: epoll vs kqueue. How good OS primitives can really help performance and scability.&lt;/li&gt;
 116&lt;li&gt;https://adamdrake.com/command-line-tools-can-be-235x-faster-than-your-hadoop-cluster.html. Command-line Tools can be 235x Faster than your Hadoop Cluster. Or how to use the right tool for the right job.&lt;/li&gt;
 117&lt;li&gt;https://nullprogram.com/blog/2018/05/27/. When FFI Function Calls Beat Native C. How lua beat C at it and the explanation behind it.&lt;/li&gt;
 118&lt;li&gt;http://igoro.com/archive/gallery-of-processor-cache-effects/. Gallery of Processor Cache Effects. Knowing a few things about the cache can make a big difference.&lt;/li&gt;
 119&lt;/ul&gt;
 120&lt;/main&gt;
 121&lt;/body&gt;
 122&lt;/html&gt;
 123 </content></entry><entry><title>Python ctypes and Windows</title><id>dist/ctypes-and-windows/index.html</id><updated>2020-07-02T22:00:00+00:00</updated><published>2019-06-18T22:00:00+00:00</published><summary>Python</summary><content type="html" src="dist/ctypes-and-windows/index.html">&lt;!DOCTYPE html&gt;
 124&lt;html&gt;
 125&lt;head&gt;
 126&lt;meta charset=&quot;utf-8&quot; /&gt;
 127&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 128&lt;title&gt;Python ctypes and Windows&lt;/title&gt;
 129&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 130&lt;/head&gt;
 131&lt;body&gt;
 132&lt;main&gt;
 133&lt;h1 class=&quot;title&quot; id=&quot;python_ctypes_and_windows&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#python_ctypes_and_windows&quot;&gt;¶&lt;/a&gt;Python ctypes and Windows&lt;/h1&gt;
 134&lt;div class=&quot;date-created-modified&quot;&gt;Created 2019-06-19&lt;br&gt;
 135Modified 2020-07-03&lt;/div&gt;
 136&lt;p&gt;&lt;a href=&quot;https://www.python.org/&quot;&gt;Python&lt;/a&gt;'s &lt;a href=&quot;https://docs.python.org/3/library/ctypes.html&quot;&gt;&lt;code&gt;ctypes&lt;/code&gt;&lt;/a&gt; is quite a nice library to easily load and invoke C methods available in already-compiled &lt;a href=&quot;https://en.wikipedia.org/wiki/Dynamic-link_library&quot;&gt;&lt;code&gt;.dll&lt;/code&gt; files&lt;/a&gt; without any additional dependencies. And I &lt;em&gt;love&lt;/em&gt; depending on as little as possible.&lt;/p&gt;
 137&lt;p&gt;In this blog post, we will walk through my endeavors to use &lt;code&gt;ctypes&lt;/code&gt; with the &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/&quot;&gt;Windows API&lt;/a&gt;, and do some cool stuff with it.&lt;/p&gt;
 138&lt;p&gt;We will assume some knowledge of C/++ and Python, since we will need to read and write a bit of both. Please note that this post is only an introduction to &lt;code&gt;ctypes&lt;/code&gt;, and if you need more information you should consult the &lt;a href=&quot;https://docs.python.org/3/library/ctypes.html&quot;&gt;Python's documentation for &lt;code&gt;ctypes&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
 139&lt;p&gt;While the post focuses on Windows' API, the code here probably applies to unix-based systems with little modifications.&lt;/p&gt;
 140&lt;h2 id=&quot;basics&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#basics&quot;&gt;¶&lt;/a&gt;Basics&lt;/h2&gt;
 141&lt;p&gt;First of all, let's learn how to load a library. Let's say we want to load &lt;code&gt;User32.dll&lt;/code&gt;:&lt;/p&gt;
 142&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import ctypes
 143
 144ctypes.windll.user32
 145&lt;/code&gt;&lt;/pre&gt;
 146&lt;p&gt;Yes, it's that simple. When you access an attribute of &lt;code&gt;windll&lt;/code&gt;, said library will load. Since Windows is case-insensitive, we will use lowercase consistently.&lt;/p&gt;
 147&lt;p&gt;Calling a function is just as simple. Let's say you want to call &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setcursorpos&quot;&gt;&lt;code&gt;SetCursorPos&lt;/code&gt;&lt;/a&gt;, which is defined as follows:&lt;/p&gt;
 148&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;BOOL SetCursorPos(
 149    int X,
 150    int Y
 151);
 152&lt;/code&gt;&lt;/pre&gt;
 153&lt;p&gt;Okay, it returns a &lt;code&gt;bool&lt;/code&gt; and takes two inputs, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. So we can call it like so:&lt;/p&gt;
 154&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;ctypes.windll.user32.SetCursorPos(100, 100)
 155&lt;/code&gt;&lt;/pre&gt;
 156&lt;p&gt;Try it! Your cursor will move!&lt;/p&gt;
 157&lt;h2 id=&quot;funky_stuff&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#funky_stuff&quot;&gt;¶&lt;/a&gt;Funky Stuff&lt;/h2&gt;
 158&lt;p&gt;We can go a bit more crazy and make it form a spiral:&lt;/p&gt;
 159&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import math
 160import time
 161
 162for i in range(200):
 163    x = int(500 + math.cos(i / 5) * i)
 164    y = int(500 + math.sin(i / 5) * i)
 165    ctypes.windll.user32.SetCursorPos(x, y)
 166    time.sleep(0.05)
 167&lt;/code&gt;&lt;/pre&gt;
 168&lt;p&gt;Ah, it's always so pleasant to do random stuff when programming. Sure makes it more fun.&lt;/p&gt;
 169&lt;h2 id=&quot;complex_structures&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#complex_structures&quot;&gt;¶&lt;/a&gt;Complex Structures&lt;/h2&gt;
 170&lt;p&gt;&lt;code&gt;SetCursorPos&lt;/code&gt; was really simple. It took two parameters and they both were integers. Let's go with something harder. Let's go with &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendinput&quot;&gt;&lt;code&gt;SendInput&lt;/code&gt;&lt;/a&gt;! Emulating input will be a fun exercise:&lt;/p&gt;
 171&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;UINT SendInput(
 172    UINT    cInputs,
 173    LPINPUT pInputs,
 174    int     cbSize
 175);
 176&lt;/code&gt;&lt;/pre&gt;
 177&lt;p&gt;Okay, &lt;code&gt;LPINPUT&lt;/code&gt;, what are you? Microsoft likes to prefix types with what they are. In this case, &lt;code&gt;LP&lt;/code&gt; stands for &amp;quot;Long Pointer&amp;quot; (I guess?), so &lt;code&gt;LPINPUT&lt;/code&gt; is just a Long Pointer to &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taginput&quot;&gt;&lt;code&gt;INPUT&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
 178&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;typedef struct tagINPUT {
 179    DWORD type;
 180    union {
 181        MOUSEINPUT    mi;
 182        KEYBDINPUT    ki;
 183        HARDWAREINPUT hi;
 184    } DUMMYUNIONNAME;
 185} INPUT, *PINPUT, *LPINPUT;
 186&lt;/code&gt;&lt;/pre&gt;
 187&lt;p&gt;Alright, that's new. We have a &lt;code&gt;struct&lt;/code&gt; and &lt;code&gt;union&lt;/code&gt;, two different concepts. We can define both with &lt;code&gt;ctypes&lt;/code&gt;:&lt;/p&gt;
 188&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;INPUT_MOUSE = 0
 189INPUT_KEYBOARD = 1
 190INPUT_HARDWARE = 2
 191
 192class INPUT(ctypes.Structure):
 193    _fields_ = [
 194        ('type', ctypes.c_long),
 195        ...
 196    ]
 197&lt;/code&gt;&lt;/pre&gt;
 198&lt;p&gt;Structures are classes that subclass &lt;code&gt;ctypes.Structure&lt;/code&gt;, and you define their fields in the &lt;code&gt;_fields_&lt;/code&gt; class-level variable, which is a list of tuples &lt;code&gt;(field name, field type)&lt;/code&gt;.&lt;/p&gt;
 199&lt;p&gt;The C structure had a &lt;code&gt;DWORD type&lt;/code&gt;. &lt;code&gt;DWORD&lt;/code&gt; is a &lt;code&gt;c_long&lt;/code&gt;, and &lt;code&gt;type&lt;/code&gt; is a name like any other, which is why we did &lt;code&gt;('type', ctypes.c_long)&lt;/code&gt;.&lt;/p&gt;
 200&lt;p&gt;But what about the union? It's anonymous, and we can't make anonymous unions (&lt;em&gt;citation needed&lt;/em&gt;) with &lt;code&gt;ctypes&lt;/code&gt;. We will give it a concrete name and a type.&lt;/p&gt;
 201&lt;p&gt;Before defining the union, we need to define its inner structures, &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmouseinput&quot;&gt;&lt;code&gt;MOUSEINPUT&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagkeybdinput&quot;&gt;&lt;code&gt;KEYBDINPUT&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taghardwareinput&quot;&gt;&lt;code&gt;HARDWAREINPUT&lt;/code&gt;&lt;/a&gt;. We won't be using them all, but since they count towards the final struct size (C will choose the largest structure as the final size), we need them, or Windows' API will get confused and refuse to work (personal experience):&lt;/p&gt;
 202&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class MOUSEINPUT(ctypes.Structure):
 203    _fields_ = [
 204        ('dx', ctypes.c_long),
 205        ('dy', ctypes.c_long),
 206        ('mouseData', ctypes.c_long),
 207        ('dwFlags', ctypes.c_long),
 208        ('time', ctypes.c_long),
 209        ('dwExtraInfo', ctypes.POINTER(ctypes.c_ulong))
 210    ]
 211
 212
 213class KEYBDINPUT(ctypes.Structure):
 214    _fields_ = [
 215        ('wVk', ctypes.c_short),
 216        ('wScan', ctypes.c_short),
 217        ('dwFlags', ctypes.c_long),
 218        ('time', ctypes.c_long),
 219        ('dwExtraInfo', ctypes.POINTER(ctypes.c_ulong))
 220    ]
 221
 222
 223class HARDWAREINPUT(ctypes.Structure):
 224    _fields_ = [
 225        ('uMsg', ctypes.c_long),
 226        ('wParamL', ctypes.c_short),
 227        ('wParamH', ctypes.c_short)
 228    ]
 229
 230
 231class INPUTUNION(ctypes.Union):
 232    _fields_ = [
 233        ('mi', MOUSEINPUT),
 234        ('ki', KEYBDINPUT),
 235        ('hi', HARDWAREINPUT)
 236    ]
 237
 238
 239class INPUT(ctypes.Structure):
 240    _fields_ = [
 241        ('type', ctypes.c_long),
 242        ('value', INPUTUNION)
 243    ]
 244&lt;/code&gt;&lt;/pre&gt;
 245&lt;p&gt;Some things to note:&lt;/p&gt;
 246&lt;ul&gt;
 247&lt;li&gt;Pointers are defined as &lt;code&gt;ctypes.POINTER(inner type)&lt;/code&gt;.&lt;/li&gt;
 248&lt;li&gt;The field names can be anything you want. You can make them more &amp;quot;pythonic&amp;quot; if you want (such as changing &lt;code&gt;dwExtraInfo&lt;/code&gt; for just &lt;code&gt;extra_info&lt;/code&gt;), but I chose to stick with the original naming.&lt;/li&gt;
 249&lt;li&gt;The union is very similar, but it uses &lt;code&gt;ctypes.Union&lt;/code&gt; instead of &lt;code&gt;ctypes.Structure&lt;/code&gt;.&lt;/li&gt;
 250&lt;li&gt;We gave a name to the anonymous union, &lt;code&gt;INPUTUNION&lt;/code&gt;, and used it inside &lt;code&gt;INPUT&lt;/code&gt; with also a made-up name, &lt;code&gt;('value', INPUTUNION)&lt;/code&gt;.&lt;/li&gt;
 251&lt;/ul&gt;
 252&lt;p&gt;Now that we have all the types we need defined, we can use them:&lt;/p&gt;
 253&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;KEYEVENTF_KEYUP = 0x0002
 254
 255def press(vk, down):
 256    inputs = INPUT(type=INPUT_KEYBOARD, value=INPUTUNION(ki=KEYBDINPUT(
 257        wVk=vk,
 258        wScan=0,
 259        dwFlags=0 if down else KEYEVENTF_KEYUP,
 260        time=0,
 261        dwExtraInfo=None
 262    )))
 263    ctypes.windll.user32.SendInput(1, ctypes.byref(inputs), ctypes.sizeof(inputs))
 264
 265
 266for char in 'HELLO':
 267    press(ord(char), down=True)
 268    press(ord(char), down=False)
 269&lt;/code&gt;&lt;/pre&gt;
 270&lt;p&gt;Run it! It will press and release the keys &lt;code&gt;hello&lt;/code&gt; to type the word &lt;code&gt;&amp;quot;hello&amp;quot;&lt;/code&gt;!&lt;/p&gt;
 271&lt;p&gt;&lt;code&gt;vk&lt;/code&gt; stands for &amp;quot;virtual key&amp;quot;. Letters correspond with their upper-case ASCII value, which is what we did above. You can find all the available keys in the page with all the &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes&quot;&gt;Virtual Key Codes&lt;/a&gt;.&lt;/p&gt;
 272&lt;h2 id=&quot;dynamic_inputs_and_pointers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#dynamic_inputs_and_pointers&quot;&gt;¶&lt;/a&gt;Dynamic Inputs and Pointers&lt;/h2&gt;
 273&lt;p&gt;What happens if a method wants something by reference? That is, a pointer to your thing? For example, &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getcursorpos&quot;&gt;&lt;code&gt;GetCursorPos&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
 274&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;typedef struct tagPOINT {
 275    LONG x;
 276    LONG y;
 277} POINT, *PPOINT, *NPPOINT, *LPPOINT;
 278
 279BOOL GetCursorPos(
 280    LPPOINT lpPoint
 281);
 282&lt;/code&gt;&lt;/pre&gt;
 283&lt;p&gt;It wants a Long Pointer to &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/desktop/api/windef/ns-windef-point&quot;&gt;&lt;code&gt;POINT&lt;/code&gt;&lt;/a&gt;. We can do just that with &lt;code&gt;ctypes.byref&lt;/code&gt;:&lt;/p&gt;
 284&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class POINT(ctypes.Structure):
 285    _fields_ = [
 286        ('x', ctypes.c_long),
 287        ('y', ctypes.c_long)
 288    ]
 289
 290
 291def get_mouse():
 292    point = POINT()
 293    ctypes.windll.user32.GetCursorPos(ctypes.byref(point))
 294    #                  pass our point by ref ^^^^^
 295    # this lets GetCursorPos fill its x and y fields
 296
 297    return point.x, point.y
 298
 299
 300while True:
 301    print(get_mouse())
 302    time.sleep(0.05)
 303&lt;/code&gt;&lt;/pre&gt;
 304&lt;p&gt;Now you can track the mouse position! Make sure to &lt;code&gt;Ctrl+C&lt;/code&gt; the program when you're tired of it.&lt;/p&gt;
 305&lt;p&gt;What happens if a method wants a dynamically-sized input?&lt;/p&gt;
 306&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;buffer = ctypes.create_string_buffer(size)
 307&lt;/code&gt;&lt;/pre&gt;
 308&lt;p&gt;In that case, you can create an in-memory &lt;code&gt;buffer&lt;/code&gt; of &lt;code&gt;size&lt;/code&gt; with &lt;code&gt;ctypes.create_string_buffer&lt;/code&gt;. It will return a character array of that size, which you can pass as a pointer directly (without &lt;code&gt;ctypes.byref&lt;/code&gt;).&lt;/p&gt;
 309&lt;p&gt;To access the buffer's contents, you can use either &lt;code&gt;.raw&lt;/code&gt; or &lt;code&gt;.value&lt;/code&gt;:&lt;/p&gt;
 310&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;entire_buffer_as_bytes = buffer.raw
 311up_until_null = buffer.value
 312&lt;/code&gt;&lt;/pre&gt;
 313&lt;p&gt;When the method fills in the data, you can &lt;code&gt;cast&lt;/code&gt; your buffer back into a pointer of a concrete type:&lt;/p&gt;
 314&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;result_ptr = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_long))
 315&lt;/code&gt;&lt;/pre&gt;
 316&lt;p&gt;And you can de-reference pointers with &lt;code&gt;.contents&lt;/code&gt;:&lt;/p&gt;
 317&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;first_result = result_ptr.contents
 318&lt;/code&gt;&lt;/pre&gt;
 319&lt;h2 id=&quot;arrays&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#arrays&quot;&gt;¶&lt;/a&gt;Arrays&lt;/h2&gt;
 320&lt;p&gt;Arrays are defined as &lt;code&gt;type * size&lt;/code&gt;. Your linter may not like that, and if you don't know the size beforehand, consider creating a 0-sized array. For example:&lt;/p&gt;
 321&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 10 longs
 322ten_longs = (ctypes.c_long * 10)()
 323for i in range(10):
 324    ten_longs[i] = 2 ** i
 325
 326# Unknown size of longs, e.g. inside some Structure
 327longs = (ctypes.c_long * 0)
 328
 329# Now you know how many longs it actually was
 330known_longs = ctypes.cast(
 331    ctypes.byref(longs),
 332    ctypes.POINTER(ctypes.c_long * size)
 333).contents
 334&lt;/code&gt;&lt;/pre&gt;
 335&lt;p&gt;If there's a better way to initialize arrays, please let me know.&lt;/p&gt;
 336&lt;h2 id=&quot;wintypes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#wintypes&quot;&gt;¶&lt;/a&gt;wintypes&lt;/h2&gt;
 337&lt;p&gt;Under Windows, the &lt;code&gt;ctypes&lt;/code&gt; module has a &lt;code&gt;wintypes&lt;/code&gt; submodule. This one contains definitions like &lt;code&gt;HWND&lt;/code&gt; which may be useful and can be imported as:&lt;/p&gt;
 338&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from ctypes.wintypes import HWND, LPCWSTR, UINT
 339&lt;/code&gt;&lt;/pre&gt;
 340&lt;h2 id=&quot;callbacks&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#callbacks&quot;&gt;¶&lt;/a&gt;Callbacks&lt;/h2&gt;
 341&lt;p&gt;Some functions (I'm looking at you, &lt;a href=&quot;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows&quot;&gt;&lt;code&gt;EnumWindows&lt;/code&gt;&lt;/a&gt;) ask us to pass a callback. In this case, it wants a &lt;a href=&quot;https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633498(v=vs.85)&quot;&gt;&lt;code&gt;EnumWindowsProc&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
 342&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;BOOL EnumWindows(
 343    WNDENUMPROC lpEnumFunc,
 344    LPARAM      lParam
 345);
 346
 347BOOL CALLBACK EnumWindowsProc(
 348    _In_ HWND   hwnd,
 349    _In_ LPARAM lParam
 350);
 351&lt;/code&gt;&lt;/pre&gt;
 352&lt;p&gt;The naive approach won't work:&lt;/p&gt;
 353&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def callback(hwnd, lParam):
 354    print(hwnd)
 355    return True
 356
 357ctypes.windll.user32.EnumWindows(callback, 0)
 358# ctypes.ArgumentError: argument 1: &amp;lt;class 'TypeError'&amp;gt;: Don't know how to convert parameter 1
 359# Aww.
 360&lt;/code&gt;&lt;/pre&gt;
 361&lt;p&gt;Instead, you must wrap your function as a C definition like so:&lt;/p&gt;
 362&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from ctypes.wintypes import BOOL, HWND, LPARAM
 363
 364EnumWindowsProc = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
 365
 366def callback(hwnd, lParam):
 367    print(hwnd)
 368    return True
 369
 370# Wrap the function in the C definition
 371callback = EnumWindowsProc(callback)
 372
 373ctypes.windll.user32.EnumWindows(callback, 0)
 374# Yay, it works.
 375&lt;/code&gt;&lt;/pre&gt;
 376&lt;p&gt;You may have noticed this is what decorators do, wrap the function. So…&lt;/p&gt;
 377&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from ctypes.wintypes import BOOL, HWND, LPARAM
 378
 379@ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
 380def callback(hwnd, lParam):
 381    print(hwnd)
 382    return True
 383
 384ctypes.windll.user32.EnumWindows(callback, 0)
 385&lt;/code&gt;&lt;/pre&gt;
 386&lt;p&gt;…will also work. And it is a &lt;em&gt;lot&lt;/em&gt; fancier.&lt;/p&gt;
 387&lt;h2 id=&quot;closing_words&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#closing_words&quot;&gt;¶&lt;/a&gt;Closing Words&lt;/h2&gt;
 388&lt;p&gt;With the knowledge above and some experimentation, you should be able to call and do (almost) anything you want. That was pretty much all I needed on my project anyway :)&lt;/p&gt;
 389&lt;p&gt;We have been letting Python convert Python values into C values, but you can do so explicitly too. For example, you can use &lt;code&gt;ctypes.c_short(17)&lt;/code&gt; to make sure to pass that &lt;code&gt;17&lt;/code&gt; as a &lt;code&gt;short&lt;/code&gt;. And if you have a &lt;code&gt;c_short&lt;/code&gt;, you can convert or cast it to its Python &lt;code&gt;.value&lt;/code&gt; as &lt;code&gt;some_short.value&lt;/code&gt;. The same applies for integers, longs, floats, doubles… pretty much anything, char pointers (strings) included.&lt;/p&gt;
 390&lt;p&gt;If you can't find something in their online documentation, you can always &lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;&lt;code&gt;rg&lt;/code&gt;&lt;/a&gt; for it in the &lt;code&gt;C:\Program Files (x86)\Windows Kits\10\Include\*&lt;/code&gt; directory.&lt;/p&gt;
 391&lt;p&gt;Note that the &lt;code&gt;ctypes.Structure&lt;/code&gt;'s that you define can have more methods of your own. For example, you can write them a &lt;code&gt;__str__&lt;/code&gt; to easily view its fields, or define a &lt;code&gt;@property&lt;/code&gt; to re-interpret some data in a meaningful way.&lt;/p&gt;
 392&lt;p&gt;For enumerations, you can pass just the right integer number, make a constant for it, or if you prefer, use a &lt;a href=&quot;https://docs.python.org/3/library/enum.html#enum.IntEnum&quot;&gt;&lt;code&gt;enum.IntEnum&lt;/code&gt;&lt;/a&gt;. For example, &lt;a href=&quot;https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism/dismloglevel-enumeration&quot;&gt;&lt;code&gt;DismLogLevel&lt;/code&gt;&lt;/a&gt; would be:&lt;/p&gt;
 393&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class DismLogLevel(enum.IntEnum):
 394    DismLogErrors = 0
 395    DismLogErrorsWarnings = 1
 396    DismLogErrorsWarningsInfo = 2
 397&lt;/code&gt;&lt;/pre&gt;
 398&lt;p&gt;And you &lt;em&gt;should&lt;/em&gt; be able to pass &lt;code&gt;DismLogLevel.DismLogErrors&lt;/code&gt; as the parameter now.&lt;/p&gt;
 399&lt;p&gt;If you see a function definition like &lt;code&gt;Function(void)&lt;/code&gt;, that's C's way of saying it takes no parameters, so just call it as &lt;code&gt;Function()&lt;/code&gt;.&lt;/p&gt;
 400&lt;p&gt;Make sure to pass all parameters, even if they seem optional they probably still want a &lt;code&gt;NULL&lt;/code&gt; at least, and of course, read the documentation well. Some methods have certain pre-conditions.&lt;/p&gt;
 401&lt;p&gt;Have fun hacking!&lt;/p&gt;
 402&lt;/main&gt;
 403&lt;/body&gt;
 404&lt;/html&gt;
 405 </content></entry><entry><title>Shattered Pixel Dungeon</title><id>dist/pixel-dungeon/index.html</id><updated>2020-07-02T22:00:00+00:00</updated><published>2019-06-02T22:00:00+00:00</published><summary>Shattered Pixel Dungeon</summary><content type="html" src="dist/pixel-dungeon/index.html">&lt;!DOCTYPE html&gt;
 406&lt;html&gt;
 407&lt;head&gt;
 408&lt;meta charset=&quot;utf-8&quot; /&gt;
 409&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 410&lt;title&gt;Shattered Pixel Dungeon&lt;/title&gt;
 411&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 412&lt;/head&gt;
 413&lt;body&gt;
 414&lt;main&gt;
 415&lt;h1 class=&quot;title&quot; id=&quot;shattered_pixel_dungeon&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#shattered_pixel_dungeon&quot;&gt;¶&lt;/a&gt;Shattered Pixel Dungeon&lt;/h1&gt;
 416&lt;div class=&quot;date-created-modified&quot;&gt;Created 2019-06-03&lt;br&gt;
 417Modified 2020-07-03&lt;/div&gt;
 418&lt;p&gt;&lt;a href=&quot;https://shatteredpixel.com/shatteredpd/&quot;&gt;Shattered Pixel Dungeon&lt;/a&gt; is the classic roguelike RPG game with randomly-generated dungeons. As a new player, it was a bit frustrating to be constantly killed on the first levels of the dungeon, but with some practice it's easy to reach high levels if you can kill the first boss.&lt;/p&gt;
 419&lt;h2 id=&quot;basic_tips&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#basic_tips&quot;&gt;¶&lt;/a&gt;Basic Tips&lt;/h2&gt;
 420&lt;p&gt;The game comes with its own tips, but here's a short and straight-forward summary:&lt;/p&gt;
 421&lt;ul&gt;
 422&lt;li&gt;&lt;strong&gt;Don't rush into enemies&lt;/strong&gt;. Abuse doors and small corridors to kill them one by one. You can use the clock on the bottom left to wait a turn without moving.&lt;/li&gt;
 423&lt;li&gt;&lt;strong&gt;Explore each level at full&lt;/strong&gt;. You will find goodies and gain XP while doing so.&lt;/li&gt;
 424&lt;li&gt;&lt;strong&gt;Upon finding a special room&lt;/strong&gt; (e.g. has a chest but is protected by piranhas), drink all potions that you found in that level until there's one that helps you (e.g. be invisible so piranhas leave you alone). There is guaranteed to be a helpful one per level with special rooms.&lt;/li&gt;
 425&lt;li&gt;&lt;strong&gt;Drink potions as early as possible&lt;/strong&gt;. Harmful potions do less damage on early levels (and if you die, you lose less). This will keep them identified early for the rest of the game.&lt;/li&gt;
 426&lt;li&gt;&lt;strong&gt;Read scrolls as early as possible&lt;/strong&gt; as well. This will keep them identified. It may be worth to wait until you have an item which may be cursed and until the level is clear, because some scrolls clean curses and others alert enemies.&lt;/li&gt;
 427&lt;li&gt;&lt;strong&gt;Food and health are resources&lt;/strong&gt; that you have to &lt;em&gt;manage&lt;/em&gt;, not keep them always at full. Even if you are starving and taking damage, you may not need to eat &lt;em&gt;just yet&lt;/em&gt;, since food is scarce. Eat when you are low on health or in possible danger.&lt;/li&gt;
 428&lt;li&gt;&lt;strong&gt;Piranhas&lt;/strong&gt;. Seriously, just leave them alone if you are melee. They're free food if you're playing ranged, though.&lt;/li&gt;
 429&lt;li&gt;&lt;strong&gt;Prefer armor over weapons&lt;/strong&gt;. And make sure to identify or clean it from curses before wearing anything!&lt;/li&gt;
 430&lt;li&gt;&lt;strong&gt;Find a dew vial early&lt;/strong&gt;. It's often a better idea to store dew (health) for later than to use it as soon as possible.&lt;/li&gt;
 431&lt;/ul&gt;
 432&lt;h2 id=&quot;bosses&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bosses&quot;&gt;¶&lt;/a&gt;Bosses&lt;/h2&gt;
 433&lt;p&gt;There is a boss every 5 levels.&lt;/p&gt;
 434&lt;ul&gt;
 435&lt;li&gt;&lt;strong&gt;Level 5 boss&lt;/strong&gt;. Try to stay on water, but don't let &lt;em&gt;it&lt;/em&gt; stay on water since it will heal. Be careful when he starts enraging.&lt;/li&gt;
 436&lt;li&gt;&lt;strong&gt;Level 10 boss&lt;/strong&gt;. Ranged weapons are good against it.&lt;/li&gt;
 437&lt;li&gt;&lt;strong&gt;Level 15 boss&lt;/strong&gt;. I somehow managed to tank it with a health potion.&lt;/li&gt;
 438&lt;li&gt;&lt;strong&gt;Level 20 boss&lt;/strong&gt;. I didn't get this far just yet. You are advised to use scrolls of magic mapping in the last levels to skip straight to the boss, since there's nothing else of value.&lt;/li&gt;
 439&lt;li&gt;&lt;strong&gt;Level 25 boss&lt;/strong&gt;. The final boss. Good job if you made it this far!&lt;/li&gt;
 440&lt;/ul&gt;
 441&lt;h2 id=&quot;mage&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#mage&quot;&gt;¶&lt;/a&gt;Mage&lt;/h2&gt;
 442&lt;p&gt;If you followed the basic tips, you will sooner or later make use of two scrolls of upgrade in a single run. This will unlock the mage class, which is ridiculously powerful. He starts with a ranged-weapon, a magic missile wand, which is really helpful to keep enemies at a distance. Normally, you want to use this at first to surprise attack them soon, and if you are low on charges, you may go melee on normal enemies if you are confident.&lt;/p&gt;
 443&lt;h2 id=&quot;luck&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#luck&quot;&gt;¶&lt;/a&gt;Luck&lt;/h2&gt;
 444&lt;p&gt;This game is all about luck and patience! Some runs will be better than others, and you should thank and pray the RNG gods for them. If you don't, they will only give you cursed items and not a single scroll to clean them. So, good luck and enjoy playing!&lt;/p&gt;
 445&lt;/main&gt;
 446&lt;/body&gt;
 447&lt;/html&gt;
 448 </content></entry><entry><title>Breaking Risk of Rain</title><id>dist/breaking-ror/index.html</id><updated>2020-07-02T22:00:00+00:00</updated><published>2019-01-11T23:00:00+00:00</published><summary>Risk of Rain</summary><content type="html" src="dist/breaking-ror/index.html">&lt;!DOCTYPE html&gt;
 449&lt;html&gt;
 450&lt;head&gt;
 451&lt;meta charset=&quot;utf-8&quot; /&gt;
 452&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 453&lt;title&gt;Breaking Risk of Rain&lt;/title&gt;
 454&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 455&lt;/head&gt;
 456&lt;body&gt;
 457&lt;main&gt;
 458&lt;h1 class=&quot;title&quot; id=&quot;breaking_risk_of_rain&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#breaking_risk_of_rain&quot;&gt;¶&lt;/a&gt;Breaking Risk of Rain&lt;/h1&gt;
 459&lt;div class=&quot;date-created-modified&quot;&gt;Created 2019-01-12&lt;br&gt;
 460Modified 2020-07-03&lt;/div&gt;
 461&lt;p&gt;&lt;a href=&quot;https://riskofraingame.com/&quot;&gt;Risk of Rain&lt;/a&gt; is a fun little game you can spend a lot of hours on. It's incredibly challenging for new players, and fun once you have learnt the basics. This blog will go through what I've learnt and how to play the game correctly.&lt;/p&gt;
 462&lt;h2 id=&quot;getting_started&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#getting_started&quot;&gt;¶&lt;/a&gt;Getting Started&lt;/h2&gt;
 463&lt;p&gt;If you're new to the game, you may find it frustrating. You must learn very well to dodge.&lt;/p&gt;
 464&lt;p&gt;Your first &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Category:Characters&quot;&gt;character&lt;/a&gt; will be &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Commando&quot;&gt;Commando&lt;/a&gt;. He's actually a very nice character. Use your third skill (dodge) to move faster, pass through large groups of enemies, and negate fall damage.&lt;/p&gt;
 465&lt;p&gt;If there are a lot of monsters, remember to &lt;strong&gt;leave&lt;/strong&gt; from there! It's really important for survival. Most enemies &lt;strong&gt;don't do body damage&lt;/strong&gt;. Not even the body of the &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Magma_Worm&quot;&gt;Magma Worm&lt;/a&gt; or the &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Wandering_Vagrant&quot;&gt;Wandering Vagrant&lt;/a&gt; (just dodge the head and projectiles respectively).&lt;/p&gt;
 466&lt;p&gt;The first thing you must do is always &lt;strong&gt;rush for the teleporter&lt;/strong&gt;. Completing the levels quick will make the game easier. But make sure to take note of &lt;strong&gt;where the chests are&lt;/strong&gt;! When you have time (even when the countdown finishes), go back for them and buy as many as you can. Generally, prefer &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Chest&quot;&gt;chests&lt;/a&gt; over &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Shrine&quot;&gt;shrines&lt;/a&gt; since they may eat all your money.&lt;/p&gt;
 467&lt;p&gt;Completing the game on &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Difficulty&quot;&gt;Drizzle&lt;/a&gt; is really easy if you follow these tips.&lt;/p&gt;
 468&lt;h2 id=&quot;requisites&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#requisites&quot;&gt;¶&lt;/a&gt;Requisites&lt;/h2&gt;
 469&lt;p&gt;Before breaking the game, you must obtain several &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Item#Artifacts&quot;&gt;artifacts&lt;/a&gt;. We are interested in particular in the following:&lt;/p&gt;
 470&lt;ul&gt;
 471&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Sacrifice&quot;&gt;Sacrifice&lt;/a&gt;. You really need this one, and may be a bit hard to get. With it, you will be able to farm the first level for 30 minutes and kill the final boss in 30 seconds.&lt;/li&gt;
 472&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Command&quot;&gt;Command&lt;/a&gt;. You need this unless you want to grind for hours to get enough of the items you really need for the rest of the game. Getting this one is easy.&lt;/li&gt;
 473&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Glass&quot;&gt;Glass&lt;/a&gt;. Your life will be very small (at the beginning…), but you will be able to one-shot everything easily.&lt;/li&gt;
 474&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Kin&quot;&gt;Kin&lt;/a&gt; (optional). It makes it easier to obtain a lot of boxes if you restart the first level until you get &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Lemurian&quot;&gt;lemurians&lt;/a&gt; or &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Jellyfish&quot;&gt;jellyfish&lt;/a&gt; as the monster, since they're cheap to spawn.&lt;/li&gt;
 475&lt;/ul&gt;
 476&lt;p&gt;With those, the game becomes trivial. Playing as &lt;a href=&quot;http://riskofrain.wikia.com/wiki/Huntress&quot;&gt;Huntress&lt;/a&gt; is excellent since she can move at high speed while killing everything on screen.&lt;/p&gt;
 477&lt;h2 id=&quot;breaking_the_game&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#breaking_the_game&quot;&gt;¶&lt;/a&gt;Breaking the Game&lt;/h2&gt;
 478&lt;p&gt;The rest is easy! With the command artifact you want the following items.&lt;/p&gt;
 479&lt;h3 id=&quot;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Category:Common_Items&quot;&gt;common_items&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#common_items&quot;&gt;¶&lt;/a&gt;Common Items&lt;/a&gt;&lt;/h3&gt;
 480&lt;ul&gt;
 481&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Soldier&amp;#x27;s_Syringe&quot;&gt;Soldier's Syringe&lt;/a&gt;. &lt;strong&gt;Stack 13&lt;/strong&gt; of these and you will triple your attack speed. You can get started with 4 or so.&lt;/li&gt;
 482&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Paul&amp;#x27;s_Goat_Hoof&quot;&gt;Paul's Goat Hoof&lt;/a&gt;. &lt;strong&gt;Stack +30&lt;/strong&gt; of these and your movement speed will be insane. You can get a very good speed with 8 or so.&lt;/li&gt;
 483&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Crowbar&quot;&gt;Crowbar&lt;/a&gt;. &lt;strong&gt;Stack +20&lt;/strong&gt; to guarantee you can one-shot bosses.&lt;/li&gt;
 484&lt;/ul&gt;
 485&lt;p&gt;If you want to be safer:&lt;/p&gt;
 486&lt;ul&gt;
 487&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Hermit&amp;#x27;s_Scarf&quot;&gt;Hermit's Scarf&lt;/a&gt;. &lt;strong&gt;Stack 6&lt;/strong&gt; of these to dodge 1/3 of the attacks.&lt;/li&gt;
 488&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Monster_Tooth&quot;&gt;Monster Tooth&lt;/a&gt;. &lt;strong&gt;Stack 9&lt;/strong&gt; of these to recover 50 life on kill. This is plenty, since you will be killing &lt;em&gt;a lot&lt;/em&gt;.&lt;/li&gt;
 489&lt;/ul&gt;
 490&lt;p&gt;If you don't have enough and want more fun, get one of these:&lt;/p&gt;
 491&lt;ul&gt;
 492&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Gasoline&quot;&gt;Gasoline&lt;/a&gt;. Burn the ground on kill, and more will die!&lt;/li&gt;
 493&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Headstompers&quot;&gt;Headstompers&lt;/a&gt;. They make a pleasing sound on fall, and hurt.&lt;/li&gt;
 494&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Lens-Maker&amp;#x27;s_Glasses&quot;&gt;Lens-Maker's Glasses&lt;/a&gt;. &lt;strong&gt;Stack 14&lt;/strong&gt; and you will always deal a critical strike for double the damage.&lt;/li&gt;
 495&lt;/ul&gt;
 496&lt;h3 id=&quot;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Category:Uncommon_Items&quot;&gt;uncommon_items&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#uncommon_items&quot;&gt;¶&lt;/a&gt;Uncommon Items&lt;/a&gt;&lt;/h3&gt;
 497&lt;ul&gt;
 498&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Infusion&quot;&gt;Infusion&lt;/a&gt;. You only really need one of this. Your life will skyrocket after a while, since this gives you 1HP per kill.&lt;/li&gt;
 499&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Hopoo_Feather&quot;&gt;Hopoo Feather&lt;/a&gt;. &lt;strong&gt;Stack +10&lt;/strong&gt; of these. You will pretty much be able to fly with so many jumps.&lt;/li&gt;
 500&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Guardian&amp;#x27;s_Heart&quot;&gt;Guardian's Heart&lt;/a&gt;. Not really necessary, but useful for early and late game, since it will absorb infinite damage the first hit.&lt;/li&gt;
 501&lt;/ul&gt;
 502&lt;p&gt;If, again, you want more fun, get one of these:&lt;/p&gt;
 503&lt;ul&gt;
 504&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Ukulele&quot;&gt;Ukelele&lt;/a&gt;. Spazz your enemies!&lt;/li&gt;
 505&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Will-o&amp;#x27;-the-wisp&quot;&gt;Will-o'-the-wisp&lt;/a&gt;. Explode your enemies!&lt;/li&gt;
 506&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Chargefield_Generator&quot;&gt;Chargefield Generator&lt;/a&gt;. It should cover your entire screen after a bit, hurting all enemies without moving a finger.&lt;/li&gt;
 507&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Golden_Gun&quot;&gt;Golden Gun&lt;/a&gt;. You will be rich, so this gives you +40% damage.&lt;/li&gt;
 508&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Predatory_Instincts&quot;&gt;Predatory Instincts&lt;/a&gt;. If you got 14 glasses, you will always be doing critical strikes, and this will give even more attack speed.&lt;/li&gt;
 509&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/56_Leaf_Clover&quot;&gt;56 Leaf Clover&lt;/a&gt;. More drops, in case you didn't have enough.&lt;/li&gt;
 510&lt;/ul&gt;
 511&lt;h3 id=&quot;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Category:Rare_Items&quot;&gt;rare_items&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#rare_items&quot;&gt;¶&lt;/a&gt;Rare Items&lt;/a&gt;&lt;/h3&gt;
 512&lt;ul&gt;
 513&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Ceremonial_Dagger&quot;&gt;Ceremonial Dagger&lt;/a&gt;. &lt;strong&gt;Stack +3&lt;/strong&gt;, then killing one thing kills another thing and makes a chain reaction.&lt;/li&gt;
 514&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Alien_Head&quot;&gt;Alien Head&lt;/a&gt;. &lt;strong&gt;Stack 3&lt;/strong&gt;, and you will be able to use your abilities more often.&lt;/li&gt;
 515&lt;/ul&gt;
 516&lt;p&gt;For more fun:&lt;/p&gt;
 517&lt;ul&gt;
 518&lt;li&gt;&lt;a href=&quot;http://riskofrain.wikia.com/wiki/Brilliant_Behemoth&quot;&gt;Brilliant Behemoth&lt;/a&gt;. Boom boom.&lt;/li&gt;
 519&lt;/ul&gt;
 520&lt;h2 id=&quot;closing_words&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#closing_words&quot;&gt;¶&lt;/a&gt;Closing Words&lt;/h2&gt;
 521&lt;p&gt;You can now beat the game in Monsoon solo with any character. Have fun! And be careful with the sadly common crashes.&lt;/p&gt;
 522&lt;/main&gt;
 523&lt;/body&gt;
 524&lt;/html&gt;
 525 </content></entry><entry><title>My new computer</title><id>dist/new-computer/index.html</id><updated>2020-06-21T22:00:00+00:00</updated><published>2020-06-18T22:00:00+00:00</published><summary>This post will be mostly me ranting about setting up a new laptop, but I also just want to share my upgrade. If you're considering installing Arch Linux with dual-boot for Windows, maybe this post will help. Or perhaps you will learn something new to troubleshoot systems in the future. Let's begin!</summary><content type="html" src="dist/new-computer/index.html">&lt;!DOCTYPE html&gt;
 526&lt;html&gt;
 527&lt;head&gt;
 528&lt;meta charset=&quot;utf-8&quot; /&gt;
 529&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 530&lt;title&gt;My new computer&lt;/title&gt;
 531&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 532&lt;/head&gt;
 533&lt;body&gt;
 534&lt;main&gt;
 535&lt;h1 class=&quot;title&quot; id=&quot;my_new_computer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#my_new_computer&quot;&gt;¶&lt;/a&gt;My new computer&lt;/h1&gt;
 536&lt;div class=&quot;date-created-modified&quot;&gt;Created 2020-06-19&lt;br&gt;
 537Modified 2020-06-22&lt;/div&gt;
 538&lt;p&gt;This post will be mostly me ranting about setting up a new laptop, but I also just want to share my upgrade. If you're considering installing Arch Linux with dual-boot for Windows, maybe this post will help. Or perhaps you will learn something new to troubleshoot systems in the future. Let's begin!&lt;/p&gt;
 539&lt;p&gt;Last Sunday, I ordered a Asus Rog Strix G531GT-BQ165 for 900€ (on a 20% discount) with the following specifications:&lt;/p&gt;
 540&lt;ul&gt;
 541&lt;li&gt;Intel® Core i7-9750H (6 cores, 12MB cache, 2.6GHz up to 4.5GHz, 64-bit)&lt;/li&gt;
 542&lt;li&gt;16GB RAM (8GB*2) DDR4 2666MHz&lt;/li&gt;
 543&lt;li&gt;512GB SSD M.2 PCIe® NVMe&lt;/li&gt;
 544&lt;li&gt;Display 15.6&amp;quot; (1920x1080/16:9) 60Hz&lt;/li&gt;
 545&lt;li&gt;Graphics NVIDIA® GeForce® GTX1650 4GB GDDR5 VRAM&lt;/li&gt;
 546&lt;li&gt;LAN 10/100/1000&lt;/li&gt;
 547&lt;li&gt;Wi-Fi 5 (802.11ac) 2x2 RangeBoost&lt;/li&gt;
 548&lt;li&gt;Bluetooth 5.0&lt;/li&gt;
 549&lt;li&gt;48Wh battery with 3 cells&lt;/li&gt;
 550&lt;li&gt;3 x USB 3.1 (GEN1)&lt;/li&gt;
 551&lt;/ul&gt;
 552&lt;p&gt;I was mostly interested in a general upgrade (better processor, disk, more RAM), although the graphics card is a really nice addition which will allow me to take some time off on more games. After using it for a bit, I really love the feel of the keyboard, and I love the lack of numpad! (No sarcasm, I really don't like numpads.)&lt;/p&gt;
 553&lt;p&gt;This is an upgrade from my previous laptop (Asus X554LA-XX822T), which I won in a competition before entering university in a programming challenge. It has served me really well for the past five years, and had the following specifications:&lt;/p&gt;
 554&lt;ul&gt;
 555&lt;li&gt;Intel® Core™ i5-5200U&lt;/li&gt;
 556&lt;li&gt;4GB RAM DDR3L 1600MHz (which I upgraded to have 8GB)&lt;/li&gt;
 557&lt;li&gt;1TB HDD&lt;/li&gt;
 558&lt;li&gt;Display 15.6&amp;quot; (1366x768/16:9)&lt;/li&gt;
 559&lt;li&gt;Intel® HD Graphics 4400&lt;/li&gt;
 560&lt;li&gt;LAN 10/100/1000&lt;/li&gt;
 561&lt;li&gt;Wifi 802.11 bgn&lt;/li&gt;
 562&lt;li&gt;Bluetooth 4.0&lt;/li&gt;
 563&lt;li&gt;Battery 2 cells&lt;/li&gt;
 564&lt;li&gt;1 x USB 2.0&lt;/li&gt;
 565&lt;li&gt;2 x USB 3.0&lt;/li&gt;
 566&lt;/ul&gt;
 567&lt;p&gt;Prior to this one, I had a Lenovo (also won in the same competition of the previous year), and prior to that (just for the sake of history), it was HP Pavilion, AMD A4-3300M processor, which unfortunately ended with heating problems. But that's very old now.&lt;/p&gt;
 568&lt;h2 id=&quot;laptop_arrival&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#laptop_arrival&quot;&gt;¶&lt;/a&gt;Laptop arrival&lt;/h2&gt;
 569&lt;p&gt;The laptop arrived 2 days ago at roughly 19:00, which I put charged for 3 hours as the book said. The day after, nightmares began!&lt;/p&gt;
 570&lt;p&gt;Trying to boot it the first two times was fun, as it comes with a somewhat loud sound on boot. I don't know why they would do this, and I immediately turned it off in the BIOS.&lt;/p&gt;
 571&lt;h2 id=&quot;installation_journey&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#installation_journey&quot;&gt;¶&lt;/a&gt;Installation journey&lt;/h2&gt;
 572&lt;p&gt;I spent all of yesterday trying to setup Windows and Arch Linux (and didn't even finish, it took me this morning too and even now it's only half functional). I absolutely &lt;em&gt;hate&lt;/em&gt; the amount of partitions the Windows installer creates on a clean disk. So instead, I first went with Arch Linux, and followed the &lt;a href=&quot;https://wiki.archlinux.org/index.php/Installation_guide&quot;&gt;installation guide on the Arch wiki&lt;/a&gt;. Pre-installation, setting up the wireless network, creating the partitions and formatting them went all good. I decided to avoid GRUB at first and go with rEFInd, but alas I missed a big warning on the wiki and after reboot (I would later find out) it was not mounting root properly, so all I had was whatever was in the Initramfs. Reboot didn't work, so I had to hold the power button.&lt;/p&gt;
 573&lt;p&gt;Anyway, once the partitions were created, I went to install Windows (there was a lot of back and forth burning different &lt;code&gt;.iso&lt;/code&gt; images on the USB, which was a bit annoying because it wasn't the fastest thing in the world). This was pretty painless, and the process was standard: select advanced to let me choose the right partition, pick the one, say &amp;quot;no&amp;quot; to everything in the services setup, and done. But this was the first Windows &lt;code&gt;.iso&lt;/code&gt; I tried. It was an old revision, and the drivers were causing issues when running (something weird about their &lt;code&gt;.dll&lt;/code&gt;, manually installing the &lt;code&gt;.ini&lt;/code&gt; driver files seemed to work?). The Nvidia drivers didn't want to be installed on such an old revision, after updating everything I could via Windows updates. So back I went to burning a newer Windows &lt;code&gt;.iso&lt;/code&gt; and going through the same process again…&lt;/p&gt;
 574&lt;p&gt;Once Windows was ready and I verified that I could boot to it correctly, it was time to have a second go at Arch Linux. And I went through the setup at least three times, getting it wrong every single time, formatting root every single time, redownloading the packages every single pain. If only had I known earlier what the issue was!&lt;/p&gt;
 575&lt;p&gt;Why bother with Arch? I was pretty happy with Linux Mint, and I lowkey wanted to try NixOS, but I had used Arch before and it's a really nice distro overall (up-to-date, has AUR, quite minimal, imperative), except for trying to install rEFInd while chrooted…&lt;/p&gt;
 576&lt;p&gt;In the end I managed to get something half-working, I still need to properly configure WiFi and pulseaudio in my system but hey it works.&lt;/p&gt;
 577&lt;p&gt;I like to be able to dual-boot Windows and Linux because Linux is amazing for productivity, but unfortunately, some games only work fine on Windows. Might as well have both systems and use one for gaming, while the other is my daily driver.&lt;/p&gt;
 578&lt;h2 id=&quot;setting_up_arch_linux&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#setting_up_arch_linux&quot;&gt;¶&lt;/a&gt;Setting up Arch Linux&lt;/h2&gt;
 579&lt;p&gt;This is the process I followed to install Arch Linux in the end, along with a brief explanation on what I think the things are doing and why we are doing them. I think the wiki could do a better job at this, but I also know it's hard to get it right for everyone. Something I do dislike is the link colour, after opening a link it becomes gray and it's a lot easier to miss the fact that it is a link in the first place, which was tough when re-reading it because some links actually matter a lot. Furthermore, important information may just be a single line, also easy to skim over. Anyway, on to the installation process…&lt;/p&gt;
 580&lt;p&gt;The first thing we want to do is configure our keyboard layout or else the keys won't correspond to what we expect:&lt;/p&gt;
 581&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;loadkeys es
 582&lt;/code&gt;&lt;/pre&gt;
 583&lt;p&gt;Because we're on a recent system, we want to verify that UEFI works correctly. If we see files listed, then it works fine:&lt;/p&gt;
 584&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;ls /sys/firmware/efi/efivars
 585&lt;/code&gt;&lt;/pre&gt;
 586&lt;p&gt;The next thing we want to do is configure the WiFi, because I don't have any ethernet cable nearby. To do this, we check what network interfaces our laptop has (we're looking for the one prefixed with &amp;quot;w&amp;quot;, presumably for wireless, such as &amp;quot;wlan0&amp;quot; or &amp;quot;wlo1&amp;quot;), we set it up, scan for available wireless network, and finally connect. In my case, the network has WPA security so we rely on &lt;code&gt;wpa_supplicant&lt;/code&gt; to connect, passing the SSID (network name) and password:&lt;/p&gt;
 587&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;ip link
 588ip link set &amp;lt;IFACE&amp;gt; up
 589iw dev &amp;lt;IFACE&amp;gt; scan | less
 590wpa_supplicant -B -i &amp;lt;IFACE&amp;gt; -c &amp;lt;(wpa_passphrase &amp;lt;SSID&amp;gt; &amp;lt;PASS&amp;gt;)
 591&lt;/code&gt;&lt;/pre&gt;
 592&lt;p&gt;After that's done, pinging an IP address like &amp;quot;1.1.1.1&amp;quot; should Just Work™, but to be able to resolve hostnames, we need to also setup a nameserver. I'm using Cloudflare's, but you could use any other:&lt;/p&gt;
 593&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;echo nameserver 1.1.1.1 &amp;gt; /etc/resolv.conf
 594ping archlinux.org
 595^C
 596&lt;/code&gt;&lt;/pre&gt;
 597&lt;p&gt;If the ping works, then network works! If you still have issues, you may need to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Network_configuration#Static_IP_address&quot;&gt;manually configure a static IP address&lt;/a&gt; and add a route with the address of your, well, router. This basically shows if we have any address, adds a static address (so people know who we are), shows what route we have, and adds a default one (so our packets know where to go):&lt;/p&gt;
 598&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;ip address show
 599ip address add &amp;lt;YOUR ADDR&amp;gt;/24 broadcast + dev &amp;lt;IFACE&amp;gt;
 600ip route show
 601ip route add default via &amp;lt;ROUTER ADDR&amp;gt; dev &amp;lt;IFACE&amp;gt;
 602&lt;/code&gt;&lt;/pre&gt;
 603&lt;p&gt;Now that we have network available, we can enable NTP to synchronize our system time (this may be required for network operations where certificates have a validity period, not sure; in any case nobody wants a wrong system time):&lt;/p&gt;
 604&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;timedatectl set-ntp true
 605&lt;/code&gt;&lt;/pre&gt;
 606&lt;p&gt;After that, we can manage our disk and partitions using &lt;code&gt;fdisk&lt;/code&gt;. We want to define partitions to tell the system where it should live. To determine the disk name, we first list them, and then edit it. &lt;code&gt;fdisk&lt;/code&gt; is really nice and reminds you at every step that help can be accessed with &amp;quot;m&amp;quot;, which you should constantly use to guide you through.&lt;/p&gt;
 607&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;fdisk -l
 608fdisk /dev/&amp;lt;DISK&amp;gt;
 609&lt;/code&gt;&lt;/pre&gt;
 610&lt;p&gt;The partitions I made are the following:&lt;/p&gt;
 611&lt;ul&gt;
 612&lt;li&gt;A 100MB one for the EFI system.&lt;/li&gt;
 613&lt;li&gt;A 32GB one for Linux' root &lt;code&gt;/&lt;/code&gt; partition.&lt;/li&gt;
 614&lt;li&gt;A 200GB one for Linux' home &lt;code&gt;/home&lt;/code&gt; partition.&lt;/li&gt;
 615&lt;li&gt;The rest was unallocated for Windows because I did this first.&lt;/li&gt;
 616&lt;/ul&gt;
 617&lt;p&gt;I like to have &lt;code&gt;/home&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt; separate because I can reinstall root without losing anything from home (projects, music, photos, screenshots, videos…).&lt;/p&gt;
 618&lt;p&gt;After the partitions are made, we format them in FAT32 and EXT4 which are good defaults for EFI, root and home. They need to have a format, or else they won't be usable:&lt;/p&gt;
 619&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;mkfs.fat -F32 /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART1&amp;gt;
 620mkfs.ext4 /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART2&amp;gt;
 621mkfs.ext4 /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART3&amp;gt;
 622&lt;/code&gt;&lt;/pre&gt;
 623&lt;p&gt;Because the laptop was new, there was no risk to lose anything, but if you're doing a install on a previous system, be very careful with the partition names. Make sure they match with the ones in &lt;code&gt;fdisk -l&lt;/code&gt;.&lt;/p&gt;
 624&lt;p&gt;Now that we have usable partitions, we need to mount them or they won't be accessible. We can do this with &lt;code&gt;mount&lt;/code&gt;:&lt;/p&gt;
 625&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;mount /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART2&amp;gt; /mnt
 626mkdir /mnt/efi
 627mount /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART1&amp;gt; /mnt/efi
 628mkdir /mnt/home
 629mount /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART3&amp;gt; /mnt/home
 630&lt;/code&gt;&lt;/pre&gt;
 631&lt;p&gt;Remember to use the correct partitions while mounting. We mount everything so that the system knows which partitions we care about, which we will let know about later on.&lt;/p&gt;
 632&lt;p&gt;Next step is to setup the basic Arch Linux system on root, which can be done with &lt;code&gt;pacstrap&lt;/code&gt;. What follows the directory is a list of packages, and you may choose any you wish (at least add &lt;code&gt;base&lt;/code&gt;, &lt;code&gt;linux&lt;/code&gt; and &lt;code&gt;linux-firmware&lt;/code&gt;). These can be installed later, but I'd recommend having them from the beginning, just in case:&lt;/p&gt;
 633&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;pacstrap /mnt base linux linux-firmware sudo vim-minimal dhcpcd wpa_supplicant man-db man-pages intel-ucode grub efibootmgr os-prober ntfs-3g
 634&lt;/code&gt;&lt;/pre&gt;
 635&lt;p&gt;Because my system has an intel CPU, I also installed &lt;code&gt;intel-ucode&lt;/code&gt;.&lt;/p&gt;
 636&lt;p&gt;Next up is generating the &lt;code&gt;fstab&lt;/code&gt; file, which we tell to use UUIDs to be on the safe side through &lt;code&gt;-U&lt;/code&gt;. This file is important, because without it the system won't know what partitions exist and will happily only boot with the initramfs, without anything of what we just installed at root. Not knowing this made me restart the entire installation process a few times.&lt;/p&gt;
 637&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;genfstab -U /mnt &amp;gt;&amp;gt; /mnt/etc/fstab
 638&lt;/code&gt;&lt;/pre&gt;
 639&lt;p&gt;After that's done, we can change our root into our mount point and finish up configuration. We setup our timezone (so DST can be handled correctly if needed), synchronize the hardware clock (to persist the current time to the BIOS), uncomment our locales (exit &lt;code&gt;vim&lt;/code&gt; by pressing ESC, then type &lt;code&gt;:wq&lt;/code&gt; and press enter), generate locale files (which some applications need), configure language and keymap, update the hostname of our laptop and what indicate what &lt;code&gt;localhost&lt;/code&gt; means…&lt;/p&gt;
 640&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;ln -sf /usr/share/zoneinfo/&amp;lt;REGION&amp;gt;/&amp;lt;CITY&amp;gt; /etc/localtime
 641hwclock --systohc
 642vim /etc/locale.gen
 643locale-gen
 644echo LANG=es_ES.UTF-8 &amp;gt; /etc/locale.conf
 645echo KEYMAP=es &amp;gt; /etc/vconsole.conf
 646echo &amp;lt;HOST&amp;gt; /etc/hostname
 647cat &amp;lt;&amp;lt;EOF &amp;gt; /etc/hosts
 648127.0.0.1 localhost
 649::1 localhost
 650127.0.1.1 &amp;lt;HOST&amp;gt;.localdomain &amp;lt;HOST&amp;gt;
 651EOF
 652&lt;/code&gt;&lt;/pre&gt;
 653&lt;p&gt;Really, we could've done all of this later, and the same goes for setting root's password with &lt;code&gt;passwd&lt;/code&gt; or creating users (some of the groups you probably want are &lt;code&gt;power&lt;/code&gt; and &lt;code&gt;wheel&lt;/code&gt;).&lt;/p&gt;
 654&lt;p&gt;The important part here is installing GRUB (which also needed the &lt;code&gt;efibootmgr&lt;/code&gt; package):&lt;/p&gt;
 655&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB
 656&lt;/code&gt;&lt;/pre&gt;
 657&lt;p&gt;If we want GRUB to find our Windows install, we also need the &lt;code&gt;os-prober&lt;/code&gt; and &lt;code&gt;ntfs-3g&lt;/code&gt; packages that we installed earlier with &lt;code&gt;pacstrap&lt;/code&gt;, and with those we need to mount the Windows partition somewhere. It doesn't matter where. With that done, we can generate the GRUB configuration file which lists all the boot options:&lt;/p&gt;
 658&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;mkdir /windows
 659mount /dev/&amp;lt;DISK&amp;gt;&amp;lt;PART5&amp;gt; /windows
 660grub-mkconfig -o /boot/grub/grub.cfg
 661&lt;/code&gt;&lt;/pre&gt;
 662&lt;p&gt;(In my case, I installed Windows before completing the Arch install, which created an additional partition in between).&lt;/p&gt;
 663&lt;p&gt;With GRUB ready, we can exit the chroot and reboot the system, and if all went well, you should be greeted with a choice of operating system to use:&lt;/p&gt;
 664&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;exit
 665reboot
 666&lt;/code&gt;&lt;/pre&gt;
 667&lt;p&gt;If for some reason you need to find what mountpoints were active prior to rebooting (to &lt;code&gt;unmount&lt;/code&gt; them for example), you can use &lt;code&gt;findmnt&lt;/code&gt;.&lt;/p&gt;
 668&lt;p&gt;Before GRUB I tried rEFInd, which as I explained had issues with for missing a warning. Then I tried systemd-boot, which did not pick up Arch at first. That's where the several reinstalls come from, I didn't want to work with a half-worked system so I mostly redid the entire process quite a few times.&lt;/p&gt;
 669&lt;h2 id=&quot;migrating_to_the_new_laptop&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#migrating_to_the_new_laptop&quot;&gt;¶&lt;/a&gt;Migrating to the new laptop&lt;/h2&gt;
 670&lt;p&gt;I had a external disk formatted with NTFS. Of course, after moving every file I cared about from my previous Linux install caused all the permissions to reset. All my &lt;code&gt;.git&lt;/code&gt; repositories, dirty with file permission changes! This is going to take a while to fix, or maybe I should just &lt;code&gt;git config core.fileMode false&lt;/code&gt;. Here is a &lt;a href=&quot;https://stackoverflow.com/a/2083563&quot;&gt;lovely command&lt;/a&gt; to sort them out on a per-repository basis:&lt;/p&gt;
 671&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;git diff --summary | grep --color 'mode change 100644 =&amp;gt; 100755' | cut -d' ' -f7- | xargs -d'\n' chmod -x
 672&lt;/code&gt;&lt;/pre&gt;
 673&lt;p&gt;I never realized how much I had stored over the years, but it really was a lot. While moving things to the external disk, I tried to do some cleanup, such as removing some build artifacts which needlessly occupy space, or completely skipping all the binary application files. If I need those I will install them anyway. The process was mostly focused on finding all the projects and program data that I did care about, or even some game saves. Nothing too difficult, but definitely time consuming.&lt;/p&gt;
 674&lt;h2 id=&quot;tuning_arch&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tuning_arch&quot;&gt;¶&lt;/a&gt;Tuning Arch&lt;/h2&gt;
 675&lt;p&gt;Now that our system is ready, install &lt;code&gt;pacman-contrib&lt;/code&gt; to grab a copy of the &lt;code&gt;rankmirrors&lt;/code&gt; speed. It should help speed up the download of whatever packages you want to install, since it will help us &lt;a href=&quot;https://wiki.archlinux.org/index.php/Mirrors#List_by_speed&quot;&gt;rank the mirrors by download speed&lt;/a&gt;. Making a copy of the file is important, otherwise whenever you try to install something it will fail saying it can't find anything.&lt;/p&gt;
 676&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.backup
 677sed -i 's/^#Server/Server/' /etc/pacman.d/mirrorlist.backup
 678rankmirrors -n 6 /etc/pacman.d/mirrorlist.backup | tee /etc/pacman.d/mirrorlist
 679&lt;/code&gt;&lt;/pre&gt;
 680&lt;p&gt;This will take a while, but it should be well worth it. We're using &lt;code&gt;tee&lt;/code&gt; to see the progress as it goes.&lt;/p&gt;
 681&lt;p&gt;Some other packages I installed after I had a working system in no particular order:&lt;/p&gt;
 682&lt;ul&gt;
 683&lt;li&gt;&lt;code&gt;xfce4&lt;/code&gt; and &lt;code&gt;xorg-server&lt;/code&gt;. I just love the simplicity of XFCE.&lt;/li&gt;
 684&lt;li&gt;&lt;code&gt;xfce4-whiskermenu-plugin&lt;/code&gt;, a really nice start menu.&lt;/li&gt;
 685&lt;li&gt;&lt;code&gt;xfce4-pulseaudio-plugin&lt;/code&gt; and &lt;code&gt;pavucontrol&lt;/code&gt;, to quickly adjust the audio with my mouse.&lt;/li&gt;
 686&lt;li&gt;&lt;code&gt;xfce4-taskmanager&lt;/code&gt;, a GUI alternative I generally prefer to &lt;code&gt;htop&lt;/code&gt;.&lt;/li&gt;
 687&lt;li&gt;&lt;code&gt;pulseaudio&lt;/code&gt; and &lt;code&gt;pulseaudio-alsa&lt;/code&gt; to get nice integration with XFCE4 and audio mixing.&lt;/li&gt;
 688&lt;li&gt;&lt;code&gt;firefox&lt;/code&gt;, which comes with fonts too. A really good web browser.&lt;/li&gt;
 689&lt;li&gt;&lt;code&gt;git&lt;/code&gt;, to commit &lt;del&gt;crimes&lt;/del&gt; code.&lt;/li&gt;
 690&lt;li&gt;&lt;code&gt;code&lt;/code&gt;, a wonderful editor which I used to write this blog entry.&lt;/li&gt;
 691&lt;li&gt;&lt;code&gt;nano&lt;/code&gt;, so much nicer to write a simple commit message.&lt;/li&gt;
 692&lt;li&gt;&lt;code&gt;python&lt;/code&gt; and &lt;code&gt;python-pip&lt;/code&gt;, my favourite language to toy around ideas or use as a calculator.&lt;/li&gt;
 693&lt;li&gt;&lt;code&gt;telegram-desktop&lt;/code&gt;, for my needs on sharing memes.&lt;/li&gt;
 694&lt;li&gt;&lt;code&gt;cmus&lt;/code&gt;, a simple terminal music player.&lt;/li&gt;
 695&lt;li&gt;&lt;code&gt;openssh&lt;/code&gt;, to connect into any VPS I have access to.&lt;/li&gt;
 696&lt;li&gt;&lt;code&gt;base-devel&lt;/code&gt;, necessary to build most projects I'll find myself working with (or even compiling some projects Rust which I installed via &lt;code&gt;rustup&lt;/code&gt;).&lt;/li&gt;
 697&lt;li&gt;&lt;code&gt;flac&lt;/code&gt;, &lt;code&gt;libmad&lt;/code&gt;, &lt;code&gt;opus&lt;/code&gt;, and &lt;code&gt;libvorbis&lt;/code&gt;, to be able to play more audio files.&lt;/li&gt;
 698&lt;li&gt;&lt;code&gt;inkscape&lt;/code&gt;, to make random drawings.&lt;/li&gt;
 699&lt;li&gt;&lt;code&gt;ffmpeg&lt;/code&gt;, to convert media or record screen.&lt;/li&gt;
 700&lt;li&gt;&lt;code&gt;xclip&lt;/code&gt;, to automatically copy screenshots to my clipboard.&lt;/li&gt;
 701&lt;li&gt;&lt;code&gt;gvfs&lt;/code&gt;, needed by Thunar to handle mounting and having a trash (perma-deletion by default can be nasty sometimes).&lt;/li&gt;
 702&lt;li&gt;&lt;code&gt;noto-fonts&lt;/code&gt;, &lt;code&gt;noto-fonts-cjk&lt;/code&gt; and &lt;code&gt;noto-fonts-extra&lt;/code&gt;, if you don't want missing gliphs everywhere.&lt;/li&gt;
 703&lt;li&gt;&lt;code&gt;xfce4-notifyd&lt;/code&gt; and &lt;code&gt;libnotify&lt;/code&gt;, for notifications.&lt;/li&gt;
 704&lt;li&gt;&lt;code&gt;cronie&lt;/code&gt;, to be able to &lt;code&gt;crontab -e&lt;/code&gt;. Make sure to &lt;code&gt;system enable cronie&lt;/code&gt;.&lt;/li&gt;
 705&lt;/ul&gt;
 706&lt;p&gt;After that, I configured my Super L key to launch &lt;code&gt;xfce4-popup-whiskermenu&lt;/code&gt; so that it opens the application menu, pretty much the same as it would on Windows, moved the panels around and configured them to my needs, and it feels like home once more.&lt;/p&gt;
 707&lt;p&gt;I made some mistakes while &lt;a href=&quot;https://wiki.archlinux.org/index.php/Systemd-networkd&quot;&gt;configuring systemd-networkd&lt;/a&gt; and accidentally added a service that was incorrect, which caused boot to wait for it to timeout before completing. My boot time was taking 90 seconds longer because of this! &lt;a href=&quot;https://www.reddit.com/r/archlinux/comments/4nv9yi/my_arch_greets_me_now_with_a_start_job/&quot;&gt;The solution was to remove said service&lt;/a&gt;, so this is something to look out for.&lt;/p&gt;
 708&lt;p&gt;In order to find what was taking long, I had to edit the &lt;a href=&quot;https://wiki.archlinux.org/index.php/kernel_parameters&quot;&gt;kernel parameters&lt;/a&gt; to remove the &lt;code&gt;quiet&lt;/code&gt; option. I prefer seeing the output on what my computer is doing anyway, because it gives me a sense of progress and most importantly is of great value when things go wrong. Another interesting option is &lt;code&gt;noauto,x-systemd.automount&lt;/code&gt;, which makes a disk lazily-mounted. If you have a slow disk, this could help speed things up.&lt;/p&gt;
 709&lt;p&gt;If you see a service taking long, you can also use &lt;code&gt;systemd-analyze blame&lt;/code&gt; to see what takes the longest, and &lt;code&gt;systemctl list-dependencies&lt;/code&gt; is also helpful to find what services are active.&lt;/p&gt;
 710&lt;p&gt;My &lt;code&gt;locale charmap&lt;/code&gt; was spitting out a bunch of warnings:&lt;/p&gt;
 711&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;$ locale charmap
 712locale: Cannot set LC_CTYPE to default locale: No such file or directory
 713locale: Cannot set LC_MESSAGES to default locale: No such file or directory
 714locale: Cannot set LC_ALL to default locale: No such file or directory
 715ANSI_X3.4-1968
 716&lt;/code&gt;&lt;/pre&gt;
 717&lt;p&gt;…ANSI encoding? Immediately I added the following to &lt;code&gt;~/.bashrc&lt;/code&gt; and &lt;code&gt;~/.profile&lt;/code&gt;:&lt;/p&gt;
 718&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;export LC_ALL=en_US.UTF-8
 719export LANG=en_US.UTF-8
 720export LANGUAGE=en_US.UTF-8
 721&lt;/code&gt;&lt;/pre&gt;
 722&lt;p&gt;For some reason, I also had to edit &lt;code&gt;xfce4-terminal&lt;/code&gt;'s preferences in advanced to change the default character encoding to UTF-8. This also solved my issues with pasting things into the terminal, and also proper rendering! I guess pastes were not working because it had some characters that could not be encoded.&lt;/p&gt;
 723&lt;p&gt;To have working notifications, I added the following to &lt;code&gt;~/.bash_profile&lt;/code&gt; after &lt;code&gt;exec startx&lt;/code&gt;:&lt;/p&gt;
 724&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;systemctl --user start xfce4-notifyd.service
 725&lt;/code&gt;&lt;/pre&gt;
 726&lt;p&gt;I'm pretty sure there's a better way to do this, or maybe it's not even necessary, but this works for me.&lt;/p&gt;
 727&lt;p&gt;Some of the other things I had left to do was setting up &lt;code&gt;sccache&lt;/code&gt; to speed up Rust builds:&lt;/p&gt;
 728&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;cargo install sccache
 729echo export RUSTC_WRAPPER=sccache &amp;gt;&amp;gt; ~/.bashrc
 730&lt;/code&gt;&lt;/pre&gt;
 731&lt;p&gt;Once I had &lt;code&gt;cargo&lt;/code&gt; ready, installed &lt;code&gt;hacksaw&lt;/code&gt; and &lt;code&gt;shotgun&lt;/code&gt; with it to perform screenshots.&lt;/p&gt;
 732&lt;p&gt;I also disabled the security delay when downloading files in Firefox because it's just annoying, in &lt;code&gt;about:config&lt;/code&gt; setting &lt;code&gt;security.dialog_enable_delay&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;
 733&lt;p&gt;The &lt;code&gt;utils-linux&lt;/code&gt; comes with a &lt;code&gt;fstrim&lt;/code&gt; utility to &lt;a href=&quot;https://wiki.archlinux.org/index.php/Solid_state_drive#Periodic_TRIM&quot;&gt;trim the SSD weekly&lt;/a&gt;, which I want enabled via &lt;code&gt;systemctl enable fstrim.timer&lt;/code&gt; (you may also want to &lt;code&gt;start&lt;/code&gt; it if you don't reboot often). For more SSD tips, check &lt;a href=&quot;https://easylinuxtipsproject.blogspot.com/p/ssd.html&quot;&gt;How to optimize your Solid State Drive&lt;/a&gt;.&lt;/p&gt;
 734&lt;p&gt;If the sound is funky prior to reboot, try &lt;code&gt;pulseaudio --kill&lt;/code&gt; and &lt;code&gt;pulseaudio --start&lt;/code&gt;, or delete &lt;code&gt;~/.config/pulse&lt;/code&gt;.&lt;/p&gt;
 735&lt;h2 id=&quot;tuning_windows&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tuning_windows&quot;&gt;¶&lt;/a&gt;Tuning Windows&lt;/h2&gt;
 736&lt;p&gt;On the Windows side, I disabled the annoying Windows defender by running (&lt;kbd&gt;Ctrl+R&lt;/kbd&gt;) &lt;code&gt;gpedit.msc&lt;/code&gt; and editing:&lt;/p&gt;
 737&lt;ul&gt;
 738&lt;li&gt;&lt;em&gt;Computer Configuration &amp;gt; Administrative Templates &amp;gt; Windows Components &amp;gt; Windows Defender » Turn off Windows Defender » Enable&lt;/em&gt;&lt;/li&gt;
 739&lt;li&gt;&lt;em&gt;User Configuration &amp;gt; Administrative Templates &amp;gt; Start Menu and Taskbar » Remove Notifications and Action Center » Enable&lt;/em&gt;&lt;/li&gt;
 740&lt;/ul&gt;
 741&lt;p&gt;I also updated the &lt;a href=&quot;https://github.com/WindowsLies/BlockWindows/raw/master/hosts&quot;&gt;&lt;code&gt;hosts&lt;/code&gt; file&lt;/a&gt; (located at &lt;code&gt;%windir%\system32\Drivers\etc\hosts&lt;/code&gt;) with the hope that it will stop some of the telemetry.&lt;/p&gt;
 742&lt;p&gt;All this time, my laptop had the keyboard lights on, which have been quite annoying. Apparently, they also can cause &lt;a href=&quot;https://www.reddit.com/r/ValveIndex/comments/cm6pos/psa_uninstalldisable_aura_sync_lighting_if_you/&quot;&gt;massive FPS drops&lt;/a&gt;. I headed over to &lt;a href=&quot;https://rog.asus.com/downloads/&quot;&gt;Asus Rog downloads&lt;/a&gt;, selected Aura Sync…&lt;/p&gt;
 743&lt;pre&gt;&lt;code class=&quot;language-md&quot;&gt;# Not Found
 744
 745The requested URL /campaign/aura/us/Sync.html was not found on this server.
 746
 747Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
 748&lt;/code&gt;&lt;/pre&gt;
 749&lt;p&gt;…great! I'll just find the &lt;a href=&quot;https://www.asus.com/campaign/aura/global/&quot;&gt;Aura site&lt;/a&gt; somewhere else…&lt;/p&gt;
 750&lt;pre&gt;&lt;code class=&quot;language-md&quot;&gt;# ASUS
 751
 752# We'll be back.
 753
 754Hi, our website is temporarily closed for service enhancements.
 755
 756We'll be back shortly.Thank you for your patience!
 757&lt;/code&gt;&lt;/pre&gt;
 758&lt;p&gt;Oh come on. After waiting for the next day, I headed over, downloaded their software, tried to install it and it was an awful experience. It felt like I was purposedly installing malware. It spammed and flashed a lot of &lt;code&gt;cmd&lt;/code&gt;'s on screen as if it was a virus. It was stuck at 100% doing that and then, Windows blue-screened with &lt;code&gt;KERNEL_MODE_HEAP_CORRUPTION&lt;/code&gt;. Amazing. How do you screw up this bad?&lt;/p&gt;
 759&lt;p&gt;Well, at least rebooting worked. I tried to &lt;a href=&quot;https://answers.microsoft.com/en-us/windows/forum/all/unable-to-uninstall-asus-aura-sync-utility/e9bec36c-e62f-4773-80be-88fb68dace16&quot;&gt;uninstall Aura, but of course that failed&lt;/a&gt;. Using the &lt;a href=&quot;https://support.microsoft.com/en-us/help/17588/windows-fix-problems-that-block-programs-being-installed-or-removed&quot;&gt;troubleshooter to uninstall programs&lt;/a&gt; helped me remove most of the crap that was installed.&lt;/p&gt;
 760&lt;p&gt;After searching around how to disable the lights (because &lt;a href=&quot;https://rog.asus.com/forum/showthread.php?112786-Option-to-Disable-Aura-Lights-on-Strix-G-series-(G531GT)-irrespective-of-OSes&quot;&gt;my BIOS did not have this setting&lt;/a&gt;), I stumbled upon &lt;a href=&quot;https://rog.asus.com/us/innovation/armoury_crate/&quot;&gt;&amp;quot;Armoury Crate&amp;quot;&lt;/a&gt;. Okay, fine, I will install that.&lt;/p&gt;
 761&lt;p&gt;The experience wasn't much better. It did the same thing with a lot of consoles flashing on screen. And of course, it resulted in another blue-screen, this time &lt;code&gt;KERNEL_SECURITY_CHECK_FAILURE&lt;/code&gt;. To finish up, the BSOD kept happening as I rebooted the system. Time to reinstall Windows once more.&lt;/p&gt;
 762&lt;p&gt;Asus software might be good, but the software is utter crap.&lt;/p&gt;
 763&lt;p&gt;After trying out &lt;a href=&quot;https://github.com/wroberts/rogauracore&quot;&gt;rogauracore&lt;/a&gt; (which didn't list my model), it worked! I could disable the stupid lights from Linux, and &lt;a href=&quot;https://gitlab.com/CalcProgrammer1/OpenRGB/-/wikis/home&quot;&gt;OpenRGB&lt;/a&gt; also works on Windows which may be worth checking out too.&lt;/p&gt;
 764&lt;p&gt;Because &lt;code&gt;rougauracore&lt;/code&gt; helped me and they linked to &lt;a href=&quot;https://github.com/linuxhw/hw-probe/blob/master/README.md#appimage&quot;&gt;hw-probe&lt;/a&gt;, I decided to &lt;a href=&quot;https://linux-hardware.org/?probe=0e3e48c501&quot;&gt;run it on my system&lt;/a&gt;, with the hopes it is useful for other people.&lt;/p&gt;
 765&lt;h2 id=&quot;closing_words&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#closing_words&quot;&gt;¶&lt;/a&gt;Closing words&lt;/h2&gt;
 766&lt;p&gt;I hope the installation journey is at least useful to someone, or that you enjoyed reading about it all. If not, sorry!&lt;/p&gt;
 767&lt;/main&gt;
 768&lt;/body&gt;
 769&lt;/html&gt;
 770 </content></entry><entry><title>Tips for Outpost</title><id>dist/tips-outpost/index.html</id><updated>2020-05-21T22:00:00+00:00</updated><published>2020-05-09T22:00:00+00:00</published><summary>Outpost</summary><content type="html" src="dist/tips-outpost/index.html">&lt;!DOCTYPE html&gt;
 771&lt;html&gt;
 772&lt;head&gt;
 773&lt;meta charset=&quot;utf-8&quot; /&gt;
 774&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 775&lt;title&gt;Tips for Outpost&lt;/title&gt;
 776&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 777&lt;/head&gt;
 778&lt;body&gt;
 779&lt;main&gt;
 780&lt;h1 class=&quot;title&quot; id=&quot;tips_for_outpost&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tips_for_outpost&quot;&gt;¶&lt;/a&gt;Tips for Outpost&lt;/h1&gt;
 781&lt;div class=&quot;date-created-modified&quot;&gt;Created 2020-05-10&lt;br&gt;
 782Modified 2020-05-22&lt;/div&gt;
 783&lt;p&gt;&lt;a href=&quot;https://store.steampowered.com/app/1127110/Outpost/&quot;&gt;Outpost&lt;/a&gt; is a fun little game by Open Mid Interactive that has popped in recently in my recommended section of Steam, and I decided to give it a try.&lt;/p&gt;
 784&lt;p&gt;It's a fun tower-defense game with progression, different graphics and random world generation which makes it quite fun for a few hours. In this post I want to talk about some tips I found useful to get past night 50.&lt;/p&gt;
 785&lt;h2 id=&quot;build_pattern&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#build_pattern&quot;&gt;¶&lt;/a&gt;Build Pattern&lt;/h2&gt;
 786&lt;p&gt;At first, you may be inclined to design a checkerboard pattern like the following, where &amp;quot;C&amp;quot; is the Crystal shrine, &amp;quot;S&amp;quot; is a stone launcher and &amp;quot;B&amp;quot; is a booster:&lt;/p&gt;
 787&lt;div class=&quot;image-container&quot;&gt;
 788&lt;img src=&quot;outpost-bad-pattern.svg&quot; alt=&quot;Bad Outpost build pattern&quot; /&gt;
 789&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
 790&lt;/div&gt;
 791&lt;p&gt;
 792&lt;p&gt;Indeed, this pattern will apply &lt;strong&gt;4&lt;/strong&gt; boosts to every turret, but unfortunately, the other 4 slots of the booster are wasted! This is because boosters are able to power 8 different towers, and you really want to maximize that. Here's a better design:&lt;/p&gt;
 793&lt;div class=&quot;image-container&quot;&gt;
 794&lt;img src=&quot;outpost-good-pattern.svg&quot; alt=&quot;Good Outpost build pattern&quot; /&gt;
 795&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
 796&lt;/div&gt;
 797&lt;p&gt;
 798&lt;p&gt;The shrine's tower does get boosted, but it's still not really worth it to boost it. This pattern works good, and it's really easy to tile: just repeat the same 3x3 pattern.&lt;/p&gt;
 799&lt;p&gt;Nonetheless, we can do better. What if we applied multiple boosters to the same tower while still applying all 8 boosts?&lt;/p&gt;
 800&lt;div class=&quot;image-container&quot;&gt;
 801&lt;img src=&quot;outpost-best-pattern.svg&quot; alt=&quot;Best Outpost build pattern&quot; /&gt;
 802&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
 803&lt;/div&gt;
 804&lt;p&gt;
 805&lt;p&gt;That's what peak performance looks like. You can actually apply multiple boosters to the same tower, and it works great.&lt;/p&gt;
 806&lt;p&gt;Now, is it really worth it building anywhere except around the shrine? Not really. You never know where a boss will come from, so all sides need a lot of defense if you want to stand a chance.&lt;/p&gt;
 807&lt;p&gt;The addition of traps in 1.6 is amazing. You want to build these outside your strong &amp;quot;core&amp;quot;, mostly to slow the enemies down so your turrets have more time to finish them off. Don't waste boosters on the traps, and build them at a reasonable distance from the center (the sixth tile is a good spot):&lt;/p&gt;
 808&lt;div class=&quot;image-container&quot;&gt;
 809&lt;img src=&quot;outpost-trap-pattern.svg&quot; alt=&quot;Trap Outpost build pattern&quot; /&gt;
 810&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
 811&lt;/div&gt;
 812&lt;p&gt;
 813&lt;p&gt;If you gather enough materials, you can build more trap and cannon layers outside, roughly at enough distance to slow them for enough duration until they reach the next layer of traps, and so on. Probably a single gap of &amp;quot;cannon, booster, cannon&amp;quot; is enough between trap layers, just not in the center where you need a lot of fire power.&lt;/p&gt;
 814&lt;h2 id=&quot;talents&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#talents&quot;&gt;¶&lt;/a&gt;Talents&lt;/h2&gt;
 815&lt;p&gt;Talents are the way progression works in the game. Generally, after a run, you will have enough experience to upgrade nearly all talents of roughly the same tier. However, some are worth upgrading more than others (which provide basically no value).&lt;/p&gt;
 816&lt;p&gt;The best ones to upgrade are:&lt;/p&gt;
 817&lt;ul&gt;
 818&lt;li&gt;Starting supplies. Amazing to get good tools early.&lt;/li&gt;
 819&lt;li&gt;Shrine shield. Very useful to hold against tough bosses.&lt;/li&gt;
 820&lt;li&gt;Better buildings (cannon, boosters, bed and traps). They're a must to deal the most damage.&lt;/li&gt;
 821&lt;li&gt;Better pickaxe. Stone is limited, so better make good use of it.&lt;/li&gt;
 822&lt;li&gt;Better chests. They provide an insane amount of resources early.&lt;/li&gt;
 823&lt;li&gt;Winter slow. Turrets will have more time to deal damage, it's perfect.&lt;/li&gt;
 824&lt;li&gt;More time. Useful if you're running out, although generally you enter nights early after having a good core anyway.&lt;/li&gt;
 825&lt;li&gt;More rocks. Similar to a better pickaxe, more stone is always better.&lt;/li&gt;
 826&lt;/ul&gt;
 827&lt;p&gt;Some decent ones:&lt;/p&gt;
 828&lt;ul&gt;
 829&lt;li&gt;In-shrine turret. It's okay to get past the first night without building but not much beyond that.&lt;/li&gt;
 830&lt;li&gt;Better axe and greaves. Great to save some energy and really nice quality of life to move around.&lt;/li&gt;
 831&lt;li&gt;Tree growth. Normally there's enough trees for this not to be an issue but it can save some time gathering wood.&lt;/li&gt;
 832&lt;li&gt;Wisps. They're half-decent since they can provide materials once you max out or max out expensive gear.&lt;/li&gt;
 833&lt;/ul&gt;
 834&lt;p&gt;Some okay ones:&lt;/p&gt;
 835&lt;ul&gt;
 836&lt;li&gt;Extra XP while playing. Generally not needed due to the way XP scales per night, but can be a good boost.&lt;/li&gt;
 837&lt;li&gt;Runestones. Not as reliable as chests but some can grant more energy per day.&lt;/li&gt;
 838&lt;/ul&gt;
 839&lt;p&gt;Some crap ones:&lt;/p&gt;
 840&lt;ul&gt;
 841&lt;li&gt;Boosts for other seasons. I mean, winter is already the best, no use there.&lt;/li&gt;
 842&lt;li&gt;Bow. The bow is very useless at the moment, it's not worth your experience.&lt;/li&gt;
 843&lt;li&gt;More energy per bush. Not really worth hunting for bushes since you will have enough energy to do well.&lt;/li&gt;
 844&lt;/ul&gt;
 845&lt;h2 id=&quot;turrets&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#turrets&quot;&gt;¶&lt;/a&gt;Turrets&lt;/h2&gt;
 846&lt;p&gt;Always build the highest tier, there's no point in anything lower than that. You will need to deal a lot of damage in a small area, which means space is a premium.&lt;/p&gt;
 847&lt;h2 id=&quot;boosters&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#boosters&quot;&gt;¶&lt;/a&gt;Boosters&lt;/h2&gt;
 848&lt;p&gt;If you're very early in the game, I recommend alternating both the flag and torch in a checkerboard pattern where the boosters should go in the pattern above. This way your towers will get extra speed and extra range, which works great.&lt;/p&gt;
 849&lt;p&gt;When you're in mid-game (stone launchers, gears and campfires), I do not recommend using campfires. The issue is their range boost is way too long, and the turrets will miss quite a few shots. It's better to put all your power into fire speed for increased DPS, at least near the center. If you manage to build too far out and some of the turrets hardly ever shoot, you may put campfires there.&lt;/p&gt;
 850&lt;p&gt;In end-game, of course alternate both of the highest tier upgrades. They are really good, and provide the best benefit / cost ratio.&lt;/p&gt;
 851&lt;h2 id=&quot;gathering_materials&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#gathering_materials&quot;&gt;¶&lt;/a&gt;Gathering Materials&lt;/h2&gt;
 852&lt;p&gt;It is &lt;strong&gt;very&lt;/strong&gt; important to use all your energy every day! Otherwise it will go to waste, and you will need a lot of materials.&lt;/p&gt;
 853&lt;p&gt;As of 1.6, you can mine two things at once if they're close enough! I don't know if this is intended or a bug, but it sure is great.&lt;/p&gt;
 854&lt;p&gt;Once you're in mid-game, your stone-based fort should stand pretty well against the nights on its own. After playing for a while you will notice, if your base can defend a boss, then it will have no issue carrying you through the nights until the next boss. You can (and should!) spend the nights gathering materials, but only when you're confident that the night won't run out.&lt;/p&gt;
 855&lt;p&gt;Before the boss hits (every fifth night), come back to your base and use all of your materials. This is the next fort upgrade that will carry it the five next nights.&lt;/p&gt;
 856&lt;p&gt;You may also speed up time during night, but make sure you use all your energy before hand. And also take care, in the current version of the game speeding up time only speeds up monster movement, not the fire rate or projectile speed of your turrets! This means they will miss more shots and can be pretty dangerous. If you're speeding up time, consider speeding it up for a little bit, then go back to normal until things are more calm, and repeat.&lt;/p&gt;
 857&lt;p&gt;If you're in the end-game, try to rush for chests. They provide a huge amount of materials which is really helpful to upgrade all your tools early so you can make sure to get the most out of every rock left in the map.&lt;/p&gt;
 858&lt;p&gt;In the end-game, after all stone has been collected, you don't really need to use all of your energy anymore. Just enough to have enough wood to build with the remaining stone. This will also be nice with the bow upgrades, which admitedly can get quite powerful, but it's best to have a strong fort first.&lt;/p&gt;
 859&lt;h2 id=&quot;season&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#season&quot;&gt;¶&lt;/a&gt;Season&lt;/h2&gt;
 860&lt;p&gt;In my opinion, winter is just the best of the seasons. You don't &lt;em&gt;really&lt;/em&gt; need that much energy (it gets tiresome), or extra tree drops, or luck. Slower movement means your turrets will be able to shoot enemies for longer, dealing more damage over time, giving them more chance to take enemies out before they reach the shrine.&lt;/p&gt;
 861&lt;p&gt;Feel free to re-roll the map a few times (play and exit, or even restart the game) until you get winter if you want to go for The Play.&lt;/p&gt;
 862&lt;h2 id=&quot;gear&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#gear&quot;&gt;¶&lt;/a&gt;Gear&lt;/h2&gt;
 863&lt;p&gt;In my opinion, you really should rush for the best pickaxe you can afford. Stone is a limited resource that doesn't regrow like trees, so once you run out, it's over. Better to make the best use out of it with a good pickaxe!&lt;/p&gt;
 864&lt;p&gt;You may also upgrade your greaves, we all known faster movement is a &lt;em&gt;really&lt;/em&gt; nice quality of life improvement.&lt;/p&gt;
 865&lt;p&gt;Of course, you will eventually upgrade your axe to chop wood (otherwise it's wasted energy, really), but it's not as much of a priority as the pickaxe.&lt;/p&gt;
 866&lt;p&gt;Now, the bow is completely useless. Don't bother with it. Your energy is better spent gathering materials to build permanent turrets that deal constant damage while you're away, and the damage adds up with every extra turret you build.&lt;/p&gt;
 867&lt;p&gt;With regards to items you carry (like sword, or helmet), look for these (from best to worst):&lt;/p&gt;
 868&lt;ul&gt;
 869&lt;li&gt;Less minion life.&lt;/li&gt;
 870&lt;li&gt;Chance to not consume energy.&lt;/li&gt;
 871&lt;li&gt;+1 turret damage.&lt;/li&gt;
 872&lt;li&gt;Extra energy.&lt;/li&gt;
 873&lt;li&gt;+1 drop from trees or stones.&lt;/li&gt;
 874&lt;li&gt;+1 free wood or stone per day.&lt;/li&gt;
 875&lt;/ul&gt;
 876&lt;p&gt;Less minion life, nothing to say. You will need it near end-game.&lt;/p&gt;
 877&lt;p&gt;The chance to not consume energy is better the more energy you have. With a 25% chance not to consume energy, you can think of it as 1 extra energy for every 4 energy you have on average.&lt;/p&gt;
 878&lt;p&gt;Turret damage is a tough one, it's &lt;em&gt;amazing&lt;/em&gt; mid-game (it basically doubles your damage) but falls short once you unlock the cannon where you may prefer other items. Definitely recommended if you're getting started. You may even try to roll it on low tiers by dying on the second night, because it's that good.&lt;/p&gt;
 879&lt;p&gt;Extra energy is really good, because it means you can get more materials before it gets too rough. Make sure you have built at least two beds in the first night! This extra energy will pay of for the many nights to come.&lt;/p&gt;
 880&lt;p&gt;The problem with free wood or stone per day is that you have, often, five times as much energy per day. By this I mean you can get easily 5 stone every day, which means 5 extra stone, whereas the other would provide just 1 per night. On a good run, you will get around 50 free stone or 250 extra stone. It's a clear winner.&lt;/p&gt;
 881&lt;p&gt;In end-game, more quality of life are revealing chests so that you can rush them early, if you like to hunt for them try to make better use of the slot.&lt;/p&gt;
 882&lt;h2 id=&quot;closing_words&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#closing_words&quot;&gt;¶&lt;/a&gt;Closing words&lt;/h2&gt;
 883&lt;p&gt;I hope you enjoy the game as much as I do! Movement is sometimes janky and there's the occassional lag spikes, but despite this it should provide at least a few good hours of gameplay. Beware however a good run can take up to an hour!&lt;/p&gt;
 884&lt;/main&gt;
 885&lt;/body&gt;
 886&lt;/html&gt;
 887 </content></entry><entry><title>Installing NixOS, Take 2</title><id>dist/installing_nixos_2/index.html</id><updated>2019-02-15T23:00:00+00:00</updated><published>2019-02-14T23:00:00+00:00</published><summary>This is my second take at installing NixOS, after a while being frustrated with Arch Linux and the fact that a few kernel upgrades ago, the system crashed randomly from time to time. </summary><content type="html" src="dist/installing_nixos_2/index.html">&lt;!DOCTYPE html&gt;
 888&lt;html&gt;
 889&lt;head&gt;
 890&lt;meta charset=&quot;utf-8&quot; /&gt;
 891&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
 892&lt;title&gt;Installing NixOS, Take 2&lt;/title&gt;
 893&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
 894&lt;/head&gt;
 895&lt;body&gt;
 896&lt;main&gt;
 897&lt;h1 class=&quot;title&quot; id=&quot;installing_nixos_take_2&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#installing_nixos_take_2&quot;&gt;¶&lt;/a&gt;Installing NixOS, Take 2&lt;/h1&gt;
 898&lt;div class=&quot;date-created-modified&quot;&gt;Created 2019-02-15&lt;br&gt;
 899Modified 2019-02-16&lt;/div&gt;
 900&lt;p&gt;This is my second take at installing NixOS, after a while being frustrated with Arch Linux and the fact that a few kernel upgrades ago, the system crashed randomly from time to time. &lt;code&gt;journalctl&lt;/code&gt; did not have any helpful hints and I thought reinstalling could be worthwhile anyway.&lt;/p&gt;
 901&lt;p&gt;This time, I started with more knowledge! The first step is heading to the &lt;a href=&quot;https://nixos.org&quot;&gt;NixOS website&lt;/a&gt; and downloading their minimal installation CD for 64 bits. I didn't go with their graphical live CD, because their &lt;a href=&quot;https://nixos.org/nixos/manual&quot;&gt;installation manual&lt;/a&gt; is a wonderful resource that guides you nicely.&lt;/p&gt;
 902&lt;p&gt;Once you have downloaded their &lt;code&gt;.iso&lt;/code&gt;, you should probably verify it's &lt;code&gt;sha256sum&lt;/code&gt; and make sure that it matches. The easiest thing to do in my opinion is using an USB to burn the image in it. Plug it in and check its device name with &lt;code&gt;fdisk -l&lt;/code&gt;. In my case, it was &lt;code&gt;/dev/sdb&lt;/code&gt;, so I went ahead with it and ran &lt;code&gt;dd if=nixos.iso of=/dev/sdb status=progress&lt;/code&gt;. Make sure to run &lt;code&gt;sync&lt;/code&gt; once that's done.&lt;/p&gt;
 903&lt;p&gt;If either &lt;code&gt;dd&lt;/code&gt; or &lt;code&gt;sync&lt;/code&gt; seem &amp;quot;stuck&amp;quot; in the end, they are just flushing the changes to disk to make sure all is good. This is normal, and depends on your drives.&lt;/p&gt;
 904&lt;p&gt;Now, reboot your computer with the USB plugged in and make sure to boot into it. You should be welcome with a pretty screen. Just select the first option and wait until it logs you in as root. Once you're there you probably want to &lt;code&gt;loadkeys es&lt;/code&gt; or whatever your keyboard layout is, or you will have a hard time with passwords, since the characters are all over the place.&lt;/p&gt;
 905&lt;p&gt;In a clean disk, you would normally create the partitions now. In my case, I already had the partitions made (100MB for the EFI system, where &lt;code&gt;/boot&lt;/code&gt; lives, 40GB for the root &lt;code&gt;/&lt;/code&gt; partition with my old Linux installation, and 700G for &lt;code&gt;/home&lt;/code&gt;), so I didn't need to do anything here. The manual showcases &lt;code&gt;parted&lt;/code&gt;, but I personally use &lt;code&gt;fdisk&lt;/code&gt;, which has very helpful help I check every time I use it.&lt;/p&gt;
 906&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: The &lt;code&gt;XY&lt;/code&gt; in &lt;code&gt;/dev/sdXY&lt;/code&gt; is probably different in your system! Make sure you use &lt;code&gt;fdisk -l&lt;/code&gt; to see the correct letters and numbers!&lt;/p&gt;
 907&lt;p&gt;With the partitions ready in my UEFI system, I formatted both &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;/boot&lt;/code&gt; just to be safe with &lt;code&gt;mkfs.ext4 -L nixos /dev/sda2&lt;/code&gt; and &lt;code&gt;mkfs.fat -F 32 -n boot /dev/sda1&lt;/code&gt; (remember that these are the letters and numbers used in my partition scheme). Don't worry about the warning in the second command regarding lowercase letters and Windows. It's not really an issue.&lt;/p&gt;
 908&lt;p&gt;Now, since we gave each partition a label, we can easily mount them through &lt;code&gt;mount /dev/disk/by-label/nixos /mnt&lt;/code&gt; and, in UEFI systems, be sure to &lt;code&gt;mkdir -p /mnt/boot&lt;/code&gt; and &lt;code&gt;mount /dev/disk/by-label/boot /mnt/boot&lt;/code&gt;. I didn't bother setting up swap, since I have 8GB of RAM in my laptop and that's really enough for my use case.&lt;/p&gt;
 909&lt;p&gt;With that done, we will now ask the configuration wizard to do some work for us (in particular, generate a template) with &lt;code&gt;nixos-generate-config --root /mnt&lt;/code&gt;. This generates a very well documented file that we should edit right now (and this is important!) with whatever editor you prefer. I used &lt;code&gt;vim&lt;/code&gt;, but you can change it for &lt;code&gt;nano&lt;/code&gt; if you prefer.&lt;/p&gt;
 910&lt;p&gt;On to the configuration file, we need to enable a few things, so &lt;code&gt;vim /mnt/etc/nixos/configuration.nix&lt;/code&gt; and start scrolling down. We want to make sure to uncomment:&lt;/p&gt;
 911&lt;pre&gt;&lt;code&gt;# We really want network!
 912networking.wireless.enable = true;
 913
 914# This &amp;quot;fixes&amp;quot; the keyboard layout. Put the one you use.
 915i18n = {
 916consoleKeyMap = &amp;quot;es&amp;quot;;
 917}
 918
 919# Timezones are tricky so let's get this right.
 920time.timeZone = &amp;quot;Europe/Madrid&amp;quot;;
 921
 922# We *really* want some base packages installed, such as
 923# wpa_supplicant, or we won't have a way to connect to the
 924# network once we install...
 925environment.systemPackages = with pkgs; [
 926wpa_supplicant wget curl vim neovim cmus mpv firefox git tdesktop
 927];
 928
 929# Printing is useful, sure, enable CUPS
 930services.printing.enable = true;
 931
 932# We have speakers, let's make use of them.
 933sound.enable = true;
 934hardware.pulseaudio.enable = true;
 935
 936# We want the X11 windowing system enabled, in Spanish.
 937services.xserver.enable = true;
 938services.xserver.layout = &amp;quot;es&amp;quot;;
 939
 940# I want a desktop manager in my laptop.
 941# I personally prefer XFCE, but the manual shows plenty
 942# of other options, such as Plasma, i3 WM, or whatever.
 943services.xserver.desktopManager.xfce.enable = true;
 944services.xserver.desktopManager.default = &amp;quot;xfce&amp;quot;;
 945
 946# Touchpad is useful (although sometimes annoying) in a laptop
 947services.xserver.libinput.enable = true;
 948
 949# We don't want to do everything as root!
 950users.users.lonami = {
 951isNormalUser = true;
 952uid = 1000;
 953home = &amp;quot;/home/lonami&amp;quot;;
 954extraGroups = [ &amp;quot;wheel&amp;quot; &amp;quot;networkmanager&amp;quot; &amp;quot;audio&amp;quot; ];
 955};
 956&lt;/code&gt;&lt;/pre&gt;
 957&lt;p&gt;&lt;em&gt;(Fun fact, I overlooked the configuration file until I wrote this and hadn't noticed sound/pulseaudio was there. It wasn't hard to find online how to enable it though!)&lt;/em&gt;&lt;/p&gt;
 958&lt;p&gt;Now, let's modify &lt;code&gt;hardware-configuration.nix&lt;/code&gt;. But if you have &lt;code&gt;/home&lt;/code&gt; in a separate partition like me, you should run &lt;code&gt;blkid&lt;/code&gt; to figure out its UUID. To avoid typing it out myself, I just ran &lt;code&gt;blkid &amp;gt;&amp;gt; /mnt/etc/nixos/hardware-configuration.nix&lt;/code&gt; so that I could easily move it around with &lt;code&gt;vim&lt;/code&gt;:&lt;/p&gt;
 959&lt;pre&gt;&lt;code&gt;# (stuff...)
 960
 961fileSystems.&amp;quot;/home&amp;quot; =
 962{ device = &amp;quot;/dev/disk/by-uuid/d344c686-cae7-4dd3-840e-308eddf86608&amp;quot;;
 963fsType = &amp;quot;ext4&amp;quot;;
 964};
 965
 966# (more stuff...)
 967&lt;/code&gt;&lt;/pre&gt;
 968&lt;p&gt;Note that, obviously, you should put your own partition's UUID there. Modifying the configuration is where I think the current NixOS' manual should have made more emphasis, at this step of the installation. They do detail it below, but that was already too late in my first attempt. Anyway, you can boot from the USB and run &lt;code&gt;nixos-install&lt;/code&gt; as many times as you need until you get it working!&lt;/p&gt;
 969&lt;p&gt;But before installing, we need to configure the network since there are plenty of things to download. If you want to work from WiFi, you should first figure out the name of your network card with &lt;code&gt;ip link show&lt;/code&gt;. In my case it's called &lt;code&gt;wlp3s0&lt;/code&gt;. So with that knowledge we can run &lt;code&gt;wpa_supplicant -B -i wlp3s0 -c &amp;lt;(wpa_passphrase SSID key)&lt;/code&gt;. Be sure to replace both &lt;code&gt;SSID&lt;/code&gt; and &lt;code&gt;key&lt;/code&gt; with the name of your network and password key, respectively. If they have spaces, surround them in quotes.&lt;/p&gt;
 970&lt;p&gt;Another funny pitfall was typing &lt;code&gt;wpa_supplicant&lt;/code&gt; in the command above twice (instead of &lt;code&gt;wpa_passphrase&lt;/code&gt;). That sure spit out a few funny errors! Once you have ran that, wait a few seconds and &lt;code&gt;ping 1.1.1.1&lt;/code&gt; to make sure that you can reach the internet. If you do, &lt;code&gt;^C&lt;/code&gt; and let's install NixOS!&lt;/p&gt;
 971&lt;pre&gt;&lt;code&gt;nixos-install
 972&lt;/code&gt;&lt;/pre&gt;
 973&lt;p&gt;Well, that was pretty painless. You can now &lt;code&gt;reboot&lt;/code&gt; and enjoy your new, functional system.&lt;/p&gt;
 974&lt;h2 id=&quot;afterword&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#afterword&quot;&gt;¶&lt;/a&gt;Afterword&lt;/h2&gt;
 975&lt;p&gt;The process of installing NixOS was really painless once you have made sense out of what things mean. I was far more pleased this time than in my previous attempt, despite the four attempts I needed to have it up and running.&lt;/p&gt;
 976&lt;p&gt;However not all is so good. I'm not sure where I went wrong, but the first time I tried with &lt;code&gt;i3&lt;/code&gt; instead of &lt;code&gt;xfce&lt;/code&gt;, all I was welcome with was a white, small terminal in the top left corner. I even generated a configuration file with &lt;code&gt;i3-config-wizard&lt;/code&gt; to make sure it could detect my Mod1/Mod4 keys (which, it did), but even after rebooting, my commands weren't responding. For example, I couldn't manage to open another terminal with &lt;code&gt;Mod1+Enter&lt;/code&gt;. I'm not even sure that I was in &lt;code&gt;i3&lt;/code&gt;…&lt;/p&gt;
 977&lt;p&gt;In my very first attempt, I pressed &lt;code&gt;Alt+F8&lt;/code&gt; as suggested in the welcome message. This took me an offline copy of the manual, which is really nicely done. Funny enough, though, I couldn't exit &lt;code&gt;w3m&lt;/code&gt;. Both &lt;code&gt;Q&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; to quit and take me back wouldn't work. Somehow, it kept throwing me back into &lt;code&gt;w3m&lt;/code&gt;, so I had to forcibly shutdown.&lt;/p&gt;
 978&lt;p&gt;In my second attempt, I also forgot to configure network, so I had no way to download &lt;code&gt;wpa_supplicant&lt;/code&gt; without having &lt;code&gt;wpa_supplicant&lt;/code&gt; itself to connect my laptop to the network! So, it was important to do that through the USB before installing it (which comes with the program preinstalled), just by making sure to add it in the configuration file.&lt;/p&gt;
 979&lt;p&gt;Some other notes, if you can't reach the internet, don't add any DNS in &lt;code&gt;/etc/resolv.conf&lt;/code&gt;. This should be done declaratively in &lt;code&gt;configuration.nix&lt;/code&gt;.&lt;/p&gt;
 980&lt;p&gt;In the end, I spent the entire afternoon playing around with it, taking breaks and what-not. I still haven't figured out why &lt;code&gt;nvim&lt;/code&gt; was printing the literal escape character when going from normal to insert mode in the &lt;code&gt;xfce4-terminal&lt;/code&gt; (and other actions also made it print this &amp;quot;garbage&amp;quot; to the console), why sometimes the network can reach the internet (and only some sites!) and sometimes not, and how to setup dualboot.&lt;/p&gt;
 981&lt;p&gt;But despite all of this, I think it was a worth installing it again. One sure sees things from a different perspective, and gets the chance to write another blog post!&lt;/p&gt;
 982&lt;p&gt;If there's something I overlooked or that could be done better, or maybe you can explain it differently, please be sure to &lt;a href=&quot;https://lonami.dev/contact&quot;&gt;contact me&lt;/a&gt; to let me know!&lt;/p&gt;
 983&lt;h2 id=&quot;update&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update&quot;&gt;¶&lt;/a&gt;Update&lt;/h2&gt;
 984&lt;p&gt;Well, that was surprisingly fast feedback. Thank you very much &lt;a href=&quot;https://bb010g.keybase.pub/&quot;&gt;@bb010g&lt;/a&gt; for it! As they rightfully pointed out, one can avoid adding &lt;code&gt;/home&lt;/code&gt; manually to &lt;code&gt;hardware-configuration.nix&lt;/code&gt; if you mount it before generating the configuration files. However, the installation process doesn't need &lt;code&gt;/home&lt;/code&gt; mounted, so I didn't do it.&lt;/p&gt;
 985&lt;p&gt;The second weird issue with &lt;code&gt;w3m&lt;/code&gt; is actually a funny one. &lt;code&gt;Alt+F8&lt;/code&gt; &lt;em&gt;switches to another TTY&lt;/em&gt;! That's why quitting the program wouldn't do anything. You'd still be in a different TTY! Normally, this is &lt;code&gt;Ctrl+Alt+FX&lt;/code&gt;, so I hadn't even thought that this is what could be happening. Anyway, the solution is not quitting the program, but rather going back to the main TTY with &lt;code&gt;Alt+F1&lt;/code&gt;. You can switch back and forth all you need to consult the manual.&lt;/p&gt;
 986&lt;p&gt;More suggestions are having &lt;a href=&quot;https://github.com/rycee/home-manager&quot;&gt;&lt;code&gt;home-manager&lt;/code&gt;&lt;/a&gt; manage the graphical sessions, since it should be easier to deal with than the alternatives.&lt;/p&gt;
 987&lt;p&gt;Despite having followed the guide and having read it over and over several times, it seems like my thoughts in this blog post may be a bit messy. So I recommend you also reading through the guide to have two versions of all this, just in case.&lt;/p&gt;
 988&lt;p&gt;Regarding network issues, they use &lt;code&gt;connman&lt;/code&gt; so that may be worth checking out.&lt;/p&gt;
 989&lt;p&gt;Regarding terminal issues with &lt;code&gt;nvim&lt;/code&gt; printing the literal escape character, I was told off for not having checked what my &lt;code&gt;$TERM&lt;/code&gt; was. I hadn't really looked into it much myself, just complained about it here, so sorry for being annoying about that. A quick search in the &lt;code&gt;nixpkgs&lt;/code&gt; repository lets us find &lt;a href=&quot;https://github.com/NixOS/nixpkgs/blob/release-18.09/pkgs/applications/editors/neovim/default.nix&quot;&gt;neovim/default.nix&lt;/a&gt;, with version 0.3.1. Looking at &lt;a href=&quot;https://github.com/neovim/neovim&quot;&gt;Neovim's main repository&lt;/a&gt; we can see that this is a bit outdated, but that is fine.&lt;/p&gt;
 990&lt;p&gt;If only I had bothered to look at &lt;a href=&quot;https://github.com/neovim/neovim/wiki/FAQ#nvim-shows-weird-symbols-2-q-when-changing-modes&quot;&gt;Neovim's wiki&lt;/a&gt;, (which they found through &lt;a href=&quot;https://github.com/neovim/neovim/issues/7749&quot;&gt;Neovim's GitHub issues&lt;/a&gt;) I would've seen that some terminals just don't support the program properly. The solution is, of course, to use a different terminal emulator with better support or to disable the &lt;code&gt;guicursor&lt;/code&gt; in Neovim's config.&lt;/p&gt;
 991&lt;p&gt;This is a pretty good life lesson. 30 seconds of searching, maybe two minutes and a half for also checking XFCE issues, are often more than enough to troubleshoot your issues. The internet is a big place and more people have surely came across the problem before, so make sure to look online first. In my defense I'll say that it didn't bother me so much so I didn't bother looking for that soon either.&lt;/p&gt;
 992&lt;/main&gt;
 993&lt;/body&gt;
 994&lt;/html&gt;
 995 </content></entry><entry><title>Installing NixOS</title><id>dist/installing_nixos/index.html</id><updated>2019-02-15T23:00:00+00:00</updated><published>2017-05-12T22:00:00+00:00</published><summary>Please see </summary><content type="html" src="dist/installing_nixos/index.html">&lt;!DOCTYPE html&gt;
 996&lt;html&gt;
 997&lt;head&gt;
 998&lt;meta charset=&quot;utf-8&quot; /&gt;
 999&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1000&lt;title&gt;Installing NixOS&lt;/title&gt;
1001&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1002&lt;/head&gt;
1003&lt;body&gt;
1004&lt;main&gt;
1005&lt;h1 class=&quot;title&quot; id=&quot;installing_nixos&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#installing_nixos&quot;&gt;¶&lt;/a&gt;Installing NixOS&lt;/h1&gt;
1006&lt;div class=&quot;date-created-modified&quot;&gt;Created 2017-05-13&lt;br&gt;
1007Modified 2019-02-16&lt;/div&gt;
1008&lt;h2 id=&quot;update&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update&quot;&gt;¶&lt;/a&gt;Update&lt;/h2&gt;
1009&lt;p&gt;&lt;em&gt;Please see &lt;a href=&quot;../installing_nixos_2/index.html&quot;&gt;my followup post with NixOS&lt;/a&gt; for a far better experience with it&lt;/em&gt;&lt;/p&gt;
1010&lt;hr /&gt;
1011&lt;p&gt;Today I decided to install &lt;a href=&quot;http://nixos.org/&quot;&gt;NixOS&lt;/a&gt; as a recommendation, a purely functional Linux distribution, since &lt;a href=&quot;https://xubuntu.org/&quot;&gt;Xubuntu&lt;/a&gt; kept crashing. Here's my journey, and how I managed to install it from a terminal for the first time in my life. Steps aren't hard, but they may not seem obvious at first.&lt;/p&gt;
1012&lt;ul&gt;
1013&lt;li&gt;
1014&lt;p&gt;Grab the Live CD, burn it on a USB stick and boot. I recommend using &lt;a href=&quot;https://etcher.io/&quot;&gt;Etcher&lt;/a&gt;.&lt;/p&gt;
1015&lt;/li&gt;
1016&lt;li&gt;
1017&lt;p&gt;Type &lt;code&gt;systemctl start display-manager&lt;/code&gt; and wait.&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.1&quot;&gt;&lt;a href=&quot;#f.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
1018&lt;/li&gt;
1019&lt;li&gt;
1020&lt;p&gt;Open both the manual and the &lt;code&gt;konsole&lt;/code&gt;.&lt;/p&gt;
1021&lt;/li&gt;
1022&lt;li&gt;
1023&lt;p&gt;Connect to the network using the GUI.&lt;/p&gt;
1024&lt;/li&gt;
1025&lt;li&gt;
1026&lt;p&gt;Create the disk partitions by using &lt;code&gt;fdisk&lt;/code&gt;.&lt;/p&gt;
1027&lt;p&gt;You can list them with &lt;code&gt;fdisk -l&lt;/code&gt;, modify a certain drive with &lt;code&gt;fdisk /dev/sdX&lt;/code&gt; (for instance, &lt;code&gt;/dev/sda&lt;/code&gt;) and follow the instructions.&lt;/p&gt;
1028&lt;p&gt;To create the file system, use &lt;code&gt;mkfs.ext4 -L &amp;lt;label&amp;gt; /dev/sdXY&lt;/code&gt; and swap with &lt;code&gt;mkswap -L &amp;lt;label&amp;gt; /dev/sdXY&lt;/code&gt;.&lt;/p&gt;
1029&lt;p&gt;The EFI partition should be done with &lt;code&gt;mkfs.vfat&lt;/code&gt;.&lt;/p&gt;
1030&lt;/li&gt;
1031&lt;li&gt;
1032&lt;p&gt;Mount the target to &lt;code&gt;/mnt&lt;/code&gt; e.g. if the label was &lt;code&gt;nixos&lt;/code&gt;, &lt;code&gt;mount /dev/disk/by-label/nixos /mnt&lt;/code&gt;&lt;/p&gt;
1033&lt;/li&gt;
1034&lt;li&gt;
1035&lt;p&gt;&lt;code&gt;mkdir /mnt/boot&lt;/code&gt; and then mount your EFI partition to it.&lt;/p&gt;
1036&lt;/li&gt;
1037&lt;li&gt;
1038&lt;p&gt;Generate a configuration template with &lt;code&gt;nixos-generate-config --root /mnt&lt;/code&gt;, and modify it with &lt;code&gt;nano /etc/nixos/configuration.nix&lt;/code&gt;.&lt;/p&gt;
1039&lt;/li&gt;
1040&lt;li&gt;
1041&lt;p&gt;While modifying the configuration, make sure to add &lt;code&gt;boot.loader.grub.device = &amp;quot;/dev/sda&amp;quot;&lt;/code&gt;&lt;/p&gt;
1042&lt;/li&gt;
1043&lt;li&gt;
1044&lt;p&gt;More useful configuration things are:&lt;/p&gt;
1045&lt;ul&gt;
1046&lt;li&gt;Uncomment the whole &lt;code&gt;i18n&lt;/code&gt; block.&lt;/li&gt;
1047&lt;li&gt;Add some essential packages like &lt;code&gt;environment.systemPackages = with pkgs; [wget git firefox pulseaudio networkmanagerapplet];&lt;/code&gt;.&lt;/li&gt;
1048&lt;li&gt;If you want to use XFCE, add &lt;code&gt;services.xserver.desktopManager.xfce.enable = true;&lt;/code&gt;, otherwise, you don't need &lt;code&gt;networkmanagerapplet&lt;/code&gt; either. Make sure to add &lt;code&gt;networking.networkmanager.enable = true;&lt;/code&gt; too.&lt;/li&gt;
1049&lt;li&gt;Define some user for yourself (modify &lt;code&gt;guest&lt;/code&gt; name) and use a UID greater than 1000. Also, add yourself to &lt;code&gt;extraGroups = [&amp;quot;wheel&amp;quot; &amp;quot;networkmanager&amp;quot;];&lt;/code&gt; (the first to be able to &lt;code&gt;sudo&lt;/code&gt;, the second to use network related things).&lt;/li&gt;
1050&lt;/ul&gt;
1051&lt;/li&gt;
1052&lt;li&gt;
1053&lt;p&gt;Run &lt;code&gt;nixos-install&lt;/code&gt;. If you ever modify that file again, to add more packages for instance (this is how they're installed), run &lt;code&gt;nixos-rebuild switch&lt;/code&gt; (or use &lt;code&gt;test&lt;/code&gt; to test but don't boot to it, or &lt;code&gt;boot&lt;/code&gt; not to switch but to use on next boot.&lt;/p&gt;
1054&lt;/li&gt;
1055&lt;li&gt;
1056&lt;p&gt;&lt;code&gt;reboot&lt;/code&gt;.&lt;/p&gt;
1057&lt;/li&gt;
1058&lt;li&gt;
1059&lt;p&gt;Login as &lt;code&gt;root&lt;/code&gt;, and set a password for your user with &lt;code&gt;passwd &amp;lt;user&amp;gt;&lt;/code&gt;. Done!&lt;/p&gt;
1060&lt;/li&gt;
1061&lt;/ul&gt;
1062&lt;p&gt;I enjoyed the process of installing it, and it's really cool that it has versioning and is so clean to keep track of which packages you install. But not being able to run arbitrary binaries by default is something very limitting in my opinion, though they've done a good job.&lt;/p&gt;
1063&lt;p&gt;I'm now back to Xubuntu, with a fresh install.&lt;/p&gt;
1064&lt;h2 id=&quot;update_2&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update_2&quot;&gt;¶&lt;/a&gt;Update&lt;/h2&gt;
1065&lt;p&gt;It is not true that &amp;quot;they don't allow running arbitrary binaries by default&amp;quot;, as pointed out in their &lt;a href=&quot;https://nixos.org/nixpkgs/manual/#sec-fhs-environments&quot;&gt;manual, buildFHSUserEnv&lt;/a&gt;:&lt;/p&gt;
1066&lt;blockquote&gt;
1067&lt;p&gt;&lt;code&gt;buildFHSUserEnv&lt;/code&gt; provides a way to build and run FHS-compatible lightweight sandboxes. It creates an isolated root with bound &lt;code&gt;/nix/store&lt;/code&gt;, so its footprint in terms of disk space needed is quite small. This allows one to run software which is hard or unfeasible to patch for NixOS -- 3rd-party source trees with FHS assumptions, games distributed as tarballs, software with integrity checking and/or external self-updated binaries. It uses Linux namespaces feature to create temporary lightweight environments which are destroyed after all child processes exit, without root user rights requirement.&lt;/p&gt;
1068&lt;/blockquote&gt;
1069&lt;p&gt;Thanks to &lt;a href=&quot;https://github.com/bb010g&quot;&gt;@bb010g&lt;/a&gt; for pointing this out.&lt;/p&gt;
1070&lt;h2 id=&quot;notes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#notes&quot;&gt;¶&lt;/a&gt;Notes&lt;/h2&gt;
1071&lt;p class=&quot;footnote&quot; id=&quot;f.1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; The keyboard mapping is a bit strange. On my Spanish keyboard, the keys were as follows: &lt;a href=&quot;#r.1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1072&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Keyboard&lt;/th&gt;&lt;th&gt;Maps to&lt;/th&gt;&lt;th&gt;Shift&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;
1073&lt;tr&gt;&lt;td&gt;'&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;_&lt;/td&gt;&lt;/tr&gt;
1074&lt;tr&gt;&lt;td&gt;´&lt;/td&gt;&lt;td&gt;'&lt;/td&gt;&lt;td&gt;&amp;quot;&lt;/td&gt;&lt;/tr&gt;
1075&lt;tr&gt;&lt;td&gt;`&lt;/td&gt;&lt;td&gt;[&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
1076&lt;tr&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;]&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
1077&lt;tr&gt;&lt;td&gt;¡&lt;/td&gt;&lt;td&gt;=&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
1078&lt;tr&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;/&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
1079&lt;tr&gt;&lt;td&gt;ñ&lt;/td&gt;&lt;td&gt;;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
1080&lt;/tbody&gt;&lt;/table&gt;
1081&lt;/main&gt;
1082&lt;/body&gt;
1083&lt;/html&gt;
1084 </content></entry><entry><title>WorldEdit Commands</title><id>dist/world_edit/index.html</id><updated>2018-07-10T22:00:00+00:00</updated><published>2018-07-10T22:00:00+00:00</published><summary>WorldEdit</summary><content type="html" src="dist/world_edit/index.html">&lt;!DOCTYPE html&gt;
1085&lt;html&gt;
1086&lt;head&gt;
1087&lt;meta charset=&quot;utf-8&quot; /&gt;
1088&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1089&lt;title&gt;WorldEdit Commands&lt;/title&gt;
1090&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1091&lt;/head&gt;
1092&lt;body&gt;
1093&lt;main&gt;
1094&lt;h1 class=&quot;title&quot; id=&quot;worldedit_commands&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#worldedit_commands&quot;&gt;¶&lt;/a&gt;WorldEdit Commands&lt;/h1&gt;
1095&lt;div class=&quot;date-created-modified&quot;&gt;2018-07-11&lt;/div&gt;
1096&lt;p&gt;&lt;a href=&quot;https://dev.bukkit.org/projects/worldedit&quot;&gt;WorldEdit&lt;/a&gt; is an extremely powerful tool for modifying entire worlds within &lt;a href=&quot;https://minecraft.net&quot;&gt;Minecraft&lt;/a&gt;, which can be used as either a mod for your single-player worlds or as a plugin for your &lt;a href=&quot;https://getbukkit.org/&quot;&gt;Bukkit&lt;/a&gt; servers.&lt;/p&gt;
1097&lt;p&gt;This command guide was written for Minecraft 1.12.1, version &lt;a href=&quot;https://dev.bukkit.org/projects/worldedit/files/2460562&quot;&gt;6.1.7.3&lt;/a&gt;, but should work for newer versions too. All WorldEdit commands can be used with a double slash (&lt;code&gt;//&lt;/code&gt;) so they don't conlict with built-in commands. This means you can get a list of all commands with &lt;code&gt;//help&lt;/code&gt;. Let's explore different categories!&lt;/p&gt;
1098&lt;h2 id=&quot;movement&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#movement&quot;&gt;¶&lt;/a&gt;Movement&lt;/h2&gt;
1099&lt;p&gt;In order to edit a world properly you need to learn how to move in said world properly. There are several straightforward commands that let you move:&lt;/p&gt;
1100&lt;ul&gt;
1101&lt;li&gt;&lt;code&gt;//ascend&lt;/code&gt; goes up one floor.&lt;/li&gt;
1102&lt;li&gt;&lt;code&gt;//descend&lt;/code&gt; goes down one floor.&lt;/li&gt;
1103&lt;li&gt;&lt;code&gt;//thru&lt;/code&gt; let's you pass through walls.&lt;/li&gt;
1104&lt;li&gt;&lt;code&gt;//jumpto&lt;/code&gt; to go wherever you are looking.&lt;/li&gt;
1105&lt;/ul&gt;
1106&lt;h2 id=&quot;information&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#information&quot;&gt;¶&lt;/a&gt;Information&lt;/h2&gt;
1107&lt;p&gt;Knowing your world properly is as important as knowing how to move within it, and will also let you change the information in said world if you need to.&lt;/p&gt;
1108&lt;ul&gt;
1109&lt;li&gt;&lt;code&gt;//biomelist&lt;/code&gt; shows all known biomes.&lt;/li&gt;
1110&lt;li&gt;&lt;code&gt;//biomeinfo&lt;/code&gt; shows the current biome.&lt;/li&gt;
1111&lt;li&gt;&lt;code&gt;//setbiome&lt;/code&gt; lets you change the biome.&lt;/li&gt;
1112&lt;/ul&gt;
1113&lt;h2 id=&quot;blocks&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#blocks&quot;&gt;¶&lt;/a&gt;Blocks&lt;/h2&gt;
1114&lt;p&gt;You can act over all blocks in a radius around you with quite a few commands. Some won't actually act over the entire range you specify, so 100 is often a good number.&lt;/p&gt;
1115&lt;h3 id=&quot;filling&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#filling&quot;&gt;¶&lt;/a&gt;Filling&lt;/h3&gt;
1116&lt;p&gt;You can fill pools with &lt;code&gt;//fill water 100&lt;/code&gt; or caves with &lt;code&gt;//fillr water 100&lt;/code&gt;, both of which act below your feet.&lt;/p&gt;
1117&lt;h3 id=&quot;fixing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#fixing&quot;&gt;¶&lt;/a&gt;Fixing&lt;/h3&gt;
1118&lt;p&gt;If the water or lava is buggy use &lt;code&gt;//fixwater 100&lt;/code&gt; or &lt;code&gt;//fixlava 100&lt;/code&gt; respectively.&lt;/p&gt;
1119&lt;p&gt;Some creeper removed the snow or the grass? Fear not, you can use &lt;code&gt;//snow 10&lt;/code&gt; or &lt;code&gt;//grass 10&lt;/code&gt;.&lt;/p&gt;
1120&lt;h3 id=&quot;emptying&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#emptying&quot;&gt;¶&lt;/a&gt;Emptying&lt;/h3&gt;
1121&lt;p&gt;You can empty a pool completely with &lt;code&gt;//drain 100&lt;/code&gt;, remove the snow with &lt;code&gt;//thaw 10&lt;/code&gt;, and remove fire with &lt;code&gt;//ex 10&lt;/code&gt;.&lt;/p&gt;
1122&lt;h3 id=&quot;removing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#removing&quot;&gt;¶&lt;/a&gt;Removing&lt;/h3&gt;
1123&lt;p&gt;You can remove blocks above and below you in some area with the &lt;code&gt;//removeabove N&lt;/code&gt; and &lt;code&gt;//removebelow N&lt;/code&gt;. You probably want to set a limit though, or you could fall off the world with &lt;code&gt;//removebelow 1 10&lt;/code&gt; for radius and depth. You can also remove near blocks with &lt;code&gt;//removenear block 10&lt;/code&gt;.&lt;/p&gt;
1124&lt;h3 id=&quot;shapes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#shapes&quot;&gt;¶&lt;/a&gt;Shapes&lt;/h3&gt;
1125&lt;p&gt;Making a cylinder (or circle) can be done with through &lt;code&gt;//cyl stone 10&lt;/code&gt;, a third argument for the height. The radius can be comma-separated to make a ellipses instead, such as &lt;code&gt;//cyl stone 5,10&lt;/code&gt;.&lt;/p&gt;
1126&lt;p&gt;Spheres are done with &lt;code&gt;//sphere stone 5&lt;/code&gt;. This will build one right at your center, so you can raise it to be on your feet with &lt;code&gt;//sphere stone 5 yes&lt;/code&gt;. Similar to cylinders, you can comma separate the radius &lt;code&gt;x,y,z&lt;/code&gt;.&lt;/p&gt;
1127&lt;p&gt;Pyramids can be done with &lt;code&gt;//pyramic stone 5&lt;/code&gt;.&lt;/p&gt;
1128&lt;p&gt;All these commands can be prefixed with &amp;quot;h&amp;quot; to make them hollow. For instance, &lt;code&gt;//hsphere stone 10&lt;/code&gt;.&lt;/p&gt;
1129&lt;h2 id=&quot;regions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#regions&quot;&gt;¶&lt;/a&gt;Regions&lt;/h2&gt;
1130&lt;h3 id=&quot;basics&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#basics&quot;&gt;¶&lt;/a&gt;Basics&lt;/h3&gt;
1131&lt;p&gt;Operating over an entire region is really important, and the first thing you need to work comfortably with them is a tool to make selections. The default wooden-axe tool can be obtained with &lt;code&gt;//wand&lt;/code&gt;, but you must be near the blocks to select. You can use a different tool, like a golden axe, to use as your &amp;quot;far wand&amp;quot; (wand usable over distance). Once you have one in your hand type &lt;code&gt;//farwand&lt;/code&gt; to use it as your &amp;quot;far wand&amp;quot;. You can select the two corners of your region with left and right click. If you have selected the wrong tool, use &lt;code&gt;//none&lt;/code&gt; to clear it.&lt;/p&gt;
1132&lt;p&gt;If there are no blocks but you want to use your current position as a corner, use &lt;code&gt;//pos1&lt;/code&gt; or 2.&lt;/p&gt;
1133&lt;p&gt;If you made a region too small, you can enlarge it with &lt;code&gt;//expand 10 up&lt;/code&gt;, or &lt;code&gt;//expand vert&lt;/code&gt; for the entire vertical range, etc., or make it smaller with &lt;code&gt;//contract 10 up&lt;/code&gt; etc., or &lt;code&gt;//inset&lt;/code&gt; it to contract in both directions. You can use short-names for the cardinal directions (NSEW).&lt;/p&gt;
1134&lt;p&gt;Finally, if you want to move your selection, you can &lt;code&gt;//shift 1 north&lt;/code&gt; it to wherever you need.&lt;/p&gt;
1135&lt;h3 id=&quot;information_2&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#information_2&quot;&gt;¶&lt;/a&gt;Information&lt;/h3&gt;
1136&lt;p&gt;You can get the &lt;code&gt;//size&lt;/code&gt; of the selection or even &lt;code&gt;//count torch&lt;/code&gt; in some area. If you want to count all blocks, get their distribution &lt;code&gt;//distr&lt;/code&gt;.&lt;/p&gt;
1137&lt;h3 id=&quot;filling_2&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#filling_2&quot;&gt;¶&lt;/a&gt;Filling&lt;/h3&gt;
1138&lt;p&gt;With a region selected, you can &lt;code&gt;//set&lt;/code&gt; it to be any block! For instance, you can use &lt;code&gt;//set air&lt;/code&gt; to clear it entirely. You can use more than one block evenly by separting them with a comma &lt;code&gt;//set stone,dirt&lt;/code&gt;, or with a custom chance &lt;code&gt;//set 20%stone,80%dirt&lt;/code&gt;.&lt;/p&gt;
1139&lt;p&gt;You can use &lt;code&gt;//replace from to&lt;/code&gt; instead if you don't want to override all blocks in your selection.&lt;/p&gt;
1140&lt;p&gt;You can make an hollow set with &lt;code&gt;//faces&lt;/code&gt;, and if you just want the walls, use &lt;code&gt;//walls&lt;/code&gt;.&lt;/p&gt;
1141&lt;h3 id=&quot;cleaning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#cleaning&quot;&gt;¶&lt;/a&gt;Cleaning&lt;/h3&gt;
1142&lt;p&gt;If someone destroyed your wonderful snow landscape, fear not, you can use &lt;code&gt;//overlay snow&lt;/code&gt; over it (although for this you actually have &lt;code&gt;//snow N&lt;/code&gt; and its opposite &lt;code&gt;//thaw&lt;/code&gt;).&lt;/p&gt;
1143&lt;p&gt;If you set some rough area, you can always &lt;code&gt;//smooth&lt;/code&gt; it, even more than one time with &lt;code&gt;//smooth 3&lt;/code&gt;. You can get your dirt and stone back with &lt;code&gt;//naturalize&lt;/code&gt; and put some plants with &lt;code&gt;//flora&lt;/code&gt; or &lt;code&gt;//forest&lt;/code&gt;, both of which support a density or even the type for the trees. If you already have the dirt use &lt;code&gt;//green&lt;/code&gt; instead. If you want some pumpkins, with &lt;code&gt;//pumpkins&lt;/code&gt;.&lt;/p&gt;
1144&lt;h3 id=&quot;moving&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#moving&quot;&gt;¶&lt;/a&gt;Moving&lt;/h3&gt;
1145&lt;p&gt;You can repeat an entire selection many times by stacking them with &lt;code&gt;//stack N DIR&lt;/code&gt;. This is extremely useful to make things like corridors or elevators. For instance, you can make a small section of the corridor, select it entirely, and then repeat it 10 times with &lt;code&gt;//stack 10 north&lt;/code&gt;. Or you can make the elevator and then &lt;code&gt;//stack 10 up&lt;/code&gt;. If you need to also copy the air use &lt;code&gt;//stackair&lt;/code&gt;.&lt;/p&gt;
1146&lt;p&gt;Finally, if you don't need to repeat it and simply move it just a bit towards the right direction, you can use &lt;code&gt;//move N&lt;/code&gt;. The default direction is &amp;quot;me&amp;quot; (towards where you are facing) but you can set one with &lt;code&gt;//move 1 up&lt;/code&gt; for example.&lt;/p&gt;
1147&lt;h3 id=&quot;selecting&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#selecting&quot;&gt;¶&lt;/a&gt;Selecting&lt;/h3&gt;
1148&lt;p&gt;You can not only select cuboids. You can also select different shapes, or even just points:&lt;/p&gt;
1149&lt;ul&gt;
1150&lt;li&gt;&lt;code&gt;//sel cuboid&lt;/code&gt; is the default.&lt;/li&gt;
1151&lt;li&gt;&lt;code&gt;//sel extend&lt;/code&gt; expands the default.&lt;/li&gt;
1152&lt;li&gt;&lt;code&gt;//sel poly&lt;/code&gt; first point with left click and right click to add new points.&lt;/li&gt;
1153&lt;li&gt;&lt;code&gt;//sel ellipsoid&lt;/code&gt; first point to select the center and right click to select the different radius.&lt;/li&gt;
1154&lt;li&gt;&lt;code&gt;//sel sphere&lt;/code&gt; first point to select the center and one more right click for the radius.&lt;/li&gt;
1155&lt;li&gt;&lt;code&gt;//sel cyl&lt;/code&gt; for cylinders, first click being the center.&lt;/li&gt;
1156&lt;li&gt;&lt;code&gt;//sel convex&lt;/code&gt; for convex shapes. This one is extremely useful for &lt;code&gt;//curve&lt;/code&gt;.&lt;/li&gt;
1157&lt;/ul&gt;
1158&lt;h2 id=&quot;brushes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#brushes&quot;&gt;¶&lt;/a&gt;Brushes&lt;/h2&gt;
1159&lt;p&gt;Brushes are a way to paint in 3D without first bothering about making a selection, and there are spherical and cylinder brushes with e.g. &lt;code&gt;//brush sphere stone 2&lt;/code&gt;, or the shorter form &lt;code&gt;//br s stone&lt;/code&gt;. For cylinder, one must use &lt;code&gt;cyl&lt;/code&gt; instead &lt;code&gt;sphere&lt;/code&gt;.&lt;/p&gt;
1160&lt;p&gt;There also exists a brush to smooth the terrain which can be enabled on the current item with &lt;code&gt;//br smooth&lt;/code&gt;, which can be used with right-click like any other brush.&lt;/p&gt;
1161&lt;h2 id=&quot;clipboard&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#clipboard&quot;&gt;¶&lt;/a&gt;Clipboard&lt;/h2&gt;
1162&lt;p&gt;Finally, you can copy and cut things around like you would do with normal text with &lt;code&gt;//copy&lt;/code&gt; and &lt;code&gt;//cut&lt;/code&gt;. The copy is issued from wherever you issue the command, so when you use &lt;code&gt;//paste&lt;/code&gt;, remember that if you were 4 blocks apart when copying, it will be 4 blocks apart when pasting.&lt;/p&gt;
1163&lt;p&gt;The contents of the clipboard can be flipped to wherever you are looking via &lt;code&gt;//flip&lt;/code&gt;, and can be rotated via the &lt;code&gt;//rotate 90&lt;/code&gt; command (in degrees).&lt;/p&gt;
1164&lt;p&gt;To remove the copy use &lt;code&gt;//clearclipboard&lt;/code&gt;.&lt;/p&gt;
1165&lt;/main&gt;
1166&lt;/body&gt;
1167&lt;/html&gt;
1168 </content></entry><entry><title>An Introduction to Asyncio</title><id>dist/asyncio/index.html</id><updated>2018-06-14T22:00:00+00:00</updated><published>2018-06-12T22:00:00+00:00</published><summary>After seeing some friends struggle with </summary><content type="html" src="dist/asyncio/index.html">&lt;!DOCTYPE html&gt;
1169&lt;html&gt;
1170&lt;head&gt;
1171&lt;meta charset=&quot;utf-8&quot; /&gt;
1172&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1173&lt;title&gt;An Introduction to Asyncio&lt;/title&gt;
1174&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1175&lt;/head&gt;
1176&lt;body&gt;
1177&lt;main&gt;
1178&lt;h1 class=&quot;title&quot; id=&quot;an_introduction_to_asyncio&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#an_introduction_to_asyncio&quot;&gt;¶&lt;/a&gt;An Introduction to Asyncio&lt;/h1&gt;
1179&lt;div class=&quot;date-created-modified&quot;&gt;Created 2018-06-13&lt;br&gt;
1180Modified 2018-06-15&lt;/div&gt;
1181&lt;h2 id=&quot;index&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#index&quot;&gt;¶&lt;/a&gt;Index&lt;/h2&gt;
1182&lt;ul&gt;
1183&lt;li&gt;&lt;a href=&quot;#background&quot;&gt;Background&lt;/a&gt;&lt;/li&gt;
1184&lt;li&gt;&lt;a href=&quot;#inputoutput&quot;&gt;Input / Output&lt;/a&gt;&lt;/li&gt;
1185&lt;li&gt;&lt;a href=&quot;#divingin&quot;&gt;Diving In&lt;/a&gt;&lt;/li&gt;
1186&lt;li&gt;&lt;a href=&quot;#toyexample&quot;&gt;A Toy Example&lt;/a&gt;&lt;/li&gt;
1187&lt;li&gt;&lt;a href=&quot;#example&quot;&gt;A Real Example&lt;/a&gt;&lt;/li&gt;
1188&lt;li&gt;&lt;a href=&quot;#extra&quot;&gt;Extra Material&lt;/a&gt;&lt;/li&gt;
1189&lt;/ul&gt;
1190&lt;h2 id=&quot;background&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#background&quot;&gt;¶&lt;/a&gt;Background&lt;/h2&gt;
1191&lt;p&gt;After seeing some friends struggle with &lt;code&gt;asyncio&lt;/code&gt; I decided that it could be a good idea to write a blog post using my own words to explain how I understand the world of asynchronous IO. I will focus on Python's &lt;code&gt;asyncio&lt;/code&gt; module but this post should apply to any other language easily.&lt;/p&gt;
1192&lt;p&gt;So what is &lt;code&gt;asyncio&lt;/code&gt; and what makes it good? Why don't we just use the old and known threads to run several parts of the code concurrently, at the same time?&lt;/p&gt;
1193&lt;p&gt;The first reason is that &lt;code&gt;asyncio&lt;/code&gt; makes your code easier to reason about, as opposed to using threads, because the amount of ways in which your code can run grows exponentially. Let's see that with an example. Imagine you have this code:&lt;/p&gt;
1194&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def method():
1195	line 1
1196	line 2
1197	line 3
1198	line 4
1199	line 5
1200&lt;/code&gt;&lt;/pre&gt;
1201&lt;p&gt;And you start two threads to run the method at the same time. What is the order in which the lines of code get executed? The answer is that you can't know! The first thread can run the entire method before the second thread even starts. Or it could be the first thread that runs after the second thread. Perhaps both run the &amp;quot;line 1&amp;quot;, and then the line 2. Maybe the first thread runs lines 1 and 2, and then the second thread only runs the line 1 before the first thread finishes.&lt;/p&gt;
1202&lt;p&gt;As you can see, any combination of the order in which the lines run is possible. If the lines modify some global shared state, that will get messy quickly.&lt;/p&gt;
1203&lt;p&gt;Second, in Python, threads &lt;em&gt;won't&lt;/em&gt; make your code faster. It will only increase the concurrency of your program, allowing you to run several things at the same time, so using threads for speed isn't a real advantage. Indeed, your code will probably run slower under the most common Python implementation, CPython, which makes use of a Global Interpreter Lock (GIL) that only lets a thread run at once.&lt;/p&gt;
1204&lt;h2 id=&quot;input_output&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#input_output&quot;&gt;¶&lt;/a&gt;Input / Output&lt;/h2&gt;
1205&lt;p&gt;Before we go any further, let's first stop to talk about input and output, commonly known as &amp;quot;IO&amp;quot;. There are two main ways to perform IO operations, such as reading or writing from a file or a network socket.&lt;/p&gt;
1206&lt;p&gt;The first one is known as &amp;quot;blocking IO&amp;quot;. What this means is that, when you try performing IO, the current application thread is going to &lt;em&gt;block&lt;/em&gt; until the Operative System can tell you it's done. Normally, this is not a problem, since disks are pretty fast anyway, but it can soon become a performance bottleneck. And network IO will be much slower than disk IO!&lt;/p&gt;
1207&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# &amp;quot;open&amp;quot; will block until the OS creates a new file in the disk.
1208#        this can be really slow if the disk is under heavy load!
1209with open('hello.txt', 'w') as fd:
1210    fd.write('hello!\n')
1211
1212    # &amp;quot;flush&amp;quot; will block until the OS has written all data to disk*
1213    fd.flush()
1214
1215# * the reality is a bit more complicated, since writes to disk are
1216#   quite expensive, the OS will normally keep the data in RAM until
1217#   it has more stuff to write to disk, and then it will `sync`
1218#   everything after a few seconds
1219&lt;/code&gt;&lt;/pre&gt;
1220&lt;p&gt;Blocking IO offers timeouts, so that you can get control back in your code if the operation doesn't finish. Imagine that the remote host doesn't want to reply, your code would be stuck for as long as the connection remains alive!&lt;/p&gt;
1221&lt;p&gt;But wait, what if we make the timeout small? Very, very small? If we do that, we will never block waiting for an answer. That's how asynchronous IO works, and it's the opposite of blocking IO (you can also call it non-blocking IO if you want to).&lt;/p&gt;
1222&lt;p&gt;How does non-blocking IO work if the IO device needs a while to answer with the data? In that case, the operative system responds with &amp;quot;not ready&amp;quot;, and your application gets control back so it can do other stuff while the IO device completes your request. It works a bit like this:&lt;/p&gt;
1223&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;&amp;amp;lt;app&amp;amp;gt; Hey, I would like to read 16 bytes from this file
1224&amp;amp;lt;OS&amp;amp;gt; Okay, but the disk hasn't sent me the data yet
1225&amp;amp;lt;app&amp;amp;gt; Alright, I will do something else then
1226(a lot of computer time passes)
1227&amp;amp;lt;app&amp;amp;gt; Do you have my 16 bytes now?
1228&amp;amp;lt;OS&amp;amp;gt; Yes, here they are! &amp;quot;Hello, world !!\n&amp;quot;
1229&lt;/code&gt;&lt;/pre&gt;
1230&lt;p&gt;In reality, you can tell the OS to notify you when the data is ready, as opposed to polling (constantly asking the OS whether the data is ready yet or not), which is more efficient.&lt;/p&gt;
1231&lt;p&gt;But either way, that's the difference between blocking and non-blocking IO, and what matters is that your application gets to run more without ever needing to wait for data to arrive, because the data will be there immediately when you ask, and if it's not yet, your app can do more things meanwhile.&lt;/p&gt;
1232&lt;h2 id=&quot;diving_in&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#diving_in&quot;&gt;¶&lt;/a&gt;Diving In&lt;/h2&gt;
1233&lt;p&gt;Now we've seen what blocking and non-blocking IO is, and how threads make your code harder to reason about, but they give concurrency (yet not more speed). Is there any other way to achieve this concurrency that doesn't involve threads? Yes! The answer is &lt;code&gt;asyncio&lt;/code&gt;.&lt;/p&gt;
1234&lt;p&gt;So how does &lt;code&gt;asyncio&lt;/code&gt; help? First we need to understand a very crucial concept before we can dive any deeper, and I'm talking about the &lt;em&gt;event loop&lt;/em&gt;. What is it and why do we need it?&lt;/p&gt;
1235&lt;p&gt;You can think of the event loop as a &lt;em&gt;loop&lt;/em&gt; that will be responsible for calling your &lt;code&gt;async&lt;/code&gt; functions:&lt;/p&gt;
1236&lt;div class=&quot;image-container&quot;&gt;
1237&lt;img src=&quot;eventloop.svg&quot; alt=&quot;The Event Loop&quot; /&gt;
1238&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1239&lt;/div&gt;
1240&lt;p&gt;
1241&lt;p&gt;That's silly you may think. Now not only we run our code but we also have to run some &amp;quot;event loop&amp;quot;. It doesn't sound beneficial at all. What are these events? Well, they are the IO events we talked about before!&lt;/p&gt;
1242&lt;p&gt;&lt;code&gt;asyncio&lt;/code&gt;'s event loop is responsible for handling those IO events, such as file is ready, data arrived, flushing is done, and so on. As we saw before, we can make these events non-blocking by setting their timeout to 0.&lt;/p&gt;
1243&lt;p&gt;Let's say you want to read from 10 files at the same time. You will ask the OS to read data from 10 files, and at first none of the reads will be ready. But the event loop will be constantly asking the OS to know which are done, and when they are done, you will get your data.&lt;/p&gt;
1244&lt;p&gt;This has some nice advantages. It means that, instead of waiting for a network request to send you a response or some file, instead of blocking there, the event loop can decide to run other code meanwhile. Whenever the contents are ready, they can be read, and your code can continue. Waiting for the contents to be received is done with the &lt;code&gt;await&lt;/code&gt; keyword, and it tells the loop that it can run other code meanwhile:&lt;/p&gt;
1245&lt;div class=&quot;image-container&quot;&gt;
1246&lt;img src=&quot;awaitkwd1.svg&quot; alt=&quot;Step 1, await keyword&quot; /&gt;
1247&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1248&lt;/div&gt;
1249&lt;p&gt;
1250&lt;div class=&quot;image-container&quot;&gt;
1251&lt;img src=&quot;awaitkwd2.svg&quot; alt=&quot;Step 2, await keyword&quot; /&gt;
1252&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1253&lt;/div&gt;
1254&lt;p&gt;
1255&lt;p&gt;Start reading the code of the event loop and follow the arrows. You can see that, in the beginning, there are no events yet, so the loop calls one of your functions. The code runs until it has to &lt;code&gt;await&lt;/code&gt; for some IO operation to complete, such as sending a request over the network. The method is &amp;quot;paused&amp;quot; until an event occurs (for example, an &amp;quot;event&amp;quot; occurs when the request has been sent completely).&lt;/p&gt;
1256&lt;p&gt;While the first method is busy, the event loop can enter the second method, and run its code until the first &lt;code&gt;await&lt;/code&gt;. But it can happen that the event of the second query occurs before the request on the first method, so the event loop can re-enter the second method because it has already sent the query, but the first method isn't done sending the request yet.&lt;/p&gt;
1257&lt;p&gt;Then, the second method &lt;code&gt;await&lt;/code&gt;'s for an answer, and an event occurs telling the event loop that the request from the first method was sent. The code can be resumed again, until it has to &lt;code&gt;await&lt;/code&gt; for a response, and so on.&lt;/p&gt;
1258&lt;p&gt;There are some important things to note here. The first is that we only need one thread to be running! The event loop decides when and which methods should run. The second is that we know when it may run other methods. Those are the &lt;code&gt;await&lt;/code&gt; keywords! Whenever there is one of those, we know that the loop is able to run other things until the resource (again, like network) becomes ready.&lt;/p&gt;
1259&lt;p&gt;So far, we already have two advantages. We are only using a single thread so the cost for switching between methods is low, and we can easily reason about where our program may interleave operations.&lt;/p&gt;
1260&lt;p&gt;Another advantage is that, with the event loop, you can easily schedule when a piece of code should run, such as using the method &lt;a href=&quot;https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_at&quot;&gt;&lt;code&gt;loop.call_at&lt;/code&gt;&lt;/a&gt;, without the need for spawning another thread at all.&lt;/p&gt;
1261&lt;p&gt;To tell the &lt;code&gt;asyncio&lt;/code&gt; to run the two methods shown above, we can use &lt;a href=&quot;https://docs.python.org/3/library/asyncio-future.html#asyncio.ensure_future&quot;&gt;&lt;code&gt;asyncio.ensure_future&lt;/code&gt;&lt;/a&gt;, which is a way of saying &amp;quot;I want the future of my method to be ensured&amp;quot;. That is, you want to run your method in the future, whenever the loop is free to do so. This method returns a &lt;code&gt;Future&lt;/code&gt; object, so if your method returns a value, you can &lt;code&gt;await&lt;/code&gt; this future to retrieve its result.&lt;/p&gt;
1262&lt;p&gt;What is a &lt;code&gt;Future&lt;/code&gt;? This object represents the value of something that will be there in the future, but might not be there yet. Just like you can &lt;code&gt;await&lt;/code&gt; your own &lt;code&gt;async def&lt;/code&gt; functions, you can &lt;code&gt;await&lt;/code&gt; these &lt;code&gt;Future&lt;/code&gt;'s.&lt;/p&gt;
1263&lt;p&gt;The &lt;code&gt;async def&lt;/code&gt; functions are also called &amp;quot;coroutines&amp;quot;, and Python does some magic behind the scenes to turn them into such. The coroutines can be &lt;code&gt;await&lt;/code&gt;'ed, and this is what you normally do.&lt;/p&gt;
1264&lt;h2 id=&quot;a_toy_example&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a_toy_example&quot;&gt;¶&lt;/a&gt;A Toy Example&lt;/h2&gt;
1265&lt;p&gt;That's all about &lt;code&gt;asyncio&lt;/code&gt;! Let's wrap up with some example code. We will create a server that replies with the text a client sends, but reversed. First, we will show what you could write with normal synchronous code, and then we will port it.&lt;/p&gt;
1266&lt;p&gt;Here is the &lt;strong&gt;synchronous version&lt;/strong&gt;:&lt;/p&gt;
1267&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# server.py
1268import socket
1269
1270
1271def server_method():
1272	# create a new server socket to listen for connections
1273	server = socket.socket()
1274
1275	# bind to localhost:6789 for new connections
1276	server.bind(('localhost', 6789))
1277
1278	# we will listen for one client at most
1279	server.listen(1)
1280
1281	# *block* waiting for a new client
1282	client, _ = server.accept()
1283
1284	# *block* waiting for some data
1285	data = client.recv(1024)
1286
1287	# reverse the data
1288	data = data[::-1]
1289
1290	# *block* sending the data
1291	client.sendall(data)
1292
1293	# close client and server
1294	server.close()
1295	client.close()
1296
1297
1298if __name__ == '__main__':
1299	# block running the server
1300	server_method()
1301&lt;/code&gt;&lt;/pre&gt;
1302&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# client.py
1303import socket
1304
1305
1306def client_method():
1307	message = b'Hello Server!\n'
1308	client = socket.socket()
1309
1310	# *block* trying to stabilish a connection
1311	client.connect(('localhost', 6789))
1312
1313	# *block* trying to send the message
1314	print('Sending', message)
1315	client.sendall(message)
1316
1317	# *block* until we receive a response
1318	response = client.recv(1024)
1319	print('Server replied', response)
1320
1321	client.close()
1322
1323
1324if __name__ == '__main__':
1325	client_method()
1326&lt;/code&gt;&lt;/pre&gt;
1327&lt;p&gt;From what we've seen, this code will block on all the lines with a comment above them saying that they will block. This means that for running more than one client or server, or both in the same file, you will need threads. But we can do better, we can rewrite it into &lt;code&gt;asyncio&lt;/code&gt;!&lt;/p&gt;
1328&lt;p&gt;The first step is to mark all your &lt;code&gt;def&lt;/code&gt;initions that may block with &lt;code&gt;async&lt;/code&gt;. This marks them as coroutines, which can be &lt;code&gt;await&lt;/code&gt;ed on.&lt;/p&gt;
1329&lt;p&gt;Second, since we're using low-level sockets, we need to make use of the methods that &lt;code&gt;asyncio&lt;/code&gt; provides directly. If this was a third-party library, this would be just like using their &lt;code&gt;async def&lt;/code&gt;initions.&lt;/p&gt;
1330&lt;p&gt;Here is the &lt;strong&gt;asynchronous version&lt;/strong&gt;:&lt;/p&gt;
1331&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# server.py
1332import asyncio
1333import socket
1334
1335# get the default &amp;quot;event loop&amp;quot; that we will run
1336loop = asyncio.get_event_loop()
1337
1338
1339# notice our new &amp;quot;async&amp;quot; before the definition
1340async def server_method():
1341	server = socket.socket()
1342	server.bind(('localhost', 6789))
1343	server.listen(1)
1344
1345	# await for a new client
1346	# the event loop can run other code while we wait here!
1347	client, _ = await loop.sock_accept(server)
1348
1349	# await for some data
1350	data = await loop.sock_recv(client, 1024)
1351	data = data[::-1]
1352
1353	# await for sending the data
1354	await loop.sock_sendall(client, data)
1355
1356	server.close()
1357	client.close()
1358
1359
1360if __name__ == '__main__':
1361	# run the loop until &amp;quot;server method&amp;quot; is complete
1362	loop.run_until_complete(server_method())
1363&lt;/code&gt;&lt;/pre&gt;
1364&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# client.py
1365import asyncio
1366import socket
1367
1368loop = asyncio.get_event_loop()
1369
1370
1371async def client_method():
1372	message = b'Hello Server!\n'
1373	client = socket.socket()
1374
1375	# await to stabilish a connection
1376	await loop.sock_connect(client, ('localhost', 6789))
1377
1378	# await to send the message
1379	print('Sending', message)
1380	await loop.sock_sendall(client, message)
1381
1382	# await to receive a response
1383	response = await loop.sock_recv(client, 1024)
1384	print('Server replied', response)
1385
1386	client.close()
1387
1388
1389if __name__ == '__main__':
1390	loop.run_until_complete(client_method())
1391&lt;/code&gt;&lt;/pre&gt;
1392&lt;p&gt;That's it! You can place these two files separately and run, first the server, then the client. You should see output in the client.&lt;/p&gt;
1393&lt;p&gt;The big difference here is that you can easily modify the code to run more than one server or clients at the same time. Whenever you &lt;code&gt;await&lt;/code&gt; the event loop will run other of your code. It seems to &amp;quot;block&amp;quot; on the &lt;code&gt;await&lt;/code&gt; parts, but remember it's actually jumping to run more code, and the event loop will get back to you whenever it can.&lt;/p&gt;
1394&lt;p&gt;In short, you need an &lt;code&gt;async def&lt;/code&gt; to &lt;code&gt;await&lt;/code&gt; things, and you run them with the event loop instead of calling them directly. So this…&lt;/p&gt;
1395&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def main():
1396	...  # some code
1397
1398
1399if __name__ == '__main__':
1400	main()
1401&lt;/code&gt;&lt;/pre&gt;
1402&lt;p&gt;…becomes this:&lt;/p&gt;
1403&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import asyncio
1404
1405
1406async def main():
1407	...  # some code
1408
1409
1410if __name__ == '__main__':
1411	asyncio.get_event_loop().run_until_complete(main)
1412&lt;/code&gt;&lt;/pre&gt;
1413&lt;p&gt;This is pretty much how most of your &lt;code&gt;async&lt;/code&gt; scripts will start, running the main method until its completion.&lt;/p&gt;
1414&lt;h2 id=&quot;a_real_example&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a_real_example&quot;&gt;¶&lt;/a&gt;A Real Example&lt;/h2&gt;
1415&lt;p&gt;Let's have some fun with a real library. We'll be using &lt;a href=&quot;https://github.com/LonamiWebs/Telethon&quot;&gt;Telethon&lt;/a&gt; to broadcast a message to our three best friends, all at the same time, thanks to the magic of &lt;code&gt;asyncio&lt;/code&gt;. We'll dive right into the code, and then I'll explain our new friend &lt;code&gt;asyncio.wait(...)&lt;/code&gt;:&lt;/p&gt;
1416&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# broadcast.py
1417import asyncio
1418import sys
1419
1420from telethon import TelegramClient
1421
1422# (you need your own values here, check Telethon's documentation)
1423api_id = 123
1424api_hash = '123abc'
1425friends = [
1426	'@friend1__username',
1427	'@friend2__username',
1428	'@bestie__username'
1429]
1430
1431# we will have to await things, so we need an async def
1432async def main(message):
1433	# start is a coroutine, so we need to await it to run it
1434	client = await TelegramClient('me', api_id, api_hash).start()
1435
1436	# wait for all three client.send_message to complete
1437	await asyncio.wait([
1438		client.send_message(friend, message)
1439		for friend in friends
1440	])
1441
1442	# and close our client
1443	await client.disconnect()
1444
1445
1446if __name__ == '__main__':
1447	if len(sys.argv) != 2:
1448		print('You must pass the message to broadcast!')
1449		quit()
1450
1451	message = sys.argv[1]
1452	asyncio.get_event_loop().run_until_complete(main(message))
1453&lt;/code&gt;&lt;/pre&gt;
1454&lt;p&gt;Wait… how did that send a message to all three of
1455my friends? The magic is done here:&lt;/p&gt;
1456&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;[
1457	client.send_message(friend, message)
1458	for friend in friends
1459]
1460&lt;/code&gt;&lt;/pre&gt;
1461&lt;p&gt;This list comprehension creates another list with three
1462coroutines, the three &lt;code&gt;client.send_message(...)&lt;/code&gt;.
1463Then we just pass that list to &lt;code&gt;asyncio.wait&lt;/code&gt;:&lt;/p&gt;
1464&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;await asyncio.wait([...])
1465&lt;/code&gt;&lt;/pre&gt;
1466&lt;p&gt;This method, by default, waits for the list of coroutines to run until they've all finished. You can read more on the Python &lt;a href=&quot;https://docs.python.org/3/library/asyncio-task.html#asyncio.wait&quot;&gt;documentation&lt;/a&gt;. Truly a good function to know about!&lt;/p&gt;
1467&lt;p&gt;Now whenever you have some important news for your friends, you can simply &lt;code&gt;python3 broadcast.py 'I bought a car!'&lt;/code&gt; to tell all your friends about your new car! All you need to remember is that you need to &lt;code&gt;await&lt;/code&gt; on coroutines, and you will be good. &lt;code&gt;asyncio&lt;/code&gt; will warn you when you forget to do so.&lt;/p&gt;
1468&lt;h2 id=&quot;extra_material&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#extra_material&quot;&gt;¶&lt;/a&gt;Extra Material&lt;/h2&gt;
1469&lt;p&gt;If you want to understand how &lt;code&gt;asyncio&lt;/code&gt; works under the hood, I recommend you to watch this hour-long talk &lt;a href=&quot;https://youtu.be/M-UcUs7IMIM&quot;&gt;Get to grips with asyncio in Python 3&lt;/a&gt; by Robert Smallshire. In the video, they will explain the differences between concurrency and parallelism, along with others concepts, and how to implement your own &lt;code&gt;asyncio&lt;/code&gt; &amp;quot;scheduler&amp;quot; from scratch.&lt;/p&gt;
1470&lt;/main&gt;
1471&lt;/body&gt;
1472&lt;/html&gt;
1473 </content></entry><entry><title>Sentences</title><id>dist/sentences/index.html</id><updated>2018-01-30T23:00:00+00:00</updated><published>2018-01-30T23:00:00+00:00</published><summary>Don't know English? </summary><content type="html" src="dist/sentences/index.html">&lt;!DOCTYPE html&gt;
1474&lt;html&gt;
1475&lt;head&gt;
1476&lt;meta charset=&quot;utf-8&quot; /&gt;
1477&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1478&lt;title&gt;Sentences&lt;/title&gt;
1479&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1480&lt;/head&gt;
1481&lt;body&gt;
1482&lt;main&gt;
1483&lt;h1 class=&quot;title&quot; id=&quot;sentences&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#sentences&quot;&gt;¶&lt;/a&gt;Sentences&lt;/h1&gt;
1484&lt;div class=&quot;date-created-modified&quot;&gt;2018-01-31&lt;/div&gt;
1485&lt;blockquote&gt;
1486&lt;p&gt;Don't know English? &lt;a href=&quot;spanish.html&quot;&gt;Read the Spanish version instead&lt;/a&gt;.&lt;/p&gt;
1487&lt;/blockquote&gt;
1488&lt;p&gt;Just a few sentences that I've been gathering among the years and I think are worthy of being kept somewhere.&lt;/p&gt;
1489&lt;ul&gt;
1490&lt;li&gt;So far, you've survived 100% of your worst days. You're doing great&lt;/li&gt;
1491&lt;li&gt;Money is not a concern, perfection is&lt;/li&gt;
1492&lt;li&gt;The only limit to our realization of tomorrow will be our doubts today&lt;/li&gt;
1493&lt;li&gt;Not all cultures deserve respect.&lt;/li&gt;
1494&lt;li&gt;It's not the same knowing that you're not free that not being free.&lt;/li&gt;
1495&lt;li&gt;Being alive is not a biolgical matter, rather mental.&lt;/li&gt;
1496&lt;li&gt;Every mountain starts off as a grain of sand.&lt;/li&gt;
1497&lt;li&gt;Time goes against desire.&lt;/li&gt;
1498&lt;li&gt;The only way to respect is fear.&lt;/li&gt;
1499&lt;li&gt;For those who have nothing I have so much.&lt;/li&gt;
1500&lt;li&gt;One isn't what they think, it's what they do.&lt;/li&gt;
1501&lt;li&gt;When your goal seems impossible, don't change the goal. Find new ways to get to it.&lt;/li&gt;
1502&lt;li&gt;Be the change you wish to see in the world.&lt;/li&gt;
1503&lt;li&gt;Tell me something, I'll forget. Show me something, I'll remember. But make me part of it and I'll understand it.&lt;/li&gt;
1504&lt;li&gt;If you want something to happen, go and do it. Or wait sitting like a stupid until it happens that it never happens.&lt;/li&gt;
1505&lt;li&gt;I'd rather be happy than be right.&lt;/li&gt;
1506&lt;li&gt;The engines don’t move the ship at all. The ship stays where it is and the engines move the universe around it.&lt;/li&gt;
1507&lt;li&gt;If I never try getting there, I'll never get there.&lt;/li&gt;
1508&lt;/ul&gt;
1509&lt;/main&gt;
1510&lt;/body&gt;
1511&lt;/html&gt;
1512 </content></entry><entry><title>Blog de Lonami</title><id>dist/index/index.html</id><updated>2018-01-30T23:00:00+00:00</updated><published>2016-03-03T23:00:00+00:00</published><summary>Hola | Hi.</summary><content type="html" src="dist/index/index.html">&lt;!DOCTYPE html&gt;
1513&lt;html&gt;
1514&lt;head&gt;
1515&lt;meta charset=&quot;utf-8&quot; /&gt;
1516&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1517&lt;title&gt;Blog de Lonami&lt;/title&gt;
1518&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1519&lt;/head&gt;
1520&lt;body&gt;
1521&lt;main&gt;
1522&lt;h1 class=&quot;title&quot; id=&quot;blog_de_lonami&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#blog_de_lonami&quot;&gt;¶&lt;/a&gt;Blog de Lonami&lt;/h1&gt;
1523&lt;div class=&quot;date-created-modified&quot;&gt;Created 2016-03-04&lt;br&gt;
1524Modified 2018-01-31&lt;/div&gt;
1525&lt;p&gt;Hola | Hi.&lt;/p&gt;
1526&lt;p&gt;Choose your language below:&lt;/p&gt;
1527&lt;ul&gt;
1528&lt;li&gt;&lt;a href=&quot;#bienvenido-al-blog&quot;&gt;Leer entradas en español&lt;/a&gt;&lt;/li&gt;
1529&lt;li&gt;&lt;a href=&quot;#welcome-to-the-blog&quot;&gt;Read English entries&lt;/a&gt;&lt;/li&gt;
1530&lt;/ul&gt;
1531&lt;h2 id=&quot;bienvenido_al_blog&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bienvenido_al_blog&quot;&gt;¶&lt;/a&gt;Bienvenido al blog&lt;/h2&gt;
1532&lt;p&gt;Bienvenido al mejor (o no) blog del mundo. En esta sección publicaré de manera muy puntual algunas entradas que espero resulten interesantes para el gran público.&lt;/p&gt;
1533&lt;h2 id=&quot;welcome_to_the_blog&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#welcome_to_the_blog&quot;&gt;¶&lt;/a&gt;Welcome to the blog&lt;/h2&gt;
1534&lt;p&gt;Welcome to the best (or not) blog in the entire world. On this blog I will occasionally post new entries which I find interesting.&lt;/p&gt;
1535&lt;/main&gt;
1536&lt;/body&gt;
1537&lt;/html&gt;
1538 </content></entry><entry><title>Graphs</title><id>dist/graphs/index.html</id><updated>2017-06-01T22:00:00+00:00</updated><published>2017-06-01T22:00:00+00:00</published><summary>There are a few things which won't render unless you enable</summary><content type="html" src="dist/graphs/index.html">&lt;!DOCTYPE html&gt;
1539&lt;html&gt;
1540&lt;head&gt;
1541&lt;meta charset=&quot;utf-8&quot; /&gt;
1542&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1543&lt;title&gt;Graphs&lt;/title&gt;
1544&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1545&lt;/head&gt;
1546&lt;body&gt;
1547&lt;main&gt;
1548&lt;script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async&gt;&lt;/script&gt;
1549&lt;div class=&quot;date-created-modified&quot;&gt;2017-06-02&lt;/div&gt;
1550&lt;noscript&gt;There are a few things which won't render unless you enable
1551JavaScript. No tracking, I promise!&lt;/noscript&gt;
1552&lt;h1 class=&quot;title&quot; id=&quot;graphs&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#graphs&quot;&gt;¶&lt;/a&gt;Graphs&lt;/h1&gt;
1553&lt;blockquote&gt;
1554&lt;p&gt;Don't know English? &lt;a href=&quot;spanish.html&quot;&gt;Read the Spanish version instead&lt;/a&gt;.&lt;/p&gt;
1555&lt;/blockquote&gt;
1556&lt;p&gt;Let's imagine we have 5 bus stations, which we'll denote by \(s_i\):&lt;/p&gt;
1557&lt;p&gt;(\begin{bmatrix}
1558&amp;amp; s_1 &amp;amp; s_2 &amp;amp; s_3 &amp;amp; s_4 &amp;amp; s_5 \
1559s_1   &amp;amp;   &amp;amp; V &amp;amp;   &amp;amp;   &amp;amp;       \
1560s_2   &amp;amp; V &amp;amp;   &amp;amp;   &amp;amp;   &amp;amp; V     \
1561s_3   &amp;amp;   &amp;amp;   &amp;amp;   &amp;amp; V &amp;amp;       \
1562s_4   &amp;amp;   &amp;amp; V &amp;amp; V &amp;amp;   &amp;amp;       \
1563s_5   &amp;amp; V &amp;amp;   &amp;amp;   &amp;amp; V &amp;amp; 
1564\end{bmatrix})&lt;/p&gt;
1565&lt;p&gt;This is known as a &lt;i&gt;&quot;table of direct interconnections&quot;&lt;/i&gt;.&lt;/p&gt;
1566  &lt;p&gt;The \(V\) represent connected paths. For instance, on the first
1567  row starting at \(s_1\), reaching the \(V\),
1568  allows us to turn up to get to \(s_2\).&lt;/p&gt;
1569&lt;p&gt;We can see the above table represented in a more graphical way:&lt;/p&gt;
1570  &lt;img src=&quot;example1.svg&quot; /&gt;
1571  &lt;p&gt;This type of graph is called, well, a &lt;i&gt;graph&lt;/i&gt;, and it's a directed
1572  graph (or &lt;i&gt;digraph&lt;/i&gt;), since the direction on which the arrows go does
1573  matter. It's made up of vertices, joined together by edges (also known as
1574  lines or directed &lt;b&gt;arcs&lt;/b&gt;).&lt;/p&gt;
1575&lt;p&gt;One can walk from a node to another through different &lt;b&gt;paths&lt;/b&gt;. For
1576  example, \(s_4 \rightarrow s_2 \rightarrow s_5\) is an indirect path of &lt;b&gt;order&lt;/b&gt;
1577  two, because we must use two edges to go from \(s_4\) to
1578  \(s_5\).&lt;/p&gt;
1579&lt;p&gt;Let's now represent its adjacency matrix called A which represents the
1580  same table, but uses &lt;mark&gt;1&lt;/mark&gt; instead &lt;/mark&gt;V&lt;/mark&gt; to represent
1581  a connection:&lt;/p&gt;
1582&lt;p&gt;(\begin{bmatrix}
15830 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 \
15841 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \
15850 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0 \
15860 &amp;amp; 1 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \
15871 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0
1588\end{bmatrix})&lt;/p&gt;
1589&lt;p&gt;This way we can see how the \(a_{2,1}\) element represents the
1590  connection \(s_2 \rightarrow s_1\), and the \(a_{5,1}\) element the
1591  \(s_5 \rightarrow s_1\) connection, etc.&lt;/p&gt;
1592&lt;p&gt;In general, \(a_{i,j}\) represents a connection from
1593    \(s_i \rightarrow s_j\)as long as \(a_{i,j}\geq 1\).&lt;/p&gt;
1594&lt;p&gt;Working with matrices allows us to have a computable representation of
1595  any graph, which is very useful.&lt;/p&gt;
1596&lt;hr /&gt;
1597&lt;p&gt;Graphs have a lot of interesting properties besides being representable
1598  by a computer. What would happen if, for instance, we calculated
1599  \(A^2\)? We obtain the following matrix:&lt;/p&gt;
1600&lt;p&gt;(\begin{bmatrix}
16011 &amp;amp; 0 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 \
16021 &amp;amp; 1 &amp;amp; 0 &amp;amp; 1 &amp;amp; 0 \
16030 &amp;amp; 1 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0 \
16041 &amp;amp; 0 &amp;amp; 0 &amp;amp; 1 &amp;amp; 1 \
16050 &amp;amp; 2 &amp;amp; 1 &amp;amp; 0 &amp;amp; 0
1606\end{bmatrix})&lt;/p&gt;
1607&lt;p&gt;We can interpret this as the paths of order &lt;b&gt;two&lt;/b&gt;.&lt;/p&gt;
1608  &lt;p&gt;But what does the element \(a_{5,2}=2\) represent? It indicates
1609  the amount of possible ways to go from  \(s_5 \rightarrow s_i \rightarrow s_2\).&lt;/p&gt;
1610&lt;p&gt;One can manually multiply the involved row and column to determine which
1611  element is the one we need to pass through, this way we have the row
1612  \([1 0 0 1 0]\) and the column \([1 0 0 1 0]\) (on
1613  vertical). The elements \(s_i\geq 1\) are \(s_1\) and
1614  \(s_4\). This is, we can go from \(s_5\) to
1615  \(s_2\) via \(s_5 \rightarrow s_1 \rightarrow s_2\) or via
1616  \(s_5 \rightarrow s_4 \rightarrow s_2\):&lt;/p&gt;
1617  &lt;img src=&quot;example2.svg&quot; /&gt;
1618&lt;p&gt;It's important to note that graphs to not consider self-connections, this
1619  is, \(s_i \rightarrow s_i\) is not allowed; neither we work with multigraphs
1620  here (those which allow multiple connections, for instance, an arbitrary
1621  number \(n\) of times).&lt;/p&gt;
1622&lt;p&gt;(\begin{bmatrix}
16231 &amp;amp; 1 &amp;amp; 0          &amp;amp; 1 &amp;amp; 0 \
16241 &amp;amp; 2 &amp;amp; \textbf{1} &amp;amp; 0 &amp;amp; 1 \
16251 &amp;amp; 0 &amp;amp; 0          &amp;amp; 1 &amp;amp; 1 \
16261 &amp;amp; 2 &amp;amp; 1          &amp;amp; 1 &amp;amp; 0 \
16272 &amp;amp; 0 &amp;amp; 0          &amp;amp; 1 &amp;amp; 2
1628\end{bmatrix})&lt;/p&gt;
1629&lt;p&gt;We can see how the first \(1\) just appeared on the element
1630    \(a_{2,3}\), which means that the shortest path to it is at least
1631  of order three.&lt;/mark&gt;
1632&lt;hr /&gt;
1633&lt;p&gt;A graph is said to be &lt;b&gt;strongly connected&lt;/b&gt; as long as there is a
1634  way to reach &lt;i&gt;all&lt;/i&gt; its elements.&lt;/p&gt;
1635&lt;p&gt;We can see all the available paths until now by simply adding up all the
1636  direct and indirect ways to reach a node, so for now, we can add
1637  \(A+A^2+A^3\) in such a way that:&lt;/p&gt;
1638&lt;p&gt;(\begin{bmatrix}
16392 &amp;amp; 2 &amp;amp; 0 &amp;amp; 1 &amp;amp; 1 \
16403 &amp;amp; 3 &amp;amp; 1 &amp;amp; 1 &amp;amp; 3 \
16411 &amp;amp; 1 &amp;amp; 1 &amp;amp; 2 &amp;amp; 1 \
16422 &amp;amp; 3 &amp;amp; 2 &amp;amp; 2 &amp;amp; 1 \
16433 &amp;amp; 2 &amp;amp; 1 &amp;amp; 2 &amp;amp; 2
1644\end{bmatrix})&lt;/p&gt;
1645&lt;p&gt;There isn't a connection between \(s_1\) and \(s_3\) yet.
1646  If we were to calculate \(A^4\):&lt;/p&gt;
1647&lt;p&gt;(\begin{bmatrix}
16481 &amp;amp; 2 &amp;amp; 1 &amp;amp;   &amp;amp;   \
1649&amp;amp;   &amp;amp;   &amp;amp;   &amp;amp;   \
1650&amp;amp;   &amp;amp;   &amp;amp;   &amp;amp;   \
1651&amp;amp;   &amp;amp;   &amp;amp;   &amp;amp;   \
1652&amp;amp;   &amp;amp;   &amp;amp;   &amp;amp;&lt;br /&gt;
1653\end{bmatrix})&lt;/p&gt;
1654&lt;p&gt;We don't need to calculate anymore. We now know that the graph is
1655  strongly connected!&lt;/p&gt;
1656&lt;hr /&gt;
1657&lt;p&gt;Congratulations! You've completed this tiny introduction to graphs.
1658  Now you can play around with them and design your own connections.&lt;/p&gt;
1659&lt;p&gt;Hold the left mouse button on the above area and drag it down to create
1660  a new node, or drag a node to this area to delete it.&lt;/p&gt;
1661&lt;p&gt;To create new connections, hold the right mouse button on the node you
1662  want to start with, and drag it to the node you want it to be connected to.&lt;/p&gt;
1663&lt;p&gt;To delete the connections coming from a specific node, middle click it.&lt;/p&gt;
1664&lt;table&gt;&lt;tr&gt;&lt;td style=&quot;width:100%;&quot;&gt;
1665    &lt;button onclick=&quot;resetConnections()&quot;&gt;Reset connections&lt;/button&gt;
1666    &lt;button onclick=&quot;clearNodes()&quot;&gt;Clear all the nodes&lt;/button&gt;
1667    &lt;br /&gt;
1668    &lt;br /&gt;
1669    &lt;label for=&quot;matrixOrder&quot;&gt;Show matrix of order:&lt;/label&gt;
1670    &lt;input id=&quot;matrixOrder&quot; type=&quot;number&quot; min=&quot;1&quot; max=&quot;5&quot;
1671                            value=&quot;1&quot; oninput=&quot;updateOrder()&quot;&gt;
1672    &lt;br /&gt;
1673    &lt;label for=&quot;matrixAccum&quot;&gt;Show accumulated matrix&lt;/label&gt;
1674    &lt;input id=&quot;matrixAccum&quot; type=&quot;checkbox&quot; onchange=&quot;updateOrder()&quot;&gt;
1675    &lt;br /&gt;
1676    &lt;br /&gt;
1677    &lt;div class=&quot;matrix&quot;&gt;
1678      &lt;table id=&quot;matrixTable&quot;&gt;&lt;/table&gt;
1679    &lt;/div&gt;
1680  &lt;/td&gt;&lt;td&gt;
1681    &lt;canvas id=&quot;canvas&quot; width=&quot;400&quot; height=&quot;400&quot; oncontextmenu=&quot;return false;&quot;&gt;
1682    Looks like your browser won't let you see this fancy example :(
1683    &lt;/canvas&gt;
1684    &lt;br /&gt;
1685  &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
1686&lt;script src=&quot;tinyparser.js&quot;&gt;&lt;/script&gt;
1687&lt;script src=&quot;enhancements.js&quot;&gt;&lt;/script&gt;
1688&lt;script src=&quot;graphs.js&quot;&gt;&lt;/script&gt;
1689&lt;/main&gt;
1690&lt;/body&gt;
1691&lt;/html&gt;
1692 </content></entry><entry><title>Apuntes de bachillerato de Filosofía</title><id>dist/filosofia/index.html</id><updated>2016-06-20T22:00:00+00:00</updated><published>2016-06-20T22:00:00+00:00</published><summary>Hay asignaturas que merecen la pena, y una de ellas es la filosofía. De verdad. Aprendes un montón de cosas y abres tu mente, comparas muchos puntos de vista y te das cuenta de grandes cosas. Por eso, quiero compartir mis apuntes con todo aquel interesado.</summary><content type="html" src="dist/filosofia/index.html">&lt;!DOCTYPE html&gt;
1693&lt;html&gt;
1694&lt;head&gt;
1695&lt;meta charset=&quot;utf-8&quot; /&gt;
1696&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1697&lt;title&gt;Apuntes de bachillerato de Filosofía&lt;/title&gt;
1698&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1699&lt;/head&gt;
1700&lt;body&gt;
1701&lt;main&gt;
1702&lt;h1 class=&quot;title&quot; id=&quot;apuntes_de_bachillerato_de_filosofía&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#apuntes_de_bachillerato_de_filosofía&quot;&gt;¶&lt;/a&gt;Apuntes de bachillerato de Filosofía&lt;/h1&gt;
1703&lt;div class=&quot;date-created-modified&quot;&gt;2016-06-21&lt;/div&gt;
1704&lt;p&gt;Hay asignaturas que merecen la pena, y una de ellas es la filosofía. De verdad. Aprendes un montón de cosas y abres tu mente, comparas muchos puntos de vista y te das cuenta de grandes cosas. Por eso, quiero compartir mis apuntes con todo aquel interesado.&lt;/p&gt;
1705&lt;p&gt;Personalmente, mi autor favorito es Friedrich Nietzsche (se pronuncia &lt;em&gt;/niche/&lt;/em&gt;). Está en el tercer trimestre, el más interesante, aunque si prefieres algo de contexto, te recomiendo leerlo todo. Puedes leerlo como si fuera un libro cualquiera:&lt;/p&gt;
1706&lt;ul&gt;
1707&lt;li&gt;Descargar en .pdf
1708&lt;ul&gt;
1709&lt;li&gt;&lt;a href=&quot;filo_trimestre1.pdf&quot;&gt;Filosofía - Primer trimestre&lt;/a&gt;&lt;/li&gt;
1710&lt;li&gt;&lt;a href=&quot;filo_trimestre2.pdf&quot;&gt;Filosofía - Segundo trimestre&lt;/a&gt;&lt;/li&gt;
1711&lt;li&gt;&lt;a href=&quot;filo_trimestre3.pdf&quot;&gt;Filosofía - Tercer trimestre&lt;/a&gt;&lt;/li&gt;
1712&lt;/ul&gt;
1713&lt;/li&gt;
1714&lt;li&gt;Descargar en .odt (lo puedes editar)
1715&lt;ul&gt;
1716&lt;li&gt;&lt;a href=&quot;filo_trimestre1.odt&quot;&gt;Filosofía - Primer trimestre&lt;/a&gt;&lt;/li&gt;
1717&lt;li&gt;&lt;a href=&quot;filo_trimestre2.odt&quot;&gt;Filosofía - Segundo trimestre&lt;/a&gt;&lt;/li&gt;
1718&lt;li&gt;&lt;a href=&quot;filo_trimestre3.odt&quot;&gt;Filosofía - Tercer trimestre&lt;/a&gt;&lt;/li&gt;
1719&lt;/ul&gt;
1720&lt;/li&gt;
1721&lt;/ul&gt;
1722&lt;p&gt;Nota: Hay algunas palabras un tanto soez. ¡Añaden emoción y no son para tanto, a lo sumo dos o tres! :)&lt;/p&gt;
1723&lt;/main&gt;
1724&lt;/body&gt;
1725&lt;/html&gt;
1726 </content></entry><entry><title>Reflexión sobre la Inteligencia artificial</title><id>dist/reflexion_ia/index.html</id><updated>2016-06-12T22:00:00+00:00</updated><published>2016-06-12T22:00:00+00:00</published><summary>Nota: esta reflexión ha sido sacada de una conversación en Telegram, aunque ha sido lo más adaptada posible a formato de blog.</summary><content type="html" src="dist/reflexion_ia/index.html">&lt;!DOCTYPE html&gt;
1727&lt;html&gt;
1728&lt;head&gt;
1729&lt;meta charset=&quot;utf-8&quot; /&gt;
1730&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1731&lt;title&gt;Reflexión sobre la Inteligencia artificial&lt;/title&gt;
1732&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1733&lt;/head&gt;
1734&lt;body&gt;
1735&lt;main&gt;
1736&lt;h1 class=&quot;title&quot; id=&quot;reflexión_sobre_la_inteligencia_artificial&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reflexión_sobre_la_inteligencia_artificial&quot;&gt;¶&lt;/a&gt;Reflexión sobre la Inteligencia artificial&lt;/h1&gt;
1737&lt;div class=&quot;date-created-modified&quot;&gt;2016-06-13&lt;/div&gt;
1738&lt;blockquote&gt;
1739&lt;p&gt;Nota: esta reflexión ha sido sacada de una conversación en Telegram, aunque ha sido lo más adaptada posible a formato de blog.&lt;/p&gt;
1740&lt;/blockquote&gt;
1741&lt;h2 id=&quot;conversación_del_12_03_16&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conversación_del_12_03_16&quot;&gt;¶&lt;/a&gt;Conversación del 12.03.16&lt;/h2&gt;
1742&lt;p&gt;Pienso que para conseguir una verdadera inteligencia artificial debemos abstraernos mucho. Es decir, siempre hay una pequeña parte de &lt;em&gt;Pero es que el ser humano, los sentimientos, tal, cual&lt;/em&gt;... Igual simplemente, absolutamente todo esté programado. Cuando actúas de manera que no sabes por qué por ejemplo, seguramente sea una serie de estímulos adecuados que producen esa respuesta porque se ha formado ese camino de neuronas en tu mente. Por ejemplo, el arco reflejo, que es un arco innato.&lt;/p&gt;
1743&lt;ul&gt;
1744&lt;li&gt;&lt;em&gt;Sensación de quemar → retirar&lt;/em&gt;&lt;/li&gt;
1745&lt;li&gt;&lt;em&gt;&lt;a href=&quot;https://es.wikipedia.org/wiki/Condicionamiento_cl%C3%A1sico&quot;&gt;Un estímulo X → una respuesta Y&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
1746&lt;/ul&gt;
1747&lt;p&gt;Es una ida y vuelta instantanea entre sensación y respuesta. El cerebro simplemente es capaz de trabajar con combinaciones más complejas, como por ejemplo la suma, este número con este otro → sale otro número, y se le añade a otro... Hay una especie de &lt;a href=&quot;https://es.wikipedia.org/wiki/Recursi%C3%B3n&quot;&gt;recursión&lt;/a&gt; también, aunque en realidad es que es el mismo estímulo el que &lt;a href=&quot;https://es.wikipedia.org/wiki/M%C3%A9todo_%28inform%C3%A1tica%29&quot;&gt;&amp;quot;llama&amp;quot;&lt;/a&gt; a un determinado camino.&lt;/p&gt;
1748&lt;p&gt;Pero lo verdaderamente impresionante es la consciencia, igual no tenemos consciencia de verdad, igual es como lo sentimos. Siempre nos han hablado de la consciencia pero nadie ha sabido probarla, por lo que sólo tenemos una idea, un concepto. Es aún más impresionante es el hecho de recordar y &lt;a href=&quot;https://es.wikipedia.org/wiki/Memoria_de_trabajo&quot;&gt;trabajar&lt;/a&gt; con la información.&lt;/p&gt;
1749&lt;p&gt;Cuando hablamos de consciencia, estamos simplemente tratando información sobre esa misma información, ¿cómo cojones sentimos lo que pensamos? Yo sé que estoy pensando porque hemos definido &lt;em&gt;pensar&lt;/em&gt; como este proceso. ¿Pero cómo coño entiendo yo eso? Es decir, ¿cómo me doy cuenta? por qué lo situo en mi cabeza? Probablemente, aunque el cerebro esté trabajando con todo eso, la sensación sea externa a nosotros, es decir, ocurre en mi cabeza. ¿Pero de verdad lo siento en mi cabeza?&lt;/p&gt;
1750&lt;p&gt;Me estoy rayando.&lt;/p&gt;
1751&lt;p&gt;El verdadero problema está en saber cómo sabemos que estamos pensando. El cerebro se compone de neuronas y conexiones, esa es la base a parte de donde se encuentra todo y tal la base es esa, y las sensaciones táctiles son igual de complejas, las procesa mi cerebro pero las siento en mi mano. ¿Será cosa de costumbre? Yo siento algo y lo situo ahí. Sin embargo sentimos ahí y no por encima o por debajo de, vamos a poner, los dedos de la mano, lo siento justo ahí. ¿Qué coño es realmente la &lt;a href=&quot;https://es.wikipedia.org/wiki/Memoria_a_corto_plazo&quot;&gt;memoria a corto plazo&lt;/a&gt;? (porque lo de la &lt;a href=&quot;https://es.wikipedia.org/wiki/Memoria_a_largo_plazo&quot;&gt;memoria a largo plazo&lt;/a&gt; se traslada ahí cuando la necesitamos para trabajar con ella, por eso es &lt;em&gt;MCP&lt;/em&gt; o memoria de trabajo según ciertas teorías).&lt;/p&gt;
1752&lt;p&gt;En fin.&lt;/p&gt;
1753&lt;/main&gt;
1754&lt;/body&gt;
1755&lt;/html&gt;
1756 </content></entry><entry><title>Inteligencia artificial</title><id>dist/inteligencia_artificial/index.html</id><updated>2016-03-04T23:00:00+00:00</updated><published>2016-02-23T23:00:00+00:00</published><summary>La inteligencia artificial es una rama apasionante que tiene su origen en la </summary><content type="html" src="dist/inteligencia_artificial/index.html">&lt;!DOCTYPE html&gt;
1757&lt;html&gt;
1758&lt;head&gt;
1759&lt;meta charset=&quot;utf-8&quot; /&gt;
1760&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
1761&lt;title&gt;Inteligencia artificial&lt;/title&gt;
1762&lt;link rel=&quot;stylesheet&quot; href=&quot;../css/style.css&quot;&gt;
1763&lt;/head&gt;
1764&lt;body&gt;
1765&lt;main&gt;
1766&lt;h1 class=&quot;title&quot; id=&quot;inteligencia_artificial&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#inteligencia_artificial&quot;&gt;¶&lt;/a&gt;Inteligencia artificial&lt;/h1&gt;
1767&lt;div class=&quot;date-created-modified&quot;&gt;Created 2016-02-24&lt;br&gt;
1768Modified 2016-03-05&lt;/div&gt;
1769&lt;h2 id=&quot;índice&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#índice&quot;&gt;¶&lt;/a&gt;Índice&lt;/h2&gt;
1770&lt;ul&gt;
1771&lt;li&gt;&lt;a href=&quot;#qu%C3%A9_es&quot;&gt;Qué es&lt;/a&gt;&lt;/li&gt;
1772&lt;li&gt;&lt;a href=&quot;#en_qu%C3%A9_consiste&quot;&gt;En qué consiste&lt;/a&gt;&lt;/li&gt;
1773&lt;li&gt;&lt;a href=&quot;#l%C3%ADmites&quot;&gt;Límites&lt;/a&gt;&lt;/li&gt;
1774&lt;li&gt;&lt;a href=&quot;#tipos_de_inteligencia_artificial&quot;&gt;Tipos de inteligencia artificial&lt;/a&gt;&lt;/li&gt;
1775&lt;li&gt;&lt;a href=&quot;#aplicaciones_pr%C3%A1cticas&quot;&gt;Aplicaciones prácticas&lt;/a&gt;&lt;/li&gt;
1776&lt;li&gt;&lt;a href=&quot;#implicaciones_%C3%A9ticas&quot;&gt;Implicaciones éticas&lt;/a&gt;&lt;/li&gt;
1777&lt;li&gt;&lt;a href=&quot;#ejemplos&quot;&gt;Ejemplos&lt;/a&gt;&lt;/li&gt;
1778&lt;li&gt;&lt;a href=&quot;#conceptos&quot;&gt;Conceptos&lt;/a&gt;&lt;/li&gt;
1779&lt;li&gt;&lt;a href=&quot;#fuentes&quot;&gt;Fuentes&lt;/a&gt;&lt;/li&gt;
1780&lt;/ul&gt;
1781&lt;h2 id=&quot;qué_es&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#qué_es&quot;&gt;¶&lt;/a&gt;Qué es&lt;/h2&gt;
1782&lt;p&gt;La inteligencia artificial es una rama apasionante que tiene su origen en la &lt;strong&gt;informática&lt;/strong&gt; y se basa en el concepto de conseguir &lt;em&gt;emular&lt;/em&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.1&quot;&gt;&lt;a href=&quot;#f.1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; al cerebro humano, mediante el desarrollo un programa que sea capaz de &lt;strong&gt;aprender y mejorar por sí sólo&lt;/strong&gt; (normalmente bajo algún tipo de supervisión)&lt;/p&gt;
1783&lt;p&gt;Fue un concepto acuñado por &lt;em&gt;John McCarthy&lt;/em&gt; en un congreso de informática de 1956, y desde entonces este campo ha crecido de manera exponencial con unas buenas previsiones de futuro.&lt;/p&gt;&lt;/p&gt;
1784&lt;div class=&quot;image-container&quot;&gt;
1785&lt;img src=&quot;human_progress_edge.svg&quot; alt=&quot;Progreso humano en la inteligencia artificial&quot; /&gt;
1786&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1787&lt;/div&gt;
1788&lt;p&gt;
1789&lt;p&gt;&lt;em&gt;Progreso humano en la inteligencia artificial. &lt;a href=&quot;http://waitbutwhy.com/2015/01/artificial-intelligence-revolution-1&quot;&gt;Fuente&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
1790&lt;h2 id=&quot;en_qué_consiste&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#en_qué_consiste&quot;&gt;¶&lt;/a&gt;En qué consiste&lt;/h2&gt;
1791&lt;p&gt;La inteligencia artificial no consiste en escribir unas pautas fijas y finitas al igual que hacen la gran mayoría de programas, en los cuales introduces unos datos y producen siempre la misma salida, una salida predecible, programada e invariable, que además, tiene sus límites, ya que si introduces datos para los que la aplicación no está programada, esta aplicación no será capaz de manejarlos. No los entenderá y no producirá ningún resultado.&lt;/p&gt;
1792&lt;p&gt;La inteligencia artificial consiste en dar un paso &lt;strong&gt;más allá&lt;/strong&gt;. Una inteligencia artificial &lt;em&gt;entrenada&lt;/em&gt; es capaz de manejar datos para los cuales no ha sido programada de manera explícita&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.2&quot;&gt;&lt;a href=&quot;#f.2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/sup&gt;&lt;/p&gt;
1793&lt;h2 id=&quot;límites&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#límites&quot;&gt;¶&lt;/a&gt;Límites&lt;/h2&gt;
1794&lt;p&gt;Actualmente, la inteligencia artificial se ve limitada por la velocidad y capacidad de los dispositivos (ordenadores, teléfonos inteligentes).&lt;/p&gt;
1795&lt;p&gt;A día de hoy, ya hemos conseguido emular el cerebro de un gusano de un milímetro de longitud, que consiste de un total de trescientas dos neuronas. El &lt;strong&gt;cerebro humano&lt;/strong&gt; contiene unas &lt;strong&gt;cien mil millones de neuronas&lt;/strong&gt;.&lt;/p&gt;
1796&lt;div class=&quot;image-container&quot;&gt;
1797&lt;img src=&quot;exponential_grow.gif&quot; alt=&quot;Progreso en la velocidad de los dispositivos&quot; /&gt;
1798&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1799&lt;/div&gt;
1800&lt;p&gt;
1801&lt;p&gt;&lt;em&gt;Crecimiento en la velocidad de procesado de los dispositivos. &lt;a href=&quot;http://waitbutwhy.com/2015/01/artificial-intelligence-revolution-1&quot;&gt;Fuente&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
1802&lt;p&gt;Comparado con las neuronas de un cerebro humano (cuya velocidad&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.3&quot;&gt;&lt;a href=&quot;#f.3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; máxima oscilan entre los 200Hz), los procesadores de hoy en día (mucho más lentos que los que tendremos dentro de algunos años) ya tienen una velocidad superior a los 2Ghz, es decir, &lt;strong&gt;10 millones de veces&lt;/strong&gt; más rápidos que las neuronas. Y la comunicación interna del cerebro, que oscila entre los 120m/s, queda infinitamente distante de la velocidad de los ordenadores que se comunican de manera óptica a la &lt;strong&gt;velocidad de la luz&lt;/strong&gt;.&lt;/p&gt;
1803&lt;p&gt;Además de todo esto, la capacidad de los dispositivos puede ser &lt;strong&gt;ampliada&lt;/strong&gt;, a diferencia del cerebro que tiene un tamaño ya determinado. Y, por último, un procesador puede estar &lt;strong&gt;trabajando sin parar&lt;/strong&gt; nunca, sin cansarse.&lt;/p&gt;&lt;/p&gt;
1804&lt;!-- Boston dynamics artificial intelligence put some more examples, like Google or predicting models or big data, ocr --&gt;
1805&lt;h2 id=&quot;tipos_de_inteligencia_artificial&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tipos_de_inteligencia_artificial&quot;&gt;¶&lt;/a&gt;Tipos de inteligencia artificial&lt;/h2&gt;
1806&lt;h3 id=&quot;según_el_tipo_de_aprendizaje&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#según_el_tipo_de_aprendizaje&quot;&gt;¶&lt;/a&gt;Según el tipo de aprendizaje&lt;/h3&gt;
1807&lt;ul&gt;
1808&lt;li&gt;&lt;strong&gt;Aprendizaje supervisado&lt;/strong&gt;: se le presenta una entrada de datos y produce una salida de los datos procesados, y un &amp;quot;tutor&amp;quot; es el que determina si la salida es correcta o no.&lt;/li&gt;
1809&lt;li&gt;&lt;strong&gt;Aprendizaje sin supervisar&lt;/strong&gt;: se le presenta una entrada de datos sin presentarle ningún otro tipo de información, para que encuentre la estructura de los datos por sí sóla.&lt;/li&gt;
1810&lt;li&gt;&lt;strong&gt;Aprendizaje por refuerzo&lt;/strong&gt;: un ordenador interactua con un entorno variable en el que debe llevar a cabo una tarea concreta, sin que un tutor le indique cómo explícitamente.&lt;/li&gt;
1811&lt;/ul&gt;
1812&lt;h3 id=&quot;según_la_forma_de_llevarlo_a_cabo_principales_métodos_&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#según_la_forma_de_llevarlo_a_cabo_principales_métodos_&quot;&gt;¶&lt;/a&gt;Según la forma de llevarlo a cabo (principales métodos)&lt;/h3&gt;
1813&lt;ul&gt;
1814&lt;li&gt;
1815&lt;p&gt;&lt;strong&gt;Aprendizaje por árbol de decisiones&lt;/strong&gt;. Este aprendizaje usa un árbol de decisiones, que almacena observaciones y conclusiones.&lt;/p&gt;
1816&lt;div class=&quot;image-container&quot;&gt;
1817&lt;img src=&quot;decision_tree.svg&quot; alt=&quot;Árbol de decisiones&quot; /&gt;
1818&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1819&lt;/div&gt;
1820&lt;p&gt;
1821&lt;/li&gt;
1822&lt;li&gt;
1823&lt;p&gt;&lt;strong&gt;Aprendizaje por asociación de reglas&lt;/strong&gt;. Utilizado para descubrir relaciones en grandes bases de datos&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.4&quot;&gt;&lt;a href=&quot;#f.4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
1824&lt;/li&gt;
1825&lt;li&gt;
1826&lt;p&gt;&lt;strong&gt;Red neuronal artificial (RNA)&lt;/strong&gt;. Inspirado en redes neuronales biológicas**. Los cálculos se estructuran en un grupo de neuronas artificiales interconectadas.&lt;/p&gt;
1827&lt;/li&gt;
1828&lt;li&gt;
1829&lt;p&gt;&lt;strong&gt;Programación lógica inductiva (PLI)&lt;/strong&gt;. Se aproxima de manera hipotética, dado un transfondo lógico y una entrada, a una solución que no se le había presentado antes.&lt;/p&gt;
1830&lt;/li&gt;
1831&lt;li&gt;
1832&lt;p&gt;&lt;strong&gt;Máquinas de soporte vectorial (MSV)&lt;/strong&gt;. Se usan para clasificar y problemas que necesitan de regresión&lt;sup class=&quot;footnote-reference&quot; id=&quot;r.5&quot;&gt;&lt;a href=&quot;#f.5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;. Dado una serie de ejemplos, una entrada será clasificada de una forma u otra.&lt;/p&gt;
1833&lt;/li&gt;
1834&lt;li&gt;
1835&lt;p&gt;&lt;em&gt;&lt;strong&gt;Clustering&lt;/strong&gt;&lt;/em&gt;. Este tipo de análisis consiste en asignar observaciones a ciertas subcategorías (denominadas &lt;em&gt;clústeres&lt;/em&gt;), para que aquellas que están en el mismo &lt;em&gt;clúster&lt;/em&gt; sean similares**. Este tipo de aprendizaje es una técnica común en análisis estadístico.&lt;/p&gt;
1836&lt;/li&gt;
1837&lt;li&gt;
1838&lt;p&gt;&lt;strong&gt;Redes bayesianas&lt;/strong&gt;. Es un modelo probabilístico que organiza variables al azar según unas determinadas condiciones mediante un gráfico**. Un ejemplo de red bayesiana es el siguiente:&lt;/p&gt;
1839&lt;div class=&quot;image-container&quot;&gt;
1840&lt;img src=&quot;bayesian_network.svg&quot; alt=&quot;Red bayesiana&quot; /&gt;
1841&lt;div class=&quot;image-caption&quot;&gt;&lt;/div&gt;
1842&lt;/div&gt;
1843&lt;p&gt;
1844&lt;/li&gt;
1845&lt;li&gt;
1846&lt;p&gt;&lt;strong&gt;Algoritmos genéticos&lt;/strong&gt;. Imita el proceso evolutivo de la selección natural, y usa métodos como la mutación para generar nuevos &amp;quot;genotipos&amp;quot; que, con algo de suerte, serán mejores en encontrar la solución correcta.&lt;/p&gt;
1847&lt;/li&gt;
1848&lt;/ul&gt;
1849&lt;h2 id=&quot;aplicaciones_prácticas&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#aplicaciones_prácticas&quot;&gt;¶&lt;/a&gt;Aplicaciones prácticas&lt;/h2&gt;
1850&lt;p&gt;La inteligencia artificial ya se encuentra desde hace algún tiempo entre nosotros, como por ejemplo el archiconocido &lt;strong&gt;buscador Google&lt;/strong&gt;, que filtra los resultados más relevantes mediante una inteligencia artificial. Otros ejemplos son el reconocimiento de caracteres a partir de una foto, o incluso reconocimiento del habla con &lt;strong&gt;asistentes virtuales como Cortana o Siri&lt;/strong&gt;, en los videojuegos, en bolsa, en los &lt;strong&gt;hospitales&lt;/strong&gt;, industria pesada, transportes, juguetes, música, aviación, robótica, filtros anti-spam... y un largo etcétera.&lt;/p&gt;
1851&lt;h2 id=&quot;implicaciones_éticas&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#implicaciones_éticas&quot;&gt;¶&lt;/a&gt;Implicaciones éticas&lt;/h2&gt;
1852&lt;p&gt;Una vez tengamos la tecnología necesaria para recrear un cerebro humano, si enseñáramos a esta inteligencia artificial al igual que un humano, ¿llegaría a tener &lt;strong&gt;sentimientos&lt;/strong&gt;? ¿Sería consciente de su existencia? ¿Podría sentir felicidad, alegría, tristeza, enfado? ¿Tendría &lt;strong&gt;creatividad&lt;/strong&gt;? ¿Derecho a propiedad? Si la respuesta es que sí, y es la respuesta más lógica, significa que, en realidad, los sentimientos no son nada más que una manera de entender las cosas. No tienen valor por sí mismos. Seríamos capaces de recrearlos, y tendrían el mismo valor que un sentimiento humano, aunque esa inteligencia viviera dentro de un ordenador. Y acabar con esta inteligencia sería acabar con esta vida, &lt;strong&gt;una vida&lt;/strong&gt; casi, por no decir enteramente, &lt;strong&gt;humana&lt;/strong&gt;. Además, todo esto implicaría que todo comportamiento humano es predecible. Por último, si esta inteligencia es realmente como un humano, al utilizarla, ¿la estaríamos esclavizando al obligarla a trabajar para nosotros? ¿En qué momento dejaremos de llamarlos &amp;quot;ordenadores&amp;quot; y comenzaremos a tratarles como &amp;quot;humanos&amp;quot;? ¿Será la humanidad capaz de adaptarse al cambio?&lt;/p&gt;
1853&lt;!-- ¿y si sólo somos cerebro y logramos recrearlo? ¿tendría sentimientos? --&gt;
1854&lt;h2 id=&quot;ejemplos&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#ejemplos&quot;&gt;¶&lt;/a&gt;Ejemplos&lt;/h2&gt;
1855&lt;p&gt;En el siguiente algorítmo genético podemos ver como una figura aprende a saltar, obedeciendo a las leyes físicas (ver en &lt;a href=&quot;https://youtu.be/Gl3EjiVlz_4&quot;&gt;YouTube&lt;/a&gt;):&lt;/p&gt;
1856&lt;iframe width=&quot;420&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Gl3EjiVlz_4&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1857&lt;p&gt;Por el contrario, en el siguiente ejemplo, un algorítmo genético aprende a &amp;quot;luchar&amp;quot; contra otra figura: (ver en &lt;a href=&quot;https://youtu.be/u2t77mQmJiY&quot;&gt;YouTube&lt;/a&gt;):&lt;/p&gt;
1858&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/u2t77mQmJiY&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1859&lt;p&gt;Estos cuatro increíbles ejemplos siguientes muestran un proceso evolutivo similar al sufrido por cualquier tipo de ser (ver en &lt;a href=&quot;https://youtu.be/GOFws_hhZs8&quot;&gt;YouTube&lt;/a&gt;):&lt;/p&gt;
1860&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/GOFws_hhZs8&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1861&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/31dsH2Fs1IQ&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1862&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/IVcvvqxtNwE&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1863&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/KrTbJUJsDSw&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
1864&lt;h2 id=&quot;conceptos&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conceptos&quot;&gt;¶&lt;/a&gt;Conceptos&lt;/h2&gt;
1865&lt;p class=&quot;footnote&quot; id=&quot;f.1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt; &lt;strong&gt;Emular&lt;/strong&gt;. Tratar de imitar un modelo, aproximarse a este. Copiar su comportamiento o incluso mejorarlo. &lt;a href=&quot;#r.1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1866
1867&lt;p class=&quot;footnote&quot; id=&quot;f.2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt; &lt;strong&gt;Explícito&lt;/strong&gt;. Suceso que ocurre de manera previamente avisada de una forma directa, anticipado &lt;em&gt;sin rodeos&lt;/em&gt;. &lt;a href=&quot;#r.2&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1868
1869&lt;p class=&quot;footnote&quot; id=&quot;f.3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt; &lt;strong&gt;Velocidad (en hercios)&lt;/strong&gt;. Número de cálculos realizados por segundo. Un procesador con una velocidad de 100Hz es capaz de realizar 100 cálculos por segundo. &lt;a href=&quot;#r.3&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1870
1871&lt;p class=&quot;footnote&quot; id=&quot;f.4&quot;&gt;&lt;sup&gt;4&lt;/sup&gt; &lt;strong&gt;Base de datos&lt;/strong&gt;. Lugar en el que se almacena de manera estructurada una información, como por ejemplo un censo que indique el nombre de las personas, sus apellidos, edad, etcétera. &lt;a href=&quot;#r.4&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1872
1873&lt;p class=&quot;footnote&quot; id=&quot;f.5&quot;&gt;&lt;sup&gt;5&lt;/sup&gt; &lt;strong&gt;Regresión&lt;/strong&gt;. Las pruebas de regresión consisten en someter a un programa a una serie de pruebas para descubrir fallos en este cometidos accidentalmente con anterioridad en versiones anteriores. &lt;a href=&quot;#r.5&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
1874
1875&lt;h2 id=&quot;fuentes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#fuentes&quot;&gt;¶&lt;/a&gt;Fuentes&lt;/h2&gt;
1876&lt;ul&gt;
1877&lt;li&gt;&lt;a href=&quot;http://waitbutwhy.com/2015/01/artificial-intelligence-revolution-1&quot;&gt;Evolución de la inteligencia artificial - Wait but why&lt;/a&gt;&lt;/li&gt;
1878&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Machine_learning&quot;&gt;&lt;em&gt;Machine learning&lt;/em&gt; - Wikipedia&lt;/a&gt;&lt;/li&gt;
1879&lt;/ul&gt;
1880&lt;/main&gt;
1881&lt;/body&gt;
1882&lt;/html&gt;
1883 </content></entry></feed>