<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luciano Muñoz</title>
    <description>The latest articles on DEV Community by Luciano Muñoz (@luciano_dev).</description>
    <link>https://dev.to/luciano_dev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F380087%2F44fc10f9-c38b-49db-ac79-b78f6800ca0e.png</url>
      <title>DEV Community: Luciano Muñoz</title>
      <link>https://dev.to/luciano_dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luciano_dev"/>
    <language>en</language>
    <item>
      <title>CS50: Week 5, Data Structures</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Sat, 10 Sep 2022 12:26:26 +0000</pubDate>
      <link>https://dev.to/luciano_dev/cs50-week-5-data-structures-3ipo</link>
      <guid>https://dev.to/luciano_dev/cs50-week-5-data-structures-3ipo</guid>
      <description>&lt;p&gt;&lt;em&gt;Three months have passed since I wrote my last post. I’ve finished the CS50 course on time, but work and life made me choose others than writing, but I wanted to recover the feeling of doing something for the dev community, so here we go again… Finishing the CS50 series with this post! I hope you enjoy it.&lt;/em&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;In past lessons, we’ve learned about memory, and we’ve been working with &lt;strong&gt;arrays&lt;/strong&gt;. The problem with arrays to store a large amount of data is that they have fixed size and their values are stored in contiguous memory addresses, so if you want to add a new item you have to allocate a new block of memory with enough space for the new array, copy value by value including the new element, and lastly, delete the old array. Arrays offer constant time &lt;code&gt;O(1)&lt;/code&gt; for lookup thanks to random access, but they’re bad for inserting/deleting an element, especially when we are working with large arrays because copy value by value takes linear time &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;br&gt; Linked Lists
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;linked list&lt;/strong&gt; is a data structure that, unlike arrays, it allows us to store a list of values in different parts of memory, giving us a better time complexity for inserting new values.&lt;/p&gt;

&lt;p&gt;With linked lists doesn’t matter where the data is stored, we can use small chunks of free memory for each node, stitching them together with pointers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MIooEvlA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1asl7hj5858l3ssny4o7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MIooEvlA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1asl7hj5858l3ssny4o7.png" alt="How linked list looks in memory" width="880" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have the tradeoff of needing to allocate more memory for each item (for its value and the pointer to the next element), in order to spend less time adding values, because you don’t need all the copy process arrays to do to add an element.&lt;/p&gt;

&lt;p&gt;Linked lists are composed of nodes that store its &lt;em&gt;value&lt;/em&gt; and the pointer to the &lt;em&gt;next&lt;/em&gt; element of the list. We could define a node in C like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Linked lists usually have a property called &lt;code&gt;head&lt;/code&gt;, which is a pointer to the first node of the list. Each time we want to add a new node to the list, we just make the new node point to the current head element, and then make &lt;code&gt;head&lt;/code&gt; point to the new node. In this way we are inserting new nodes at the beginning of the list, which takes constant time &lt;code&gt;O(1)&lt;/code&gt; since the required steps don’t change doesn’t matter how many items the list has. On the other hand, inserting nodes into a sorted list will have a running time of &lt;code&gt;O(n)&lt;/code&gt;, since we might need to insert our nodes at the end.&lt;/p&gt;

&lt;p&gt;Unlike arrays, searching is not a powerful feature of linked lists, we have a running time of &lt;code&gt;O(n)&lt;/code&gt; for searching since we need to follow each node, one at a time, to search for a value. We won’t be able to use binary search either, since we can’t use indexes to access elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Binary Trees
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;tree&lt;/strong&gt; is another data structure where each node points to other nodes. It allows us to store a list of values in different parts of memory, just like linked lists. But, preserves the searching power of arrays, allowing us to use Binary search (divide and conquer approach), since each node points to one to the left (with a smaller value) and one to the right (with a larger value).&lt;/p&gt;

&lt;p&gt;Every left child is smaller than the root, and every right child is larger than the root, as we can see in the picture below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2dyaF6aB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khy5kw98ds2rocpz2vjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2dyaF6aB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/khy5kw98ds2rocpz2vjc.png" alt="How binary trees looks" width="880" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each node has at most two &lt;strong&gt;children&lt;/strong&gt;, or nodes it is pointing to. And like a linked list, we’ll want to keep a &lt;code&gt;header&lt;/code&gt; pointer to the beginning of the list, the &lt;strong&gt;root&lt;/strong&gt; of the tree. To search for a number, we’ll start at the root node, and be able to recursively search the left or right subtree.&lt;/p&gt;

&lt;p&gt;We can define a node in C like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we add nodes in inefficient ways, though, our binary search tree might start to look like a linked list:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_AZ5OPt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35kgb5jj3l998d3udetb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_AZ5OPt4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35kgb5jj3l998d3udetb.png" alt="Inefficient binary tree" width="589" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can make the tree balanced, or more optimal, by making the node with value &lt;code&gt;2&lt;/code&gt; the new root node.&lt;/p&gt;

&lt;p&gt;With a balanced binary search tree, the running time for search and insert will be &lt;code&gt;O(log⁡ n)&lt;/code&gt;. But if our tree isn’t balanced, it can devolve into a linked list, with running time for search and insert of &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Binary trees are used for efficient searching and sorting.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Hash Table
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;hash table&lt;/strong&gt; is a data structure that allows us to associate keys with values. It looks like an array, where we can jump to each location by its index (&lt;em&gt;key&lt;/em&gt;). Keys are hashed and converted into an index where we can find the value stored.&lt;/p&gt;

&lt;p&gt;If we need to implement a phone book, we could think of each location as a letter from A through Z, and insert names into each location. If we have multiple names with the same first letter, we can add them with a linked list, like this. Using a linked list to store values is a method to solve hash collisions, and is called &lt;em&gt;chaining&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0w1G_ZrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4ehfw2atpad7tuijetv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0w1G_ZrT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h4ehfw2atpad7tuijetv.png" alt="How a hash table looks like" width="880" height="1040"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create the hash table in C, we might write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;hash_table&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NUMBER_OF_BUCKETS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since a hash table is just an array of pointers to nodes, with &lt;code&gt;NUMBER_OF_BUCKETS&lt;/code&gt; as its size.&lt;/p&gt;

&lt;p&gt;To decide which location in the array a value should be placed in, we use a &lt;strong&gt;hash function&lt;/strong&gt;, which takes some input and produces an index. &lt;/p&gt;

&lt;p&gt;It turns out that the worst case running time for searching a hash table is &lt;code&gt;O(n)&lt;/code&gt; since all of our values might be in the same location, devolving into a linked list as well. But, on average the running time is constant &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hash tables are used for database indexes, implementing caches, implementing set data structures, etc. And offer constant time for adding, removeing, and lookup elements. But they’re not an ideal data structure if sorting is the goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Trie
&lt;/h3&gt;

&lt;p&gt;A trie is a tree with arrays as nodes. It gives us constant time lookup, even for massive datasets. Supposing we are looking to store names:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mThk0tAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iwynw8l83g0bb6b5pdz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mThk0tAd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iwynw8l83g0bb6b5pdz.png" alt="Array to create a trie" width="714" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each array will have locations that represent each letter, A-Z.&lt;/p&gt;

&lt;p&gt;For each word, the first letter will point to an array, where the next valid letter will point to another array, and so on, until we reach a boolean value indicating the end of a valid word, marked in green:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ST9AjWPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1i55dz5sa9ms1blx8c7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ST9AjWPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1i55dz5sa9ms1blx8c7a.png" alt="How a trie looks like" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With multiple names, we start seeing some of the space being reused for the first letters that are shared:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aklgIzpa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zxexmbxtangqzpv0rw3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aklgIzpa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zxexmbxtangqzpv0rw3.png" alt="Increasing a trie length" width="880" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We might define a trie in code with a structure like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;is_word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;children&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SIZE_OF_ALPHABET&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At each node, we’ll have a boolean value that indicates if it’s a valid word. Then, we’ll have an array of &lt;code&gt;SIZE_OF_ALPHABET&lt;/code&gt; pointers to other nodes, called &lt;code&gt;children&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The good thing is that the height of our trie is the length of the longest word we want to store. &lt;/p&gt;

&lt;p&gt;And even if our data structure has lots of words, the maximum lookup time will be just the length of the word we’re looking for. Doesn’t matter how many names contain the trie, will always take 5 steps to find the name “&lt;em&gt;Harry&lt;/em&gt;”.&lt;/p&gt;

&lt;p&gt;Tries have a constant time &lt;code&gt;O(1)&lt;/code&gt;, for searching and insertion. The cost for this, though, is that we need lots of memory to store mostly arrays with null pointers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Summary
&lt;/h3&gt;

&lt;p&gt;Here you have some sort of summary of each data structure seen on this post:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linked Lists&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insertion is easy - just stack onto the front&lt;/li&gt;
&lt;li&gt;Deletion is easy - once you find the element&lt;/li&gt;
&lt;li&gt;Lookup is bad - have to rely on linear search&lt;/li&gt;
&lt;li&gt;Relatively difficult to sort - unless you’re willing to compromise on super-fast insertion and instead sort as you construct&lt;/li&gt;
&lt;li&gt;Relatively small size-wise (not as small as arrays)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hash Tables&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insertion is a two-step process - hash, then add&lt;/li&gt;
&lt;li&gt;Deletion is easy - once you find the element&lt;/li&gt;
&lt;li&gt;Lookup is on average better than linked lists because you have the benefit of a real-world constant factor. You have smaller linked lists on each location instead of one entire linked list.&lt;/li&gt;
&lt;li&gt;Not an ideal data structure if sorting is the goal, just use an array&lt;/li&gt;
&lt;li&gt;Can run the gamut of size. It depends on the height of the hash table and the length of the linked lists on each location.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tries&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insertion is complex - A lot of dynamic memory allocation, but gets easier as you go&lt;/li&gt;
&lt;li&gt;Deletion is easy - Just free a node&lt;/li&gt;
&lt;li&gt;Lookup is fast - not quite as fast as an array, but almost&lt;/li&gt;
&lt;li&gt;Already sorted - sorts as you build in almost all situations&lt;/li&gt;
&lt;li&gt;Rapidly becomes huge, even with very little data present, not great if space is at a premium&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you wanna know more about time complexity of different data structures and sorting algorithms here you have a great cheatsheet: &lt;a href="https://www.bigocheatsheet.com/"&gt;bigocheatsheet.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;There are more data structures like &lt;em&gt;queues&lt;/em&gt;, &lt;em&gt;stacks&lt;/em&gt;, &lt;em&gt;doubly linked lists&lt;/em&gt;, &lt;em&gt;b-trees&lt;/em&gt;, etc; but maybe we can see some of them in other posts. This is a really important topic to learn and understand, not just because they’re present in every tech interview, but because they’re really helpful and improve us as developers to take better decisions when storing data.&lt;/p&gt;

&lt;p&gt;On each data structure, we always pay a price, we must choose to minimize space, or minimize time. It’s not really possible to get the best of both worlds. That’s why is so important to learn about data structures: to make smart decisions.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt; 💗.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>computerscience</category>
      <category>data</category>
    </item>
    <item>
      <title>Web Scraping with Python</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Tue, 14 Jun 2022 17:31:58 +0000</pubDate>
      <link>https://dev.to/luciano_dev/web-scraping-with-python-1h9b</link>
      <guid>https://dev.to/luciano_dev/web-scraping-with-python-1h9b</guid>
      <description>&lt;p&gt;&lt;em&gt;Scraping&lt;/em&gt; is a technique for extracting data from a website when there’s no other source to obtain that data, like a Rest API or RSS feed. &lt;/p&gt;

&lt;p&gt;Google and other search engines have bots scraping all the information that later you see in your search results. Not just search engines use scraping, but also other kinds of websites, for example, for pricing, flights, and hotels comparison.&lt;/p&gt;

&lt;p&gt;I want to show you in this post how we can develop our own bot. You could use the same approach that I use to track the price of that product you want, or get the latest news from the news website you like, the limit is your imagination.&lt;/p&gt;

&lt;p&gt;I recommend you the book &lt;a href="https://www.amazon.com/-/es/Ryan-Mitchell/dp/1491910291"&gt;Web Scraping with Python&lt;/a&gt; if you want to go a bit deeper into web scraping with Python 🐍.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;br&gt;¿How does scraping work?
&lt;/h1&gt;

&lt;p&gt;There are different ways, but the most used technique is by obtaining the HTML code of the target website, and telling our bot what tags or attributes it has to search for, and where the information we want is stored.&lt;/p&gt;

&lt;p&gt;Imagine a website with this HTML structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"layout-articles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- News 1 --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/news-1"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"News 1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                News 1
            &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"news-1.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- News 2 --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/news-2"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"News 2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                News 2
            &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"news-2.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to get all the news titles of this page, we could search for the &lt;code&gt;section&lt;/code&gt; element which contains the attribute &lt;code&gt;class="layout-articles"&lt;/code&gt;, and from them get all the &lt;code&gt;a&lt;/code&gt; tags that contain the title and URL of each news item.&lt;/p&gt;

&lt;p&gt;This is just a simple example for you to have a better understanding of scraping.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;br&gt;¿What are we going to build?
&lt;/h1&gt;

&lt;p&gt;There’s a great site called &lt;a href="http://simpledesktops.com/"&gt;Simple Desktops&lt;/a&gt;, with a cool collection of fancy wallpapers, and our bot will take care of browsing the pages of this site and downloading each wallpaper 👏👏👏.&lt;br&gt;
&lt;a href="https://giphy.com/embed/l41lUJ1YoZB1lHVPG"&gt;https://giphy.com/embed/l41lUJ1YoZB1lHVPG&lt;/a&gt;&lt;br&gt;
First, let’s analyze the HTML structure of the website, which allows us to understand the steps our bot must follow for its task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Website pagination works as follows, &lt;code&gt;/browse/&lt;/code&gt;, &lt;code&gt;/browse/1/&lt;/code&gt;, &lt;code&gt;/browse/2/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;On each page, each wallpaper is a &lt;code&gt;div class="desktop"&lt;/code&gt; containing an &lt;code&gt;img&lt;/code&gt; tag whose &lt;code&gt;src&lt;/code&gt; attribute has the URL to download the wallpaper.&lt;/li&gt;
&lt;li&gt;The site uses a thumbnail generator implicit in the URL of each wallpaper image, but if we delete the text • that referred to the resize we can have access to the original image: Apple_Park.png~~.295x184_q100.png~~ 😎.&lt;/li&gt;
&lt;li&gt;The URL to the next page is stored in the &lt;code&gt;&amp;lt;a class="more"&lt;/code&gt; tag.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the information collected before we can say that our algorithm must follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do a request to &lt;code&gt;/browse/&lt;/code&gt; URL&lt;/li&gt;
&lt;li&gt;Get the wallpapers URL from the &lt;code&gt;src&lt;/code&gt; attribute of &lt;code&gt;img&lt;/code&gt; tag contained in each &lt;code&gt;div class="desktop"&lt;/code&gt; tag&lt;/li&gt;
&lt;li&gt;Remove the resize from the wallpaper URL&lt;/li&gt;
&lt;li&gt;Download the wallpapers&lt;/li&gt;
&lt;li&gt;Get the URL of the next page of the site and repeat step 2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Great, now that we know what to do… &lt;strong&gt;¡let´s code!🎈&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  &lt;br&gt;¿How to create a bot in Python?
&lt;/h1&gt;

&lt;p&gt;These are the packages we will use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/os.html"&gt;os&lt;/a&gt;: for handling file paths and folders&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/re.html"&gt;re&lt;/a&gt;: for regular expressions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/shutil.html"&gt;shutil&lt;/a&gt;: for file operations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://requests.readthedocs.io/es/latest/"&gt;requests&lt;/a&gt;: for HTTP requests&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;BeautifulSoup&lt;/a&gt;: for parsing the HTML code, the heart of our bot ❤️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;BeautifulSoup&lt;/em&gt; and &lt;em&gt;requests&lt;/em&gt; are two packages not built-in in Python, so we’re going to install them with &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;beautifulsoup4
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re going to split our code into functions to make it easy to read and debug.&lt;/p&gt;

&lt;p&gt;Create a directory and inside create a file called &lt;code&gt;simpledesktop-bot.py&lt;/code&gt;. First, we start by importing the packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;shutil&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;requests.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPError&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the entry point of our app we configure the initial data so that it can start running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Run, run, run
&lt;/span&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'http://simpledesktops.com'&lt;/span&gt;
    &lt;span class="n"&gt;first_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'/browse/'&lt;/span&gt;
    &lt;span class="n"&gt;download_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s"&gt;'wallpapers'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Create download directory if it does not exists
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Start crawling
&lt;/span&gt;    &lt;span class="n"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the beginning, we set the initial data, like the website URL, the path of the first page where our bot will start running, and a directory to store the downloaded wallpapers. If that directory doesn’t exist we create it with the &lt;code&gt;os.makedirs&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;In the last place, we call the function &lt;code&gt;processPage()&lt;/code&gt; to start the scraping process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Recursive function that deliver pages to request and wallpaper's data to the other functions
    """&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;PATH:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'========================='&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wallpapers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPageContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;downloadWallpaper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'This page does not contain any wallpaper'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'THIS IS THE END, BUDDY'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;processPage()&lt;/code&gt; is a recursive function that acts as a wrapper to manage the calls to the other functions.&lt;/p&gt;

&lt;p&gt;The first called function is &lt;code&gt;getPageContent()&lt;/code&gt;, which makes the HTTP request, analyzes the HTML structure, and returns a dictionary with the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;images&lt;/em&gt;: it’s a list containing each wallpaper’s URL&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;next_page&lt;/em&gt;: the URL path to the next page to process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;code&gt;wallpapers['images']&lt;/code&gt; is not empty, then we call &lt;code&gt;downloadWallpaper()&lt;/code&gt;, which receives the list of image’s URL and the download directory, and it’s in charge of processing each download.&lt;/p&gt;

&lt;p&gt;Lastly, if &lt;code&gt;wallpapers['next_page']&lt;/code&gt; exist, then we call recursively &lt;code&gt;processPage()&lt;/code&gt; with the path for the next page, otherwise, the program ends.&lt;/p&gt;

&lt;p&gt;Now let’s see the code of each function that &lt;code&gt;processPage()&lt;/code&gt; calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getPageContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Get wallpaper and next page data from requested page
    """&lt;/span&gt;
    &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;next_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requestPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Search wallpapers URL
&lt;/span&gt;        &lt;span class="n"&gt;wallpapers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'div'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'desktop'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;wp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'img'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'src'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# Search for next page URL
&lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;more_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'more'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="n"&gt;next_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;more_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'href'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;next_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;getPageContent()&lt;/code&gt; is the heart of our program, because its goal is to make a request to the page received by parameter and return a list of the wallpaper’s URL and the URL path  of the next page.&lt;/p&gt;

&lt;p&gt;First let’s initialize the &lt;code&gt;image&lt;/code&gt; and &lt;code&gt;next_page&lt;/code&gt; variables, which are going to store the return data.&lt;/p&gt;

&lt;p&gt;Then we call &lt;code&gt;requestPage()&lt;/code&gt;, which makes the HTTP request and returns the HTML content already parsed and ready to be manipulated. Here is where we see the black magic behind BeautifulSoup!. Using the &lt;code&gt;find_all&lt;/code&gt; method we get a list of &lt;code&gt;div class="desktop"&lt;/code&gt; tag. Then we loop over the list and using the &lt;code&gt;find&lt;/code&gt; method we search the &lt;code&gt;img&lt;/code&gt; tag and extract the wallpaper URL from the &lt;code&gt;src&lt;/code&gt; attribute. Each URL is stored in the &lt;code&gt;images&lt;/code&gt; list.&lt;/p&gt;

&lt;p&gt;Next, we search for the &lt;code&gt;a class="more"&lt;/code&gt; tag, extract the &lt;code&gt;href&lt;/code&gt; attribute and store it in the &lt;code&gt;next_page&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Lastly, we return a dictionary containing &lt;code&gt;images&lt;/code&gt; and &lt;code&gt;next_page&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;requestPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Request pages and parse HTML response
    """&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;raw_html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error parsing HTML code'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s see what &lt;code&gt;requestPage()&lt;/code&gt; does. It requests the URL page received by parameter, and stores the payload into the &lt;code&gt;raw_html&lt;/code&gt; variable. Then parse the plain HTML with BeautifulSoup and return the parsed content.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;try/except&lt;/code&gt; we intercept any error that may be raised.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;downloadWallpaper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="s"&gt;"""
    Process wallpaper downloads
    """&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;match_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'^.+?(\.png|jpg)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;formated_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match_url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
            &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;wp_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copyfileobj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wp_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Wallpaper URL is invalid'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;downloadWallpaper()&lt;/code&gt; receives a list with the wallpaper’s URL to process each download. The first task this function does is delete from the URL the piece of text that works as a resize. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://static.simpledesktops.com/uploads/desktops/2020/03/30/piano.jpg.300x189_q100.png"&gt;http://static.simpledesktops.com/uploads/desktops/2020/03/30/piano.jpg.300x189_q100.png&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Deleting &lt;code&gt;.300x189_q100.png&lt;/code&gt; from the end of the URL allows us to download the image with their original size. To accomplish this task we’re using the regular expression &lt;code&gt;^.+?(\.png|jpg)&lt;/code&gt;, which returns the URL from the start until the first occurrence of &lt;code&gt;.png&lt;/code&gt; or &lt;code&gt;.jpg&lt;/code&gt; is found. If there is no match then the URL is not valid.&lt;/p&gt;

&lt;p&gt;Then we extract the file name using the function &lt;code&gt;rfind(’/’)&lt;/code&gt; to find the first slash character starting from the right of the string, where the filename starts. With this value and the directory, we save in the variable &lt;code&gt;file_path&lt;/code&gt; the destination in our computer where the wallpaper will be downloaded.&lt;/p&gt;

&lt;p&gt;In the next block of code, we check first if the wallpaper doesn't already exist to prevent downloading it again. If the file does not exist we execute the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We download the file using &lt;code&gt;requests.get()&lt;/code&gt; and store a reference to the binary file in memory in the variable &lt;code&gt;wp_file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then we &lt;code&gt;open()&lt;/code&gt; the local file in binary and writing mode and reference that file as &lt;code&gt;output_file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The last step is to copy the content of &lt;code&gt;wp_file&lt;/code&gt; (the downloaded image) into &lt;code&gt;output_file&lt;/code&gt; (the file on disk) using &lt;code&gt;shutil.copyfileobj()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have already downloaded the wallpaper and saved it on our disk.&lt;/p&gt;

&lt;p&gt;There’s no need to free the memory of opened files because we’re working inside a &lt;code&gt;with&lt;/code&gt; statement, which manage it automatically.&lt;/p&gt;

&lt;p&gt;And that’s all, we can now execute the program. To run it just open the console and type &lt;code&gt;python3 simpledesktop-bot.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python3 simpledesktop-bot.py

PATH: /browse/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/sphericalharmonics1.png
/Users/MyUser/simple-desktop-scraper/wallpapers/Dinosaur_eye_2.png
/Users/MyUser/simple-desktop-scraper/wallpapers/trippin.png
...

PATH: /browse/2/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/Apple_Park.png
/Users/MyUser/simple-desktop-scraper/wallpapers/triangles.png
/Users/MyUser/simple-desktop-scraper/wallpapers/thanksgiving_twelvewalls.png
...

PATH: /browse/3/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/minimalistic_rubik_cube_2880.png
/Users/MyUser/simple-desktop-scraper/wallpapers/Nesting_Dolls.png
/Users/MyUser/simple-desktop-scraper/wallpapers/flat_bamboo_wallpaper.png
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the code in the GitHub repository, and if you like it give it a star 😉.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/luciano-im/SimpleDesktop-Bot"&gt;SimpleDesktop-Bot&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;&lt;br&gt;
Thanks for reading, it is very valuable for me that you have read this post. I hope you have learned something new, as I did when I was writing and coding this, if so leave a comment or send me a tweet because I would love to know it.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt; 💗.&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>showdev</category>
    </item>
    <item>
      <title>CS50: Week 4, Memory</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Tue, 07 Jun 2022 18:02:59 +0000</pubDate>
      <link>https://dev.to/luciano_dev/cs50-week-4-memory-417f</link>
      <guid>https://dev.to/luciano_dev/cs50-week-4-memory-417f</guid>
      <description>&lt;p&gt;In week 2 we took a look at memory and how we could use arrays to store data. Now, in week 4, &lt;em&gt;David Malan&lt;/em&gt; goes a bit deeper into &lt;strong&gt;memory&lt;/strong&gt; management, introducing us to memory addresses, pointers, and memory allocation, among other low-level and interesting things.&lt;/p&gt;

&lt;p&gt;If you remember, Memory RAM is like a huge grid where information is stored as &lt;em&gt;0's&lt;/em&gt; and &lt;em&gt;1's&lt;/em&gt;. Each square of the grid has an address used by the computer when reading and writing information into it. These addresses are described using the hexadecimal system.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Hexadecimal
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Hexadecimal"&gt;hexadecimal system&lt;/a&gt; is a much more concise way to express data. It is easier for a person to remember the number &lt;code&gt;72&lt;/code&gt; to refer to the letter &lt;code&gt;H&lt;/code&gt;, instead of the equivalent in binary &lt;code&gt;01001000&lt;/code&gt;. The same thing happens with memory addresses, it is easier to read &lt;code&gt;0x5FA3F&lt;/code&gt; than its equivalent in decimal system &lt;code&gt;391743&lt;/code&gt; or in binary &lt;code&gt;1011111101000111111&lt;/code&gt;. The values in a computer’s memory are still stored as binary, but hexadecimal helps us, humans, represent larger numeric values with fewer digits needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hexadecimal system&lt;/strong&gt;, or base-16, is formed by 16 digits:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;0 1 2 3 4 5 6 7 8 9 A B C D E F&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The digits start with &lt;code&gt;0&lt;/code&gt; through &lt;code&gt;9&lt;/code&gt;, and continue with &lt;code&gt;A&lt;/code&gt; through &lt;code&gt;F&lt;/code&gt; as equivalents to the decimal values of &lt;code&gt;10&lt;/code&gt; through &lt;code&gt;15&lt;/code&gt;. After &lt;code&gt;F&lt;/code&gt;, we need to carry the one, as we would go from 01 to 10 in binary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16^1 16^0
  1    0   =  16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the &lt;code&gt;1&lt;/code&gt; has a value of &lt;code&gt;16^1×1 = 16&lt;/code&gt;, so &lt;code&gt;10&lt;/code&gt; in hexadecimal is 16 in decimal.&lt;/p&gt;

&lt;p&gt;With two digits, we can have a maximum value of &lt;code&gt;FF&lt;/code&gt;, or (remember that &lt;code&gt;F&lt;/code&gt; is 15 in the decimal system):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;16^1×15 + 16^0×15 = 16×15 + 1×15 = 240 + 15 = 255
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With 8 bits in binary, the highest value we can count to is also 255, with &lt;code&gt;11111111&lt;/code&gt;. So &lt;strong&gt;two digits in hexadecimal can conveniently represent the value of a byte in binary&lt;/strong&gt;. (Each digit in hexadecimal, with 16 values, maps to four bits in binary.)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Pointers
&lt;/h3&gt;

&lt;p&gt;When we create a variable in our program, it is stored at some memory location. That memory location has an address, which is described using hexadecimal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qiSCrMna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z46ki5wo9xlxyiaoyn4r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qiSCrMna--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z46ki5wo9xlxyiaoyn4r.png" alt="Pointers" width="880" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our computer’s memory, there are now 4 bytes (remember that an &lt;code&gt;int&lt;/code&gt; takes 4 bytes in memory) somewhere that has the value of 50, with some value for its address, like &lt;code&gt;0x123.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By writing &lt;code&gt;0x&lt;/code&gt; in front of a hexadecimal value, we can distinguish them from decimal values.&lt;/p&gt;

&lt;p&gt;A reference to that address in memory can be stored in another variable, which is better known as a &lt;strong&gt;pointer&lt;/strong&gt;. So, a pointer is a variable that stores a &lt;a href="https://en.wikipedia.org/wiki/Memory_address"&gt;memory address&lt;/a&gt;, where some other variable might be stored, the specific byte in which that value is stored.&lt;/p&gt;

&lt;p&gt;Also, pointers provide a way to pass data by reference between functions. By default, &lt;em&gt;C&lt;/em&gt; passes data by value, which means it only passes a copy of that data. Using pointers we can pass a reference to work with the original data.&lt;/p&gt;

&lt;p&gt;A pointer value is a memory address, and the type of the pointer describes the data stored at that memory address.&lt;/p&gt;

&lt;p&gt;In &lt;em&gt;C&lt;/em&gt; we can declare a pointer using the &lt;code&gt;*&lt;/code&gt; &lt;em&gt;star operator&lt;/em&gt;. Also, we can use the &lt;code&gt;&amp;amp;&lt;/code&gt; &lt;em&gt;address operator&lt;/em&gt; to get the memory address of some variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make address
&lt;span class="nv"&gt;$ &lt;/span&gt;./address
0x7ffcb4578e5c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can run this program a few times and see that the address of &lt;code&gt;n&lt;/code&gt; changes because different addresses in memory will be available at different times.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;*&lt;/code&gt; operator is also used as the &lt;em&gt;dereference operator&lt;/em&gt;, which goes to an address to get the value stored there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%i&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./address
0x7ffda0a4767c
50
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The value of a memory address in itself is not significant, since it’s just some location in memory where a variable is stored; but it is a significant idea to use with strings.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Strings
&lt;/h3&gt;

&lt;p&gt;We already saw that &lt;em&gt;C&lt;/em&gt; doesn’t have native support for strings, they’re just an array of type &lt;code&gt;char&lt;/code&gt;. Because it is an array, we can declare a string with &lt;code&gt;string s = "HI!";&lt;/code&gt;, and access each character with &lt;code&gt;s[0]&lt;/code&gt;, &lt;code&gt;s[1]&lt;/code&gt;, &lt;code&gt;s[2]&lt;/code&gt;, and &lt;code&gt;s[3]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each character has its own memory address, and &lt;code&gt;s&lt;/code&gt; is actually just a pointer containing the address of the first character of the string:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UaRt1lkX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b01lkpftas3afmd53osf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UaRt1lkX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b01lkpftas3afmd53osf.png" alt="String pointers" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recall that we can read the entire string by starting at the address in &lt;code&gt;s&lt;/code&gt;, and continue reading one character at a time from memory until we reach the &lt;em&gt;NUL&lt;/em&gt; character &lt;code&gt;\0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As we can see in the following example, the address of the first character, &lt;code&gt;&amp;amp;s[0]&lt;/code&gt;, is the same as the value of &lt;code&gt;s&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HI!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make address
&lt;span class="nv"&gt;$ &lt;/span&gt;./address
HI!
0x123
0x123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, the address of the first character, &lt;code&gt;&amp;amp;s[0]&lt;/code&gt;, is the same as the value of &lt;code&gt;s&lt;/code&gt;. And each following character has an address that is one byte higher:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HI!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%p&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make address
&lt;span class="nv"&gt;$ &lt;/span&gt;./address
0x123
0x123
0x124
0x125
0x126
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because each string is just a pointer to a different location in memory, if we compare two strings containing the same text, they will be different, because we are comparing the addresses where they are stored and not the text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HI!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"HI!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Same&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Different&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make compare
&lt;span class="nv"&gt;$ &lt;/span&gt;./compare
Different
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might look in our computer’s memory like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hawjkEO8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t63tq2g34hmyr6umwhh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hawjkEO8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t63tq2g34hmyr6umwhh3.png" alt="Memory" width="880" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we now copy the string into another variable we will see that any change made to the copy will affect also the original string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ctype.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hi!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// capitalize the first letter&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"s: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"t: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make copy
&lt;span class="nv"&gt;$ &lt;/span&gt;./copy
s: Hi!
t: Hi!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The concept is the same as with the compare situation, in this case both, variables point to the same address in memory where the string &lt;em&gt;“hi!”&lt;/em&gt; is stored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8AJ-YuSm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bo7voavpqvpd3o19x6ez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8AJ-YuSm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bo7voavpqvpd3o19x6ez.png" alt="Memory reference" width="880" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For both compare and copy operations with strings, the process is similar: loop over the string and compare or copy character by character. Also, you can use the methods &lt;a href="https://manual.cs50.io/3/strcmp"&gt;strcmp()&lt;/a&gt; and &lt;a href="https://manual.cs50.io/3/strcpy"&gt;strcpy()&lt;/a&gt; from the C library &lt;code&gt;string.h&lt;/code&gt; created for this purpose. But we will see that in detail below.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Dynamic memory allocation
&lt;/h3&gt;

&lt;p&gt;To make a copy of a string, we have to do a little more work, first, we need a free block of memory that acts like an “empty string”,  where to copy the characters. To get a free block of memory there’s a function called &lt;code&gt;malloc&lt;/code&gt; which allocates **dynamically some number of bytes in memory for our program to use. Once we´re done with the allocated memory, there’s another function called &lt;code&gt;free&lt;/code&gt; to give back again the memory to the operating system, so it can do something else with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ctype.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hi!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// + 1 because we need an extra byte for the NUL '\0' character&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strlen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;strcpy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;toupper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"s: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"t: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;free&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;make copy
&lt;span class="nv"&gt;$ &lt;/span&gt;./copy
s: hi!
t: Hi!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our computers might slow down if a program we’re running never frees allocated memory. The operating system will take longer and longer to find enough available memory for our program.&lt;/p&gt;

&lt;p&gt;If the computer is out of memory, &lt;code&gt;malloc&lt;/code&gt; will return &lt;code&gt;NULL&lt;/code&gt;, a special value of all &lt;code&gt;0&lt;/code&gt; bits that indicates there isn’t an address to point to. So we’re checking for that case in our example, and exit if &lt;code&gt;t&lt;/code&gt; is &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now both &lt;code&gt;s&lt;/code&gt; and &lt;code&gt;t&lt;/code&gt; point to a different memory location where &lt;code&gt;hi!&lt;/code&gt; and &lt;code&gt;Hi!&lt;/code&gt; are stored.&lt;/p&gt;

&lt;p&gt;We must be careful when allocating memory with malloc, if we don’t initialize our variables, we will end up getting what is known as &lt;strong&gt;&lt;em&gt;garbage values&lt;/em&gt;&lt;/strong&gt;, random data that were in the block of memory that the system gave us. And if we try to go to an address that’s a garbage value, our program is likely to crash from a segmentation fault error.&lt;/p&gt;

&lt;p&gt;Next, we are going a bit deeper into how memory works.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Memory layout
&lt;/h3&gt;

&lt;p&gt;So far we’ve been talking about memory imagining it is like a huge grid, where magically the computer stores and retrieves data. Going deeper about how memory works, different types of data that need to be stored for our program are organized into different sections:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XWwrXRSr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yudhvfbvcl8vmyym599p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XWwrXRSr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yudhvfbvcl8vmyym599p.png" alt="Memory layout" width="500" height="854"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;machine code&lt;/strong&gt; section is our compiled program’s binary code. When we run our program, that code is loaded into memory.&lt;/p&gt;

&lt;p&gt;Just below, or in the next part of memory, are &lt;strong&gt;global variables&lt;/strong&gt; we declared in our program.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;heap&lt;/strong&gt; section is an empty area from where &lt;code&gt;malloc&lt;/code&gt; can get free memory for our program to use. As we call &lt;code&gt;malloc&lt;/code&gt;, we start allocating memory from the top down.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;stack&lt;/strong&gt; section is used by functions and local variables in our program as they are called and grow upwards.&lt;/p&gt;

&lt;p&gt;If we call &lt;code&gt;malloc&lt;/code&gt; for too much memory, we will have a &lt;strong&gt;&lt;em&gt;heap overflow&lt;/em&gt;&lt;/strong&gt;, since we end up going past our heap. The three golden rules of memory allocation are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every block of memory allocated with &lt;code&gt;malloc&lt;/code&gt; must subsequently be &lt;code&gt;freed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Only memory you &lt;code&gt;malloc&lt;/code&gt; should be &lt;code&gt;freed&lt;/code&gt;, to prevent segmentation fault errors.&lt;/li&gt;
&lt;li&gt;Do not &lt;code&gt;free&lt;/code&gt; a block of memory more than once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other hand, if we call too many functions without returning from them, we will have a &lt;strong&gt;&lt;em&gt;stack overflow&lt;/em&gt;&lt;/strong&gt;, where our stack has too much memory allocated as well.&lt;/p&gt;

&lt;p&gt;But, why could we call too many functions without returning from them? Maybe for a bug in a recursive function.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;br&gt; Call Stack
&lt;/h3&gt;

&lt;p&gt;The call stack is the flow that C uses to work. When you call a function, the system sets aside space in memory for that function to do its work. Those chunks in memory are known as stack frames or function frames.&lt;/p&gt;

&lt;p&gt;More than one function’s stack frame may exist in memory at a given time, for example, we have a &lt;code&gt;main()&lt;/code&gt; function which calls to &lt;code&gt;move()&lt;/code&gt; function, which also calls to &lt;code&gt;direction()&lt;/code&gt; function. All of them are in memory, but just one function is active doing its work.&lt;/p&gt;

&lt;p&gt;Frames are arranged in a stack. A stack is a linear data structure that follows LIFO (Last In First Out) as the order in which the operations are performed. The frame for the most recently called function is always on top of the stack and is the active frame. When a function finishes its work, its frame is popped off the stack and the frame immediately below becomes the active frame, which continues doing its work where it left off.&lt;/p&gt;

&lt;p&gt;This is how recursion works. But maybe it is better to explain it with the example of the factorial calculation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%i&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      CALL STACK
-------------------------     ______
|        fact(0)        |    |      |
-------------------------    |      |
|        fact(1)        |    |      |
-------------------------    |      |
|        fact(2)        |    |      |
-------------------------    |      |
|        fact(3)        |    |      |
-------------------------    |      |
|        fact(4)        |    |      |
-------------------------    |      |
|        fact(5)        |    |      |
-------------------------    |      |
|         main()        |    |      |
-------------------------    ˄      ˅ ORDER OF EXECUTION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;First, our program executes the &lt;code&gt;main()&lt;/code&gt; function, and its frame is pushed to the stack.&lt;/li&gt;
&lt;li&gt;Then &lt;code&gt;main()&lt;/code&gt; calls the &lt;code&gt;fact(5)&lt;/code&gt; function. For &lt;code&gt;main()&lt;/code&gt; finishes its work, it needs the result of &lt;code&gt;fact(5)&lt;/code&gt;, so the frame for this function is pushed on top of the stack.&lt;/li&gt;
&lt;li&gt;For &lt;code&gt;fact(5)&lt;/code&gt; to finish its work, it needs the result of &lt;code&gt;fact(n-1)&lt;/code&gt;, which is the same as &lt;code&gt;fact(4)&lt;/code&gt;, so the frame for this function is pushed on top of the stack.&lt;/li&gt;
&lt;li&gt;The process repeats until the program reaches &lt;code&gt;fact(0)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fact(0)&lt;/code&gt; is the first function in returning a value, it returns the number 1. At this point, the frame for &lt;code&gt;fact(0)&lt;/code&gt; is popped off from the stack.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fact(1)&lt;/code&gt; uses the value returned by &lt;code&gt;fact(0)&lt;/code&gt; to calculate and return its own value, and then it’s also popped off from the stack.&lt;/li&gt;
&lt;li&gt;Once &lt;code&gt;fact(5)&lt;/code&gt; returns its value and is popped off from the stack, the &lt;code&gt;main()&lt;/code&gt; function picks up its work where it left at the beginning, prints the factorial, and returns 0.&lt;/li&gt;
&lt;li&gt;At this point, the program ends and the call stack gets empty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
I think it is great to know how memory works in general, and how programming languages manage it to do its work. I hope you found it interesting too. It is a topic that recruiters may ask when you’re in an interview, so better have a notion about it.&lt;/p&gt;

&lt;p&gt;In the next post: data structures 😃, a must if you wanna be a good developer.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt; 💗.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
    <item>
      <title>CS50: Week 3, Sorting and Searching Algorithms</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Wed, 11 May 2022 20:28:05 +0000</pubDate>
      <link>https://dev.to/luciano_dev/cs50-week-3-sorting-and-searching-algorithms-2h02</link>
      <guid>https://dev.to/luciano_dev/cs50-week-3-sorting-and-searching-algorithms-2h02</guid>
      <description>&lt;p&gt;Since previous lectures, we’ve been learning about memory, how to store data in it, the types and sizes of data, among others things.&lt;/p&gt;

&lt;p&gt;If we need to manage a large amount of data, it is convenient to use an array to store it, we already know how to do it, so this week &lt;strong&gt;&lt;em&gt;David Malan&lt;/em&gt;&lt;/strong&gt; teaches how to sort and search values in arrays explaining &lt;a href="https://en.wikipedia.org/wiki/Search_algorithm" rel="noopener noreferrer"&gt;Searching Algorithms&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sorting_algorithm" rel="noopener noreferrer"&gt;Sorting Algorithms&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Big O and Big Omega
&lt;/h3&gt;

&lt;p&gt;To understand the difference between distinct algorithms, we must first have a notion about &lt;strong&gt;Big O notation&lt;/strong&gt;. In computer science, we can measure the efficiency of an algorithm in terms of &lt;em&gt;memory consumption&lt;/em&gt; and &lt;em&gt;running time&lt;/em&gt;. &lt;a href="https://www.youtube.com/watch?v=v4cd1O4zkGw" rel="noopener noreferrer"&gt;Big O notation&lt;/a&gt; is a special notation that measures running time, it tells you how fast an algorithm is, or how long an algorithm takes to run given some size of input. It doesn’t measure running time in seconds or milliseconds, instead, it gives us an idea of how many operations an algorithm performs in relation to the input it receives.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Big O&lt;/em&gt; describes the upper bound of the number of operations, or how many steps an algorithm might take in the worst case until it finishes, while &lt;strong&gt;Big Omega notation&lt;/strong&gt; (big Ω), in counterpart, describes the lower bound of the number of operations of an algorithm, or how few steps it might take in the best case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyo8egj9ogaksbj7zxo2e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyo8egj9ogaksbj7zxo2e.png" alt="Big O comparision"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The image above expresses the running time of three different ways of searching for a person in a phone book:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The red line represents searching on one page at a time starting from the beginning. It could take a lot of time find someone because the the searching becomes proportionally longer to complete as the phone book grows. If it takes &lt;code&gt;1&lt;/code&gt; second to check &lt;code&gt;10&lt;/code&gt; name, it will take &lt;code&gt;2&lt;/code&gt; seconds to check &lt;code&gt;20&lt;/code&gt; names, &lt;code&gt;3&lt;/code&gt; seconds to check &lt;code&gt;30&lt;/code&gt; names, &lt;code&gt;100&lt;/code&gt; seconds to check &lt;code&gt;1000&lt;/code&gt; names, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The yellow line represents searching on two pages at a time. It is double faster than the first option but still takes a lot of time to complete the search.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The green line represents the last and most efficient option, a divide and conquers approach. Open the phone book in the middle, if the target name is not there, then preserve the half where the name alphabetically must appear and discard the other half. Then repeat the process with the remaining half until the target is found. It’s much faster than the other two options because the time required to find a name goes up linearly while the size of the phone book grows exponentially. So if it takes &lt;code&gt;1&lt;/code&gt; second to check &lt;code&gt;10&lt;/code&gt; names, it will take &lt;code&gt;2&lt;/code&gt; seconds to check &lt;code&gt;100&lt;/code&gt; names, &lt;code&gt;3&lt;/code&gt; seconds to check &lt;code&gt;1000&lt;/code&gt; names, and so on.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
In the chart above, if we zoomed out and changed the units on our axes, we would see the red and yellow lines end up very close together:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw48wr4gkjy5ybybd4r7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw48wr4gkjy5ybybd4r7e.png" alt="Big O comparision"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since both the red and yellow lines end up being very similar as &lt;code&gt;n&lt;/code&gt; becomes larger and larger, we can say they have the same time complexity. We would describe them both as having &lt;code&gt;big O of n&lt;/code&gt; or &lt;code&gt;on the order of n&lt;/code&gt; running time.&lt;/p&gt;

&lt;p&gt;The green line, though, is fundamentally different in its shape, even as &lt;code&gt;n&lt;/code&gt; becomes very large, so it takes &lt;code&gt;big O of log⁡ n&lt;/code&gt; steps 🤯 (later we will see why).&lt;/p&gt;

&lt;p&gt;The most common running times are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O(n2)  -  &lt;em&gt;Quadratic time&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;O(n * log n)  -  &lt;em&gt;Linearithmic time&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;O(n)  -  &lt;em&gt;Linear time&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;O(log n)  -  &lt;em&gt;Logarithmic time&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;O(1)  -  &lt;em&gt;Constant time&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;br&gt; Linear Search
&lt;/h3&gt;

&lt;p&gt;Is the simplest and intuitive method for finding an element within an array. The steps required to perform Linear Search would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start from the leftmost element of the array.&lt;/li&gt;
&lt;li&gt;Check if the target value matches the value stored in the array.&lt;/li&gt;
&lt;li&gt;If matches, then the algorithm finishes successfully. &lt;/li&gt;
&lt;li&gt;If it doesn’t match, repeat step 2 with the next element of the array.&lt;/li&gt;
&lt;li&gt;If the array finishes with no matches, then the target is not present in the array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We might write the algorithm pseudocode as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For each element from left to right
    If number is at this position
        Return true
Return false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next example we search for the number &lt;code&gt;7&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list = [0, 2, 10, 4, 7, 9]

[0, 2, 10, 4, 7, 9] --&amp;gt; 0 is not equal to 7
 ^
[0, 2, 10, 4, 7, 9] --&amp;gt; 2 is not equal to 7
    ^
[0, 2, 10, 4, 7, 9] --&amp;gt; 10 is not equal to 7
       ^
[0, 2, 10, 4, 7, 9] --&amp;gt; 4 is not equal to 7
           ^
[0, 2, 10, 4, 7, 9] --&amp;gt; MATCH
              ^

The number 7 was found after 5 iterations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;n&lt;/code&gt; elements, we’ll need to look at all &lt;code&gt;n&lt;/code&gt; of them in the worst case (e.g. if we were searching for the number 9 in the example above), so the &lt;em&gt;big O&lt;/em&gt; running time of this algorithm is linear &lt;code&gt;O(n)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The lower bound, would be &lt;code&gt;Ω(1)&lt;/code&gt;, since we might be lucky and find the number we are looking for at the first position of the array (e.g. if we were searching for the number 0 in the example above). &lt;code&gt;Ω(1)&lt;/code&gt; is also known as constant time, because a constant number of steps is required, no matter how big the problem is.&lt;/p&gt;

&lt;p&gt;Linear Search is correct because it solves the searching problem, but it is not very efficient.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Just in case, this is my implementation of Linear Search in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Linear Search
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;linear_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Use the in operator to check if the target value 
&lt;/span&gt;    &lt;span class="c1"&gt;# is on the list
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;# Ask the user for a target value
&lt;/span&gt;    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Que número buscas?: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;linear_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;El número existe.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;El número no existe.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;br&gt; Binary Search
&lt;/h3&gt;

&lt;p&gt;This method uses an approach called &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Divide-and-conquer_algorithm" rel="noopener noreferrer"&gt;divide and conquer&lt;/a&gt;&lt;/em&gt;, where we divide the problem in half on each step. This algorithm works only on sorted arrays. The steps required to perform Linear Search would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get an element from the middle of the array.&lt;/li&gt;
&lt;li&gt;If the element matches the target value, then the algorithm finishes successfully. &lt;/li&gt;
&lt;li&gt;If the target value is smaller than the middle element, narrow the array to the left half.&lt;/li&gt;
&lt;li&gt;If the target value is greater than the middle element, narrow the array to the right half.&lt;/li&gt;
&lt;li&gt;Repeat from step 1 with the narrowed array.&lt;/li&gt;
&lt;li&gt;If the array is empty, then the target is not present in the array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We might write the algorithm pseudocode as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If array is empty
    Return false
If number is at the middle position
    Return true
Else if number &amp;lt; number at the middle position
    Search left half
Else if number &amp;gt; number at the middle position
    Search right half
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next example we search for the number &lt;code&gt;6&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list = [0, 1, 2, 3, 4, 5, 6]

[0, 1, 2, 3, 4, 5, 6] --&amp;gt; 3 is the middle element. 6 is higher so we search on the right half
          ^
[4, 5, 6] --&amp;gt; 5 is the middle element. 6 is higher so we search on the right half
    ^
[6] --&amp;gt; MATCH
 ^

The number 6 was found after 3 iterations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
The upper bound for binary search is &lt;code&gt;O(log⁡ n)&lt;/code&gt;, known as &lt;em&gt;logarithmic time.&lt;/em&gt; When an algorithm has &lt;code&gt;O(log n)&lt;/code&gt; running time, it means that as the input size grows, the number of operations grows very slowly. Since in Binary Search we’re discarding the half of the elements on every step, we can say that &lt;code&gt;n&lt;/code&gt; (the size of the problem) is reduced exponentially, while the time required to find the target goes up linearly.&lt;/p&gt;

&lt;p&gt;The best case scenario for this algorithm is to find the target exactly in the middle, in the first iteration, which means that the Big Omega running time is in the order of &lt;code&gt;Ω(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even though binary search might be much faster than linear search, it requires our array to be sorted first. If we’re planning to search our data many times, it might be worth taking the time to sort it first, so we can use binary search.&lt;/p&gt;

&lt;p&gt;To understand in-depth how Binary Search works we must know first what &lt;strong&gt;recursion&lt;/strong&gt; is. If you look at the pseudocode again note that we're using the same “&lt;em&gt;search&lt;/em&gt;” algorithm for the left and right half. That is &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Recursion" rel="noopener noreferrer"&gt;recursion&lt;/a&gt;, the ability for a function to call itself.&lt;/p&gt;

&lt;p&gt;This seems like a cyclical process that will never end, but we’re actually changing the input to the function and dividing the problem in half each time, stopping once there are no more elements left. When the function runs over elements, that is the condition, also known as &lt;strong&gt;base case&lt;/strong&gt;, which tells the recursive function to stop, so it doesn’t call itself over and over forever.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Here is my implementation of Binary Search written in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Binary Search
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Base Case
&lt;/span&gt;    &lt;span class="c1"&gt;# If there's only 1 element then check explcitly if matches the target value
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="c1"&gt;# Calculate the middle of the list
&lt;/span&gt;    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="c1"&gt;# Check if the middle element matches the target
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If the target is smaller, repeat the search on the left half 
&lt;/span&gt;        &lt;span class="c1"&gt;# otherwise, look in the right half.
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;:],&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nb"&gt;long&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Ask the user for a target value
&lt;/span&gt;    &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Que número buscas?: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="c1"&gt;# Sort the array with sorted() function since Binary Search works with sorted lists
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;El número existe.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;El número no existe.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;br&gt; Selection Sort
&lt;/h3&gt;

&lt;p&gt;Selection Sort works by sorting arrays from left to right. The steps required to sort a list with this algorithm would be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start from the leftmost element of the array&lt;/li&gt;
&lt;li&gt;Traverse the array to find the smallest element&lt;/li&gt;
&lt;li&gt;After traversing the array, swap the smallest element with the value on the first position of the array&lt;/li&gt;
&lt;li&gt;Repeat from step 2, now starting from the second element, and swap the smallest value with the value on the second position of the array. Continue repeating with the 3rd, 4td, and so on, until the array is sorted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because computers can only look at one number at a time, we must iterate over the entire array each time to find the smallest value, without taking into account already sorted elements.&lt;/p&gt;

&lt;p&gt;We might write the algorithm pseudocode as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For i from 0 to n–1
    Find smallest number between numbers[i] and numbers[n-1]
    Swap smallest number with numbers[i]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next example we sort the next list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list = [3, 6, 5, 7, 8, 2]

[3, 6, 5, 7, 8, 2] --&amp;gt; 2 is the smallest element
                ^
[2, 6, 5, 7, 8, 3] --&amp;gt; Swap it with the element on the first position
 ^              ^

[2, 6, 5, 7, 8, 3] --&amp;gt; Now 3 is the smallest, since 2 is already sorted
                ^
[2, 3, 5, 7, 8, 6] --&amp;gt; Swap it with the element in the second position
    ^           ^

[2, 3, 5, 7, 8, 6] --&amp;gt; Now 5 is the smallest number. No swap needed because is already sorted
       ^

[2, 3, 5, 7, 8, 6] --&amp;gt; Repeat the process
                ^
[2, 3, 5, 6, 8, 7]
          ^     ^

[2, 3, 5, 6, 8, 7]
                ^
[2, 3, 5, 6, 7, 8]
             ^  ^

After 5 iterations the  array is sorted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
We can say that the algorithm has an upper bound for running time of &lt;code&gt;O(n2)&lt;/code&gt;, because we will be iterating the array over and over, searching for the smallest number.&lt;/p&gt;

&lt;p&gt;In the best case, where the list is already sorted, our selection sort algorithm will still look at all the numbers and repeat the loop, so it has a lower bound for running time of &lt;code&gt;Ω(n2)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is my implementation of Selection Sort written in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Selection Sort
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;selection_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# If the list has just one item then it's already sorted
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;

    &lt;span class="c1"&gt;# Loop over the entire list
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;lowest_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="c1"&gt;# Loop over each element to find the smallest one
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;lowest_index&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lowest_index&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="c1"&gt;# Save the index of the smallest element
&lt;/span&gt;                &lt;span class="n"&gt;lowest_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;
        &lt;span class="c1"&gt;# Swap elements
&lt;/span&gt;        &lt;span class="c1"&gt;# It's possible to swap elements like this in Python,
&lt;/span&gt;        &lt;span class="c1"&gt;# avoiding the use of a temporary variable
&lt;/span&gt;        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lowest_index&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lowest_index&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nb"&gt;long&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;selection_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;br&gt; Bubble Sort
&lt;/h3&gt;

&lt;p&gt;This algorithm sorts elements from right to left using comparison and swapping elements. We compare contiguous pairs of elements and swapping both if the smaller is on the right, and repeating the entire loop until no swaps were needed anymore.&lt;/p&gt;

&lt;p&gt;We could describe its functionality as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Look at the first element of the array, which will be the “current value”.&lt;/li&gt;
&lt;li&gt;Compare the current value with the next element in the array.&lt;/li&gt;
&lt;li&gt;If the next element is smaller, swap both values. Save in a variable that a swap was performed.&lt;/li&gt;
&lt;li&gt;Move to the next element of the array and make it the current value.&lt;/li&gt;
&lt;li&gt;Repeat from step 2 until the last number in the list has been reached.&lt;/li&gt;
&lt;li&gt;If any values were swapped, repeat again from step 1, without taking into account the last element of the array, which will be already sorted.&lt;/li&gt;
&lt;li&gt;If the end of the list is reached without any swaps being made, then the list is sorted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The pseudocode for bubble sort might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Repeat n-1 times
    For i from 0 to n–2
        If numbers[i] and numbers[i+1] out of order
            Swap them
    If no swaps
        Quit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are going to sort the same list we sorted with Selection Sort to see the differences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list = [3, 6, 2, 7, 5]

[3, 6, 2, 7, 5] --&amp;gt; compare 3 and 6, they're sorted
 ^  ^
[3, 6, 2, 7, 5] --&amp;gt; compare 6 and 2, swap them
    ^  ^
[3, 2, 6, 7, 5] --&amp;gt; compare 6 and 7, they're sorted
       ^  ^
[3, 2, 6, 7, 5] --&amp;gt; compare 7 and 5, swap them
          ^  ^
// Start from the beginning again

[3, 2, 6, 5, 7] --&amp;gt; compare 3 and 2, swap them
 ^  ^
[2, 3, 6, 5, 7] --&amp;gt; compare 3 and 6, they're sorted
    ^  ^
[2, 3, 6, 5, 7] --&amp;gt; compare 6 and 5, swap them
       ^  ^

// We don't compare 7 because is already sorted. At this point
// we know that the array is sorted, but still we need to loop 
// through the array one more time to check that no more swaps 
// are needed

[2, 3, 5, 6, 7] --&amp;gt; compare 2 and 3, they're sorted
 ^  ^
[2, 3, 5, 6, 7] --&amp;gt; compare 3 and 5, they're sorted
    ^  ^

// At this point the algorithm finishes because there were no
// swaps, and as in the previous iteration, we don't need to
// compare the number 6 because is already sorted.


After 3 iterations the array is sorted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
We can say that bubble sort has an upper bound for running time of &lt;code&gt;O(n2)&lt;/code&gt;, because as with Selection Sort, we must iterate over the array once and once, but the difference is that the lower bound would be &lt;code&gt;Ω(n)&lt;/code&gt;, because if the array is sorted just a single iteration over the array is needed to check that there were no swaps.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Here is my implementation of Bubble Sort written in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Bubble Sort
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bubble_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# If the list has just one item then it's already sorted 
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;

    &lt;span class="c1"&gt;# Loop over the entire list
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Swaps counter
&lt;/span&gt;        &lt;span class="n"&gt;swaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

        &lt;span class="c1"&gt;# Loop over the list to compare pairs of adjacent elements
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="c1"&gt;# Swap elements
&lt;/span&gt;                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="n"&gt;swaps&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

        &lt;span class="c1"&gt;# If there were no swaps, then the array is sorted
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;swaps&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nb"&gt;long&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;bubble_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;br&gt; Merge Sort
&lt;/h3&gt;

&lt;p&gt;This algorithm also makes use of the divide and conquer approach, and the recursion technique, just like Binary Search does. It divides the input array into two halves, calls itself for the two halves until it get an array containing one element (which is considered sorted), and then it repeatedly merges each sorted halves.&lt;/p&gt;

&lt;p&gt;We could describe the algorithm with the following steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the middle of the array.&lt;/li&gt;
&lt;li&gt;Divide the array from the middle.&lt;/li&gt;
&lt;li&gt;Call Merge Sort for the left half of the array.&lt;/li&gt;
&lt;li&gt;Call Merge Sort for the right half of the array.&lt;/li&gt;
&lt;li&gt;Merge the two sorted halves into a single sorted array&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As we’re using recursion, each call to Merge Sort will perform all the steps (from 1 to 5) for the sublist it receives. The base case, when Merge Sort stops calling itself, is when it receives an array with just one element since an array of one element is already sorted.&lt;/p&gt;

&lt;p&gt;The pseudocode for bubble sort might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If only one number
  Quit
Else
    Sort left half of number
    Sort right half of number
    Merge sorted halves
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It could be difficult to understand the algorithm just by words, so an example could help to show how Merge Sort works.&lt;/p&gt;

&lt;p&gt;In the example below, the red arrows represent each call to Merge Sort, which divides the array it receives into two sublists; and the green arrows represent the merging operation.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctf7fj8twsmf90hnwpkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctf7fj8twsmf90hnwpkv.png" alt="Merge Sort example"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;The strategy is to sort each half, and then merge them. The merging operation works as follows:&lt;/p&gt;

&lt;p&gt;Compare the leftmost element of both sublists and move the smallest value to a new array. Repeat the process until both sublists are merged into one array.&lt;/p&gt;

&lt;p&gt;If we want to merge the last two sublists of the example above, the steps are the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Compare the first element of each sublist and copy the smallest value 
// to a new array

[3, 27, 38, 43]  [9, 10, 82]  =&amp;gt;  [3]
 ^                ^
[27, 38, 43]     [9, 10, 82]  =&amp;gt;  [3, 9]
 ^                ^
[27, 38, 43]     [10, 82]     =&amp;gt;  [3, 9, 10]
 ^                ^
[27, 38, 43]     [82]         =&amp;gt;  [3, 9, 10, 27]
 ^                ^
[38, 43]         [82]         =&amp;gt;  [3, 9, 10, 27, 38]
 ^                ^
[43]             [82]         =&amp;gt;  [3, 9, 10, 27, 38, 43]
 ^                ^
[]               [82]         =&amp;gt;  [3, 9, 10, 27, 38, 43, 82]
                  ^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
The &lt;strong&gt;base case&lt;/strong&gt; for our recursive function will be a list containing just one element, as I said before, a list of one element is considered sorted.&lt;/p&gt;

&lt;p&gt;The time complexity of Merge Sort is &lt;code&gt;O(n Log n)&lt;/code&gt;, as the algorithm always divides the array into two halves, which have a complexity of &lt;code&gt;O(log n)&lt;/code&gt;; and the merge operation takes linear time, or &lt;code&gt;O(n)&lt;/code&gt;, since we only need to look at each element once. &lt;/p&gt;

&lt;p&gt;The lower bound of our merge sort is still &lt;code&gt;Ω(n log⁡ n)&lt;/code&gt;, since we have to do all the work even if the list is sorted.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Here is my implementation of Merge Sort written in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Merge Sort
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Base case
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;

    &lt;span class="c1"&gt;# Calculate the middle of the list
&lt;/span&gt;    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="c1"&gt;# Call merge sort for left and right halves
&lt;/span&gt;    &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;:],&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;

    &lt;span class="c1"&gt;# Calculate how many elements must be merged
&lt;/span&gt;    &lt;span class="n"&gt;merge_q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Empty list were the sublists will be merged into
&lt;/span&gt;    &lt;span class="n"&gt;sorted_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;merge_q&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# If both sublists have elements to be sorted
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Append smallest value to the sorted list
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                &lt;span class="n"&gt;sorted_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;sorted_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# If right half is empty append left half to the sorted list
&lt;/span&gt;        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sorted_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# If left half is empty append right half to the sorted list
&lt;/span&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;sorted_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sorted_array&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;merge_sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
I hope you found interesting searching and sorting algorithms, as I found it when taking the class. There are other algorithms, but this is a good first approach to this topic.&lt;/p&gt;

&lt;p&gt;The next lecture is about memory: addresses, pointers, allocation, and other concepts to continue learning how computer software works. &lt;/p&gt;

&lt;p&gt;I hope you find interesting what I’m sharing about my learning path. If you’re taking CS50 also, leave me your opinion about it.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on &lt;a href="https://www.instagram.com/luciano.webdev/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; 💗.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
    <item>
      <title>CS50: Week 2, Arrays</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Mon, 02 May 2022 15:32:56 +0000</pubDate>
      <link>https://dev.to/luciano_dev/cs50-week-2-arrays-b2d</link>
      <guid>https://dev.to/luciano_dev/cs50-week-2-arrays-b2d</guid>
      <description>&lt;p&gt;Hi veryone! Continuing with the &lt;em&gt;&lt;strong&gt;CS50 series&lt;/strong&gt;&lt;/em&gt;, this is what I found interesting in Week 2. Topics included in this lecture were compilers, debugging techniques, memory, and mostly arrays.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
We’re using the C programming language, a &lt;a href="https://en.wikipedia.org/wiki/Compiled_language"&gt;compiled language&lt;/a&gt;. It means that a compiler traduces the source code into machine code and generates the binary file that the computer runs to execute the software. On the other hand we have also &lt;a href="https://www.freecodecamp.org/news/compiled-versus-interpreted-languages/"&gt;interpreted languages&lt;/a&gt;, like Python or Javascript, which are traduced at run-time by an interpreter, line by line.&lt;/p&gt;

&lt;p&gt;Compilers execute 4 tasks when compiling code: &lt;em&gt;preprocessing&lt;/em&gt;, &lt;em&gt;compiling&lt;/em&gt;, &lt;em&gt;assembling&lt;/em&gt;, and &lt;em&gt;linking&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Preprocessing&lt;/em&gt;&lt;/strong&gt; involves replacing lines that start with a &lt;code&gt;#&lt;/code&gt;, as &lt;code&gt;#include&lt;/code&gt;. For example, &lt;code&gt;#include &amp;lt;cs50.h&amp;gt;&lt;/code&gt; will tell the compiler to look for that header file, since it contains content, like prototypes of functions, that we want to include in our program. Then the compiler will essentially copy and paste the contents of those header files into our program.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Compiling&lt;/em&gt;&lt;/strong&gt; takes our source code, in C, and converts it to another language called &lt;strong&gt;assembly language.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The next step is to take the code in assembly and translate it to binary by &lt;strong&gt;&lt;em&gt;assembling&lt;/em&gt;&lt;/strong&gt; it. The instructions in binary are machine code, which a computer’s CPU can run directly.&lt;/li&gt;
&lt;li&gt;The last step is &lt;strong&gt;&lt;em&gt;linking&lt;/em&gt;&lt;/strong&gt;, where previously compiled versions of libraries that we included earlier, like &lt;code&gt;cs50.c&lt;/code&gt;, are combined with the compiled binary of our program. In other words, linking is the process of combining all the machine code into one binary file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That a language is compiled does not mean that you will never need to debug a program, it is an advantage that the compiler prevents some errors, but we going to debug our programs anyway. &lt;/p&gt;

&lt;p&gt;There are different techniques to debug code, like printing variable values on the screen to understand what is doing the software. A better option is using a debugger, which you can run line by line to watch the flow the code follow and how each variable changes. Lastly, we have the &lt;a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging"&gt;rubber duck debugging technique&lt;/a&gt;, where we explain what we’re trying to do in our code to a rubber duck (or other inanimate object), and just by talking through our own code out loud step-by-step, we might realize the mistakes we made.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
I mentioned in my last post about some of the data types that come with C, which we can use to declare variables and store specific data, like &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, or &lt;code&gt;char&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Each variable is stored in memory with a fixed number of bytes. These are common type size for most computer systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bool&lt;/code&gt; is 1 byte size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;char&lt;/code&gt; is 1 byte size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;int&lt;/code&gt; is 4 bytes size,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;float&lt;/code&gt; is 4 bytes size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;double&lt;/code&gt; is 8 bytes size&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;long&lt;/code&gt; is 8 bytes size&lt;/li&gt;
&lt;li&gt;but talking about &lt;code&gt;strings&lt;/code&gt;, the size will vary depending on the length of the string.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can think of bytes stored in RAM as though they were in a grid, one after the other.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IORtYhfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvjfsl458xcacttp0yy6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IORtYhfe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvjfsl458xcacttp0yy6.png" alt="RAM Memory" width="880" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;char&lt;/code&gt; whose size is 1 byte will is stored in one of those, but an &lt;code&gt;int&lt;/code&gt; will use four bytes, four of those squares.&lt;/p&gt;

&lt;p&gt;When talking about arrays, we’re referring to one of the most widely used data structure in most programming languages.&lt;/p&gt;

&lt;p&gt;In an array, we can store more than one value. In C all the values must be of the same type, but in other languages, an array can contain different types of values.&lt;/p&gt;

&lt;p&gt;The particularly of arrays is that they’re stored in memory back-to-back, or contiguously, and we can access their values using bracket notation starting from the element 0: &lt;code&gt;array[0]&lt;/code&gt;, &lt;code&gt;array[1]&lt;/code&gt;, &lt;code&gt;array[2]&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Arrays, unlike the other data types, don’t have a fixed size in memory, it’s up to you to assign the size when defining the array in the code. But, once you set the size of the array it is permanent, and can’t be changed.&lt;/p&gt;

&lt;p&gt;C doesn’t have native support for strings, they’re just an array of type &lt;code&gt;char&lt;/code&gt;. Each character in our string is stored in a byte of memory as well:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8cih_cpX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwbq49lbwr7bb2ycuu58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8cih_cpX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwbq49lbwr7bb2ycuu58.png" alt="String stored in memory" width="880" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In C, strings end with a special character, &lt;code&gt;'\0'&lt;/code&gt;, or a byte with all eight bits set to 0, so our programs have a way of knowing where the string ends. This character is called the &lt;strong&gt;null character&lt;/strong&gt;, or NUL. So, we actually need four bytes to store the string &lt;code&gt;HI!&lt;/code&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
The last words of this lecture were about command-line arguments. I’ve seen this before with Python, and now I realize that Python took it from C, and used even the same variable name. In C we have the variables &lt;code&gt;argc&lt;/code&gt; and &lt;code&gt;argv&lt;/code&gt; that the &lt;code&gt;main&lt;/code&gt; function gets automatically when the program is run from the command line. &lt;code&gt;argc&lt;/code&gt; (argument count) store the number of arguments, and &lt;code&gt;argv[]&lt;/code&gt; (argument vector) is an array of the arguments themselves.&lt;/p&gt;

&lt;p&gt;These variables receive at least one parameter when we run our software: the program itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;./name
argc &lt;span class="o"&gt;=&lt;/span&gt; 1
argv[0] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'./name'&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;./name Luciano
argc &lt;span class="o"&gt;=&lt;/span&gt; 2
argv[0] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'./name'&lt;/span&gt;
argv[1] &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Luciano'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
The code below checks if it receives a name as an argument and prints &lt;code&gt;hello, {name}&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cs50.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"missing command-line argument&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello, %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note also that the &lt;code&gt;main&lt;/code&gt; function returns an integer value called an &lt;strong&gt;exit status&lt;/strong&gt;. There are some conventions but by default, we return &lt;code&gt;0&lt;/code&gt; if nothing went wrong, and &lt;code&gt;1&lt;/code&gt; or higher if something fails.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/luciano-im/cs50/tree/main/Pset%202"&gt;Check the code for the Problem set of Week 2&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Next week is about algorithms for sorting and searching, a challenging but necessary topic. &lt;/p&gt;

&lt;p&gt;I hope you find interesting what I’m sharing about my learning path. If you’re taking CS50 also, left me your opinion about it.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;br&gt;
&lt;br&gt;&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt; 💗.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>career</category>
    </item>
    <item>
      <title>CS50: About Week 0 and Week 1</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Tue, 26 Apr 2022 13:43:40 +0000</pubDate>
      <link>https://dev.to/luciano_dev/cs50-about-week-0-and-week-1-fee</link>
      <guid>https://dev.to/luciano_dev/cs50-about-week-0-and-week-1-fee</guid>
      <description>&lt;p&gt;Hi there!, in my previous post I told you that I’m looking for my first job as a software developer working abroad. After a few failed technical interviews, I realized that in my self-taught learning I missed some concepts and topics which now I need to learn to improve my programming skills.&lt;/p&gt;

&lt;p&gt;Searching for study material was when I found &lt;a href="https://learning.edx.org/course/course-v1:HarvardX+CS50+X/home"&gt;CS50: Introduction to Computer Science&lt;/a&gt;, which seemed a good starting point to review concepts from scratch. The course is intended for people with or without prior programming knowledge and covers beginners to more advanced topics.&lt;/p&gt;

&lt;p&gt;The intent is to teach students not how to use a programming language, but how to think algorithmically and solve problems efficiently, no matter the tool. The course is divided into weeks, each having a lecture, related materials, labs, and a set of problems to be solved.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 0
&lt;/h2&gt;

&lt;p&gt;In this lecture the instructor explains the basics of programming, like variables, conditionals, and loops, using Scratch, a software developed to teach programming, but what I want to highlight is what &lt;em&gt;David Malan&lt;/em&gt; says about our career: &lt;strong&gt;computer science is fundamentally problem solving&lt;/strong&gt;. Sounds silly, but many times we programmers start coding without having fully understood the problem, and without having a clear idea of its solution, the most important thing of all.&lt;/p&gt;

&lt;p&gt;The instructor gives a very clear explanation of how computers and the binary system work, which was what I liked the most about the lecture.&lt;/p&gt;

&lt;p&gt;Computers use the &lt;a href="https://en.wikipedia.org/wiki/Binary_system"&gt;binary system&lt;/a&gt; as their unique “language” to store and process data. This system uses just 0 and 1 to represent numbers. But, why do computers use it? Since computers run on electricity, which can be turned on or off, it is possible to represent a bit by turning some switch on or off. And what is a bit may you be thinking? It's just a binary digit, each 0 and 1.&lt;/p&gt;

&lt;p&gt;But computers don't use bits separately, they work with groups of 8 bits at a time, known as bytes, like 00000011 which represents the number 3. With 8 bits we can count from 0 to 255, that is the reason why this range is widely used in different contexts, like in RGB colors or IP addresses.&lt;/p&gt;

&lt;p&gt;So, computers use the binary system to represent information, and the binary system represents numbers, what happens with letters and other characters?. The computer uses an &lt;a href="https://en.m.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt; table to map numbers to characters. The ASCII standard includes uppercase and lowercase letters, numbers, punctuation, and other special characters. For example, bytes 01001000, 01001001, and 00100001 represent the decimal numbers 72, 73, and 33, which map to the word &lt;em&gt;HI!&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;But computers also represent others characters not included in the ASCII standard, like emojis, for example. For those characters, they use another standard called &lt;a href="https://home.unicode.org/"&gt;Unicode&lt;/a&gt;, which uses not just a byte for each character like ASCII does, but 4 bytes for a character, for example, these bytes 11110000 10011111 10011000 10110111 represent the emoji 😷.&lt;/p&gt;

&lt;p&gt;To represent colors, one of the most used systems is &lt;a href="https://en.wikipedia.org/wiki/RGB_color_model"&gt;RGB&lt;/a&gt;, which uses 3 bytes (from 0 to 255), each one for red, green, and blue respectively. The combination of these three values gives us a variety of shades of colors.&lt;/p&gt;

&lt;p&gt;Each color is a pixel, we can represent an image on the screen using millions of pixels, and with thousands or millions of images, we get a video. Yes, videos are just a sequence of images. Music can be represented with bits, too. MIDI is one such format that represents music with numbers for each note.&lt;/p&gt;

&lt;p&gt;The important thing here is that what a byte means is given by the context. In Microsoft Word, the number 72 could represent the letter H, but in Photoshop maybe is a value for one of the RGB channels of a pixel.&lt;/p&gt;

&lt;p&gt;Here comes in handy what programmers do in typed programming languages, defining the data type of the value stored in a variable, like a number, or a string.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1
&lt;/h2&gt;

&lt;p&gt;Since this lecture, the instructor teaches and uses the &lt;a href="https://en.wikipedia.org/wiki/C_(programming_language)"&gt;C programming language&lt;/a&gt;. This is the first time I develop in it, and what I noted is that both Python and JavaScript, the languages that I use the most, have taken some syntax and functionalities from C, which makes me feel a bit familiar with it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;David&lt;/em&gt; starts with a few words about code quality, which I found pretty good to understand the goals that every programmer must follow each time to write code. The quality can be evaluated based on 3 aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;correctness&lt;/strong&gt;, or whether our code solves our problem correctly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;design&lt;/strong&gt;, or how well-written our code is, based on how efficient and readable it is&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;style&lt;/strong&gt;, or how well-formatted our code is visually&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Already deep into the world of C, it is important to know which are its data types. This is useful, not just because the concept of a data type is common to every programming language, but to understand later the memory of the computer works.&lt;/p&gt;

&lt;p&gt;In C, these are the data types and its size in memory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;char&lt;/strong&gt; → 1 byte (8 bits) → Range (from -128 to 127)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unsigned char&lt;/strong&gt; → 1 byte (8 bits) → Range (from 0 to 255)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;int&lt;/strong&gt; → 4 bytes (32 bits) → Range (from -2^31 to 2^31 which means about -2 billion to 2 billion)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;unsigned int&lt;/strong&gt; → 4 bytes (32 bits) → Range (from 0 to about 4 billion)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;long&lt;/strong&gt; → 8 bytes (64 bits) → Big integers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;float&lt;/strong&gt; → 4 bytes → 32 bits of precision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;double&lt;/strong&gt; → 8 bytes → 64 bits of precision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to know the range of each data type, because going beyond the allowed range, it will end in an &lt;em&gt;overflow&lt;/em&gt; issue. For example, if we try to store a bigger number than 2 billion in an &lt;code&gt;int&lt;/code&gt; variable, an &lt;strong&gt;&lt;em&gt;Integer Overflow&lt;/em&gt;&lt;/strong&gt; error will be triggered.&lt;/p&gt;

&lt;p&gt;Limits in the size of data types also come with other kinds of problems like the &lt;strong&gt;&lt;em&gt;floating-point imprecision&lt;/em&gt;:&lt;/strong&gt; the inability for computers to represent all possible real numbers with a finite number of bits, like 32 bits for a &lt;code&gt;float&lt;/code&gt;. So, our computer has to store the closest value it can, leading to imprecision.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;Y2038&lt;/em&gt; is an integer overflow problem that is going to happen in the year 2038, when 32-bit computers are going to run out of bits to track time. Many years ago, some humans decided to use 32 bits to measure time with Unix time (or Unix epoch), which is the number of seconds since January 1st, 1970. But since a 32-bit integer can only count up to about two billion, in 2038 we’ll reach that limit.&lt;/p&gt;

&lt;p&gt;The 32 bits of an integer representing 2147483647 (the maximum value for an &lt;code&gt;int&lt;/code&gt;) look like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;01111111111111111111111111111111&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When we increase that by 1, the bits will actually look like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;10000000000000000000000000000000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;But the first bit in an integer represents whether or not it’s a negative value, so the decimal value will be -2147483648, the lowest possible &lt;em&gt;negative&lt;/em&gt; value of an &lt;code&gt;int&lt;/code&gt;. So computers might actually think it’s sometime in 1901.&lt;/p&gt;

&lt;p&gt;Fortunately, these days we have powerful computers, so we can start allocating more and more bits to store higher and higher values.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/luciano-im/cs50/tree/main/Pset%201"&gt;This is the code for the Problem set of Week 1&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
At the moment the course is great, with lots of information and very clear explanations. It is always good to review the bases because you find data that you did not remember or did not even know about.&lt;/p&gt;

&lt;p&gt;I hope you find interesting what I’m sharing about my learning path. If you’re taking CS50 also, left me your opinion about it.&lt;/p&gt;

&lt;p&gt;See you soon! 😉&lt;br&gt;
&lt;br&gt;&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me, you can give me a follow or contact me on Instagram, Twitter, or LinkedIn ❤.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>cs50</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>My Learning Journey</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Wed, 20 Apr 2022 02:10:56 +0000</pubDate>
      <link>https://dev.to/luciano_dev/my-learning-journey-4l1d</link>
      <guid>https://dev.to/luciano_dev/my-learning-journey-4l1d</guid>
      <description>&lt;p&gt;Hi there!, my name is Luciano Muñoz and I'm a developer. First of all I want to thank you for taking a few minutes to read me ❤️.&lt;/p&gt;

&lt;p&gt;My intention with this blog is to document the learning process in my journey as a developer. I'm not starting from scratch, I have been programming for several years. I did it as a hobby for a long time, and the last few years as a freelancer, in parallel to my current full time job as IT support.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Since a few years for this part I have set myself the goal of &lt;strong&gt;&lt;em&gt;getting a job as a developer for a foreign company&lt;/em&gt;&lt;/strong&gt;. After seeing other programmers work for companies in USA, Canada or Germany, and earn salaries in dollars, I felt that was able to do it also. Not just for the possibility of working doing something that I love like programming, but also for the peace of living with a dollarized salary in an economically unstable country like Argentina, with inflation rates that seems to never stop growing.&lt;/p&gt;

&lt;p&gt;Long story short, in early 2020 I began to study English, an essential requirement to work abroad; and parallel to my full time job as IT support I continued to carry out freelance projects for local clients in order to continue improving negotiation skills, deadlines managing, etc. In 2021, while I was still taking English classes, the goal changed, the idea of working abroad was still alive but no longer as a freelancer, but as a developer employed in a company or startup. Freelancing was definitely not for me, it requires skills that I didn’t have and that I didn’t like it. I learned a lot in those years as a freelancer and I gained experience that otherwise would have been impossible, but the reality is that all I wanted to do was programming and solve problems.&lt;/p&gt;

&lt;p&gt;With the new goal in mind, I began applying to open Backend and Fullstack positions. It was hard to take the decision and overcome my fears, but I did it finally. The responses from the recruiters were not too long in coming, and at the end of 2021 I had my first interviews with foreign companies. To my surprise, I passed the english interviews 👌, but failed the technical interviews 🙈. All this time I had been so focused on improving my English that I had neglected programming.&lt;/p&gt;

&lt;p&gt;These first interviews helped me to realize that in my self-taught learning I was skipping and taking many concepts for granted, about which I couldn’t give an answer when interviewers asked me. Beyond that in practice one knows how to write a Class or develop an API, it’s mandatory to be able to explain in word each of these concepts.&lt;/p&gt;

&lt;p&gt;So it was that in this 2022 I set myself the goal of learning all those concepts that I am missing, and documenting the process in this blog.&lt;/p&gt;

&lt;p&gt;The first step was building a learning roadmap, for which I recommend widely the site &lt;a href="https://roadmap.sh/"&gt;roadmap.sh&lt;/a&gt; for this purpose. In particular, it helped me a lot the roadmaps for &lt;a href="https://roadmap.sh/backend"&gt;Backend&lt;/a&gt; and &lt;a href="https://roadmap.sh/python"&gt;Python&lt;/a&gt;, the language that I use because I think it’s very powerful with a nice and clear syntax.&lt;/p&gt;

&lt;p&gt;With the roadmap in hand, the next step was to search for study material, and in that process I found CS50, Harvard’s Introductory Computer Science course, which I thought was a good starting point for the variety of topics it includes, such as &lt;em&gt;algorithms&lt;/em&gt;, &lt;em&gt;data structures&lt;/em&gt;, &lt;em&gt;memory management&lt;/em&gt;, &lt;em&gt;C&lt;/em&gt;, &lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;Javascript&lt;/em&gt;, &lt;em&gt;SQL&lt;/em&gt;, among others. &lt;a href="https://twitter.com/davidjmalan"&gt;David J. Malan&lt;/a&gt; is a great instructor, didactic and very clear when teaching.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
So, this will be my starting point.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
If someone feels an interest in the course, it’s totally free in the &lt;a href="https://learning.edx.org/course/course-v1:HarvardX+CS50+X/home"&gt;edX&lt;/a&gt; platform.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
See you soon!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;




&lt;p&gt;Thanks for reading. If you are interested in knowing more about me you can give me a follow or contact me at &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Documentando Mi Aprendizaje</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Wed, 20 Apr 2022 02:10:27 +0000</pubDate>
      <link>https://dev.to/luciano_dev/documentando-mi-aprendizaje-21jg</link>
      <guid>https://dev.to/luciano_dev/documentando-mi-aprendizaje-21jg</guid>
      <description>&lt;p&gt;Hola persona que lee, mi nombre es Luciano Muñoz y soy programador. Antes que nada te quiero agradecer por tomarte unos minutos para leerme ❤️.&lt;/p&gt;

&lt;p&gt;En este blog voy a intentar documentar todo el proceso de aprendizaje en mi carrera como programador. No estoy empezando de cero, programo desde hace ya varios años. Por mucho tiempo lo hice como hobby, y los últimos años como freelance, en paralelo a mi actual trabajo de 48 horas semanales como soporte de IT.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Desde hace tiempo me puse como objetivo &lt;strong&gt;&lt;em&gt;conseguir trabajo como programador para una empresa del exterior.&lt;/em&gt;&lt;/strong&gt; Luego de ver a otros programadores trabajar para empresas de USA, Canadá o Alemania, y cobrar salarios en dólares, sentí que yo también podía lograrlo. No solo por la posibilidad de dedicarme a algo que me apasiona como la programación, sino también por la tranquilidad que genera un salario dolarizado en un país económicamente inestable como Argentina, con índices de inflación que nunca paran de crecer.&lt;/p&gt;

&lt;p&gt;Long story short, a principios de 2020 comencé a estudiar inglés, requisito indispensable para trabajar para el exterior; y de forma paralela a mi trabajo fijo como soporte de IT seguí realizando proyectos freelance para clientes locales con el fin de continuar mejorando las skills de negociación, deadlines, etc. En 2021, mientras continuaba con las clases de inglés, el objetivo fue mutando, la idea de trabajar para el exterior seguía en pie, pero ya no como freelance, sino como programador empleado en una empresa o startup. El freelance definitivamente no era para mí, requería de habilidades comerciales que no poseía y no me gustaban. Aprendí mucho en esos años trabajando bajo esa modalidad y gané experiencia que de otra forma hubiese sido imposible, pero la realidad es que yo solo quería programar y resolver problemas.&lt;/p&gt;

&lt;p&gt;Con este nuevo objetivo en mente, comencé a postularme a posiciones de Backend y Fullstack. Me costó mucho tomar la decisión y superar mis miedos, pero las respuestas de los recruiters no tardaron en llegar, y finalizando el 2021 tuve mis primeras entrevistas con empresas del exterior. Para mi sorpresa, lograba pasar las entrevistas en inglés 👌, pero fallaba en las entrevistas técnicas 🙈. Todo este tiempo me había enfocado tanto en mejorar mi inglés que había descuidado la programación.&lt;/p&gt;

&lt;p&gt;Estas primeras entrevistas me sirvieron para darme cuenta que en mi aprendizaje autodidacta fui salteando y dando por sabido muchos conceptos, sobre los que no pude dar respuesta cuando me los preguntaron. Más allá de que en la práctica uno sepa cómo escribir una clase o desarrollar una API, es indispensable poder explicar en palabras cada uno de esos temas.&lt;/p&gt;

&lt;p&gt;Así fue que en este 2022 me puse como objetivo aprender todos esos conceptos que me faltan, y documentar el proceso en este blog.&lt;/p&gt;

&lt;p&gt;Comencé por armar un roadmap o plan de estudio, para lo cual recomiendo ampliamente el sitio &lt;a href="https://roadmap.sh/"&gt;roadmap.sh&lt;/a&gt;. Particularmente me fueron de gran utilidad los roadmaps para &lt;a href="https://roadmap.sh/backend"&gt;Backend&lt;/a&gt; y &lt;a href="https://roadmap.sh/python"&gt;Python&lt;/a&gt;, lenguaje que utilizo por elección ya que me parece muy potente y con una sintaxis super clara.&lt;/p&gt;

&lt;p&gt;Con roadmap en mano, el próximo paso fue buscar material de estudio para cada tema, y allí fue que di con CS50, el curso de introducción a las ciencias de la computación de Harvard, el cual me pareció un muy buen punto de arranque por la variedad de de conceptos y temas que se ven, como ser &lt;em&gt;algoritmos&lt;/em&gt;, &lt;em&gt;estructuras de datos&lt;/em&gt;, &lt;em&gt;manejo de memoria&lt;/em&gt;, &lt;em&gt;C&lt;/em&gt;, &lt;em&gt;Python&lt;/em&gt;, &lt;em&gt;SQL&lt;/em&gt;, &lt;em&gt;Javascript&lt;/em&gt;, entre otros. &lt;a href="https://twitter.com/davidjmalan"&gt;David J. Malan&lt;/a&gt; es un gran instructor, didáctico y muy claro al enseñar.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Así que este será mi punto de partida.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Si alguien esta interesado en tomar el curso, puede inscribirse totalmente gratis en el sitio  &lt;a href="https://learning.edx.org/course/course-v1:HarvardX+CS50+X/home"&gt;edX&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Nos vemos pronto!&lt;br&gt;
&lt;br&gt;&lt;/p&gt;




&lt;p&gt;Gracias por leer. Si te interesa conocer más sobre mí podes seguirme o contactarme en &lt;a href="https://www.instagram.com/luciano.webdev/"&gt;Instagram&lt;/a&gt;, &lt;a href="https://twitter.com/luciano_dev"&gt;Twitter&lt;/a&gt; o &lt;a href="https://www.linkedin.com/in/luciano-mu%C3%B1oz/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Backup en la Nube con Rclone</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Wed, 10 Jun 2020 01:31:55 +0000</pubDate>
      <link>https://dev.to/luciano_dev/backup-en-la-nube-con-rclone-5hc8</link>
      <guid>https://dev.to/luciano_dev/backup-en-la-nube-con-rclone-5hc8</guid>
      <description>&lt;p&gt;Hace unos días el cloud server de un cliente literalmente desapareció, llevándose consigo la aplicación entera, incluida la base de datos. El estrés se fue por las nubes, pero fue todavía peor cuando me di cuenta que el último backup tenia más de 90 días 😱.&lt;/p&gt;

&lt;p&gt;Siempre recomiendo a mis clientes la contratación de algún servicio de hosting que incluya backups automáticos, pero eso no siempre sucede. Si desarrollas proyectos freelance para clientes medianos o pequeños sabrás que los recursos muchas veces son limitados, que el servidor de producción sirve aplicación y base de datos, y que el único ambiente de staging es la PC que usas para desarrollar.&lt;/p&gt;

&lt;p&gt;Solía pensar que la responsabilidad no recaía sobre mi si algo llegara a ocurrir, pero al tener esta experiencia me dí cuenta que no podía simplemente desentenderme del problema y decirle al cliente que toda su información se había perdido, tenia que poder ofrecerle algún tipo de solución. Por ello decidí armarme un flow de backup simple, rápido, y replicable fácilmente en otros servidores Linux para implementar en este tipo de proyectos.&lt;/p&gt;

&lt;p&gt;Al final la historia con mi cliente terminó bien, ya que con ayuda del soporte técnico fue posible recuperar la información y volver a dejar el server operativo, pero el estrés del momento me llevo a pensar en esta solución casera de backup que te mostraré a continuación.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Backup de Información en la Nube
&lt;/h2&gt;

&lt;p&gt;Las herramientas que vamos a usar son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El comando &lt;a href="https://www.geeksforgeeks.org/zip-command-in-linux-with-examples/"&gt;zip&lt;/a&gt; de Linux&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html"&gt;mysqldump&lt;/a&gt;, &lt;a href="https://www.postgresql.org/docs/12/app-pgdump.html"&gt;pg_dump&lt;/a&gt; o el comando necesario para hacer un backup de la base de datos&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/crontab-in-linux-with-examples/"&gt;crontab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rclone.org/"&gt;Rclone&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conceptualmente la idea es muy sencilla: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crear un script bash que se encargue de comprimir los archivos y carpetas que queramos resguardar&lt;/li&gt;
&lt;li&gt;Hacer una copia del archivo en la nube&lt;/li&gt;
&lt;li&gt;Crear una tarea programada que ejecute todo esto de manera automática&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://rclone.org/"&gt;&lt;em&gt;Rclone&lt;/em&gt;&lt;/a&gt; es la herramienta principal que vamos a usar en nuestro backup, ya que nos permitirá hacer una copia del archivo en algún servicio en la nube. Soporta servicios gratuitos de almacenamiento de archivos como Dropbox y Google Drive, y servicios de pago como Amazon S3 y Google Cloud Storage, entre otros.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1 - Instalando y Configurando Rclone
&lt;/h3&gt;

&lt;p&gt;En primer lugar vamos a instalar Rclone para tenerlo disponible cuando armemos el script bash. Te recomiendo instalarlo primero en tu equipo local, ya que para configurar los servicios de almacenamiento es necesario un navegador, y si solo tienes acceso a tu servidor por SSH te será difícil de finalizar la configuración. Luego podrás copiar la configuración de tu PC al server remoto fácilmente. &lt;/p&gt;

&lt;p&gt;Instalar Rclone es muy sencillo, tanto como ejecutar el siguiente comando en la consola:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="o"&gt;[&lt;/span&gt;https://rclone.org/install.sh]&lt;span class="o"&gt;(&lt;/span&gt;https://rclone.org/install.sh&lt;span class="o"&gt;)&lt;/span&gt; | &lt;span class="nb"&gt;sudo &lt;/span&gt;bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si por algún motivo el software no se instala, en la documentación tenes los pasos para &lt;a href="https://rclone.org/install/#linux-installation-from-precompiled-binary"&gt;instalar desde el binario&lt;/a&gt; 😉. &lt;/p&gt;

&lt;p&gt;Y si estás en Windows podes bajar el instalador desde la &lt;a href="https://rclone.org/downloads/"&gt;página de descargas&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Una vez instalado Rclone vamos a configurar el servicio de almacenamiento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rclone config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acá tienes las guías para configurar &lt;a href="https://rclone.org/dropbox/"&gt;Dropbox&lt;/a&gt; y &lt;a href="https://rclone.org/drive/"&gt;Google Drive&lt;/a&gt;, y podes consultar el resto de los servicios en &lt;a href="https://rclone.org/docs/"&gt;este enlace&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Ahora que ya tenemos &lt;em&gt;Rclone&lt;/em&gt; instalado y configurado, vamos a buscar donde podemos encontrar el archivo de configuración, que luego deberemos copiar en nuestro servidor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;rclone config file
Configuration file is stored at:
/Users/MyUser/.config/rclone/rclone.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Ahora solo resta repetir el proceso de instalación de &lt;em&gt;Rclone&lt;/em&gt; en el servidor remoto. Una vez instalado, ejecutamos el comando &lt;code&gt;rclone config file&lt;/code&gt; para conocer en que directorio debemos pegar el archivo de configuración de nuestra PC local, y subimos el archivo &lt;code&gt;.conf&lt;/code&gt; a esa carpeta con algún cliente FTP o de la manera que creas conveniente.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2 - Creando el Script de Backup
&lt;/h3&gt;

&lt;p&gt;En primer lugar vamos a crear un directorio donde guardaremos nuestro script, y más adelante el archivo de backup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/backup/
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;backup.script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
El contenido del archivo de script es muy subjetivo, ya que dependerá de los archivos y carpetas que desees resguardar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Backup de la base de datos&lt;/span&gt;
mysqldump &lt;span class="nt"&gt;-u&lt;/span&gt; my_user &lt;span class="nt"&gt;-pmy_password&lt;/span&gt; my_db &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /home/my_user/backup/my_db.sql
&lt;span class="c"&gt;# Me ubico en la carpeta backup y borro último archivo de backup&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; /home/my_user/backup
&lt;span class="nb"&gt;rm&lt;/span&gt; /home/my_user/backup/&lt;span class="k"&gt;*&lt;/span&gt;.zip
&lt;span class="c"&gt;# Comienzo a crear el nuevo archivo de backup, zipeando archivos y carpetas con el comando zip&lt;/span&gt;
zip &lt;span class="nt"&gt;-ur&lt;/span&gt; &lt;span class="s2"&gt;"backup-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%d"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.zip"&lt;/span&gt; /etc/apache2/apache2.conf
zip &lt;span class="nt"&gt;-ur&lt;/span&gt; &lt;span class="s2"&gt;"backup-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%d"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.zip"&lt;/span&gt; /etc/apache2/sites-availables
zip &lt;span class="nt"&gt;-ur&lt;/span&gt; &lt;span class="s2"&gt;"backup-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +&lt;span class="s2"&gt;"%Y-%m-%d"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;.zip"&lt;/span&gt; /home/my_user/my_site/mediafiles
&lt;span class="c"&gt;# Copio el archivo de backup al servicio de almacenamiento en la nube&lt;/span&gt;
rclone copy backup-&lt;span class="k"&gt;*&lt;/span&gt;.zip remote:my_site/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
El script anterior está basado en un script real que utilizo en un servidor de producción. Hago un backup de la base de datos &lt;em&gt;MySQL&lt;/em&gt;, luego genero el archivo comprimido &lt;code&gt;backup-aaaa-mm-dd.zip&lt;/code&gt; (donde &lt;em&gt;aaaa-mm-dd&lt;/em&gt; corresponde a la fecha de creación del archivo) al cual agrego el archivo de configuración de &lt;em&gt;apache&lt;/em&gt; y los &lt;em&gt;virtual hosts&lt;/em&gt;, comprimo la carpeta &lt;em&gt;mediafiles&lt;/em&gt; que contiene los archivos subidos por los usuarios, y por último le digo a &lt;em&gt;rclone&lt;/em&gt; que copie el archivo de backup dentro de la carpeta &lt;em&gt;my_site&lt;/em&gt; del servicio que hemos declarado como &lt;code&gt;remote&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Rclone tiene muchas más funcionalidades incorporadas que podes ver en la &lt;a href="https://rclone.org/commands/"&gt;documentación&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Por último le damos permisos de ejecución al script, y lo ejecutamos para probar su funcionamiento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;chmod&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;script&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Si todo va bien solo resta configurar &lt;em&gt;crontab&lt;/em&gt; para que la tarea de backup se ejecute automáticamente.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3 - Backup Automático
&lt;/h3&gt;

&lt;p&gt;Para que el backup se ejecute de manera automática vamos a crear una tarea con &lt;em&gt;crontab&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Por si no lo sabes, &lt;em&gt;crontab&lt;/em&gt; es el comando que nos ofrece el entorno Linux para administrar las tareas programadas. Básicamente es un archivo de texto donde agregaremos una nueva linea indicando la programación de nuestra tarea.&lt;/p&gt;

&lt;p&gt;La sintaxis de &lt;em&gt;crontab&lt;/em&gt; tiene los siguientes parámetros, con los que podemos jugar para asignar la programación que deseamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;m &lt;span class="o"&gt;=&lt;/span&gt; minuto &lt;span class="o"&gt;(&lt;/span&gt;0-60&lt;span class="o"&gt;)&lt;/span&gt;
h &lt;span class="o"&gt;=&lt;/span&gt; hora &lt;span class="o"&gt;(&lt;/span&gt;0-23&lt;span class="o"&gt;)&lt;/span&gt;
dom &lt;span class="o"&gt;=&lt;/span&gt; día del mes &lt;span class="o"&gt;(&lt;/span&gt;1-31&lt;span class="o"&gt;)&lt;/span&gt;
mon &lt;span class="o"&gt;=&lt;/span&gt; mes &lt;span class="o"&gt;(&lt;/span&gt;1-12&lt;span class="o"&gt;)&lt;/span&gt;
dow &lt;span class="o"&gt;=&lt;/span&gt; día de la semana &lt;span class="o"&gt;(&lt;/span&gt;1-7&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; comando a ejecutar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Para agregar nuestra tarea debemos ejecutar crontab con el parámetro &lt;code&gt;-e&lt;/code&gt; (edición):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;crontab &lt;span class="nt"&gt;-e&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
A continuación te dejo algunos ejemplos para te vayas dando una idea de como programar las tareas en &lt;em&gt;crontab&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;m h dom mon dow &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;span class="c"&gt;# Cada viernes a las 4:00&lt;/span&gt;
0 4 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; 5 /home/my_user/backup/backup.script
&lt;span class="c"&gt;# El día 10 de cada mes a las 15:30&lt;/span&gt;
30 15 10 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/my_user/backup/backup.script
&lt;span class="c"&gt;# Todos los días a las 20:00&lt;/span&gt;
0 20 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; /home/my_user/backup/backup.script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Para finalizar guardamos el archivo y eso es todo! La tarea programada debería ejecutar el script automáticamente. Solo tendremos que controlar que los backups se estén guardando en la nube.&lt;/p&gt;

&lt;p&gt;Con estos pocos pasos ya tenemos configurado un backup automático que se guardará en la nube, y que es sencillo de implementar y replicar en otro server.&lt;/p&gt;






&lt;p&gt;Nuevamente gracias por haber llegado hasta acá y leído este post. Espero que te sirva y lo puedas aplicar. &lt;/p&gt;

&lt;p&gt;Me gustaría conocer tus historias de terror y como las resolviste. Si tenes algo para contarme no dudes en dejarme un comment, o mandarme un twit a &lt;a href="https://twitter.com/luciano_dev"&gt;@luciano_dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si te gusta mi contenido me ayudarías mucho difundiéndolo con tus amigos o en tu feed de Twitter, y si te gustaría que escriba sobre algo en particular dejame un comment. Espero tu feedback para ir mejorando con cada nuevo post ❤️.&lt;/p&gt;

</description>
      <category>backup</category>
      <category>linux</category>
      <category>rclone</category>
    </item>
    <item>
      <title>Virtualenv y Pip para crear Entornos Virtuales de Python</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Mon, 01 Jun 2020 13:51:34 +0000</pubDate>
      <link>https://dev.to/luciano_dev/virtualenv-y-pip-para-crear-entornos-virtuales-de-python-31l6</link>
      <guid>https://dev.to/luciano_dev/virtualenv-y-pip-para-crear-entornos-virtuales-de-python-31l6</guid>
      <description>&lt;p&gt;&lt;a href="https://virtualenv.pypa.io/en/latest/index.html"&gt;&lt;em&gt;Virtualenv&lt;/em&gt;&lt;/a&gt; es una herramienta para crear entornos de &lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; aislados, es decir ambientes completamente separados de la instalación global de Python, con sus propias dependencias y versiones.&lt;/p&gt;

&lt;p&gt;Cuando comencé a programar aplicaciones web, &lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt; era uno de los &lt;a href="https://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador"&gt;frameworks MVC&lt;/a&gt; de moda. Aún no existía React, el ecosistema Javascript se reducía a jQuery, Node.js era una novedad y Rails era la joyita. Era tanto el hype con Django que venia creciendo muy rápido y con un ciclo de release muy corto, por lo que salían versiones muy seguido con bugfixes, nuevas features y algunos breaking changes.&lt;/p&gt;

&lt;p&gt;En mi primera aplicación había usado Django 1.4 pero al comenzar a programar la segunda aplicacion el framework ya se encontraba en la version 1.8, y al actualizar esta dependencia desate el caos. Aquella primera aplicación web se empezó a romper por todos lados. Era obvio, los breaking changes entre Django 1.4 y 1.8 hacían que nada funcionase como debía.&lt;/p&gt;

&lt;p&gt;Buscando una solución fue que encontré &lt;em&gt;Virtualenv&lt;/em&gt;. Con esta herramienta pude crear dos entornos virtuales completamente aislados donde instalar las dependencias de cada proyecto sin que interfieran entre si. Esto me permitía correr las dos aplicaciones en paralelo sin inconvenientes, y me daba la seguridad de que podía instalar y actualizar cualquier dependencia sin miedo a romper otra cosa mas que la misma aplicación en la que me encontraba trabajando.&lt;/p&gt;

&lt;p&gt;Virtualenv ya se ha vuelto un estándar para la comunidad, tal es así que desde Python 3.3 se agrego al core el modulo &lt;a href="https://docs.python.org/3/library/venv.html"&gt;venv&lt;/a&gt;, que nos permite crear entornos virtuales de forma nativa. Aunque aún no posee todas las virtudes de Virtualenv se sabe que es un modulo en continuo desarrollo. Peeeeero... por el momento &lt;em&gt;Virtualenv&lt;/em&gt; sigue siendo la mejor opción.&lt;/p&gt;



&lt;h1&gt;
  
  
  ¿Cómo instalo Virtualenv?
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Virtualenv&lt;/em&gt; se instala, al igual que la mayoría de las dependencias de Python, con &lt;em&gt;pip&lt;/em&gt;. Solo necesitamos correr este comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;virtualenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h1&gt;
  
  
  ¿Cómo se usa Virtualenv?
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Virtualenv&lt;/em&gt; es muy sencillo de usar y no requiere configuración. Generalmente solo necesitaremos de 3 comandos que nos permitirán crear, activar y desactivar los entornos virtuales.&lt;/p&gt;

&lt;p&gt;Hay distintas maneras de organización, algunos programadores prefieren mantener todos sus entornos virtuales dentro de un mismo directorio, pero yo personalmente prefiero crearlos dentro del directorio de cada proyecto. De esta manera puedo asignarle siempre el mismo nombre, y me resulta mucho mas sencillo para trabajar.&lt;/p&gt;

&lt;p&gt;Para &lt;em&gt;crear&lt;/em&gt; un entorno virtual primero debemos ubicarnos en el directorio elegido y luego ingresar el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;virtualenv &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Este comando nos creará dentro de la carpeta &lt;code&gt;env&lt;/code&gt; un entorno virtual con el interprete de Python por defecto de nuestro sistema operativo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Y si necesitamos crear un entorno con otra versión de Python?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sencillo... usamos el flag &lt;code&gt;--python&lt;/code&gt; e indicamos la ruta del interprete de Python que querramos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;virtualenv &lt;span class="nt"&gt;--python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin/python3.8 &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;El entorno virtual instalara &lt;em&gt;pip&lt;/em&gt; y &lt;em&gt;wheel&lt;/em&gt; por defecto, de manera que con solo activarlo ya podremos comenzar a instalar las dependencias que necesitamos.&lt;/p&gt;

&lt;p&gt;Para &lt;em&gt;activar&lt;/em&gt; el entorno virtual nos ubicamos en el directorio donde lo hemos creado y ejecutamos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mac y Linux&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate

&lt;span class="c"&gt;# Windows&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;El prompt de nuestra consola ahora deberá mostrarnos el nombre del entorno virtual, lo cual nos da la seguridad de que se activo correctamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Por último, una vez que hayamos terminado de trabajar, o si necesitamos cambiar de entorno, lo &lt;em&gt;desactivamos&lt;/em&gt; con el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;$ &lt;/span&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Para &lt;em&gt;borrar&lt;/em&gt; un entorno virtual basta simplemente con eliminar su carpeta.&lt;/p&gt;

&lt;p&gt;Con estos comandos ya tenemos practicamente todo lo que necesitamos para usar &lt;em&gt;Virtualenv&lt;/em&gt;, pero en la ayuda podemos consultar las demás opciones disponibles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;virtualenv &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Por último, nunca te olvides de ir guardando las dependencias de tus proyectos con el comando &lt;code&gt;freeze&lt;/code&gt; de &lt;em&gt;pip&lt;/em&gt;, ya que este nos permitirá replicar nuestro entorno virtual en otro equipo de manera sencilla y rápida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generar un archivo con las dependencias&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pip freeze &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Instalar las dependencias desde el archivo generado&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;h1&gt;
  
  
  Conclusiones
&lt;/h1&gt;

&lt;p&gt;Espero que esto te sirva si estas empezando a programar con Python, y recordá que la mejor manera de aprender es haciendo, y al hacer vamos a equivocarnos.&lt;/p&gt;

&lt;p&gt;Tenemos que darle mucho amor a lo que aprendemos desde la necesidad, porque nos permite comprender el valor real que nos aporta para resolver nuestro problema, y puedo asegurarte que es un aprendizaje que vamos a incorporar para siempre.&lt;/p&gt;

&lt;p&gt;Gracias por haber llegado hasta el final. Si este post te gustó dejame un comment o mandame un tweet (&lt;a href="https://twitter.com/luciano_dev"&gt;@luciano_dev&lt;/a&gt;) porque me interesa conocer tu opinión.&lt;/p&gt;

&lt;p&gt;¡Hasta el próximo post! ❤️&lt;/p&gt;

</description>
      <category>python</category>
      <category>virtualenv</category>
      <category>pip</category>
    </item>
    <item>
      <title>Web Scraping con Python</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Thu, 21 May 2020 15:21:15 +0000</pubDate>
      <link>https://dev.to/luciano_dev/web-scraping-con-python-1kl3</link>
      <guid>https://dev.to/luciano_dev/web-scraping-con-python-1kl3</guid>
      <description>&lt;p&gt;&lt;em&gt;Scraping&lt;/em&gt; es una técnica para leer y extraer datos de un sitio web cuando no existe un medio que nos permita obtener está información "por el buen camino", como una API Rest o RSS. El &lt;em&gt;scraping&lt;/em&gt; está relacionado a lo que hoy conocemos como &lt;em&gt;crawler&lt;/em&gt;, o simplemente &lt;em&gt;bot&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Sin ir más lejos Google y los demás buscadores tienen bots que indexan la web constantemente almacenando toda la información que luego ves en los resultados de búsqueda. Pero no solo los buscadores utilizan &lt;em&gt;scraping&lt;/em&gt;, también sitios como los comparadores de precios de productos, hoteles, vuelos, y muchos otros más.&lt;/p&gt;

&lt;p&gt;Lo que quiero mostrarte en este post es que nosotros podemos programar nuestro propio bot, ya que se trata de una técnica que podemos aprender sin mayores problemas. No vas a salir programando el próximo Google, pero por ejemplo vas a poder programar un bot para hacer un seguimiento del precio de ese producto que tanto queres, o para consultar los titulares de los sitios de noticias que lees a diario. Y lo cool es que con un poco de ingenio podemos lograr cosas mucho más increíbles.&lt;/p&gt;

&lt;p&gt;Si te interesa conocer esta técnica más a fondo te recomiendo el libro "&lt;a href="https://www.amazon.com/-/es/Ryan-Mitchell/dp/1491910291"&gt;Web Scraping with Python&lt;/a&gt;". Con solo unos capítulos vas a entender lo potente que es el &lt;em&gt;scraping&lt;/em&gt;, y como implementarlo con Python 🐍.&lt;/p&gt;

&lt;p&gt;Let's go!&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Cómo funciona el &lt;em&gt;scraping&lt;/em&gt;?
&lt;/h2&gt;

&lt;p&gt;Existen distintas técnicas, pero lo normal es scrapear un sitio web a través del código &lt;a href="https://es.wikipedia.org/wiki/HTML"&gt;HTML&lt;/a&gt;, indicándole a nuestro bot que tags y atributos debe buscar para encontrar la información que queremos.&lt;/p&gt;

&lt;p&gt;Imaginemos que deseamos obtener los titulares de un sitio de noticias que tiene la siguiente estructura HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"layout-articles"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Noticia 1 --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/noticia-1"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Noticia 1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                Noticia 1
            &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"noticia-1.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Noticia 2 --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/noticia-2"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Noticia 2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                Noticia 2
            &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"noticia-2.jpg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuestro software debería buscar la etiqueta &lt;code&gt;section class="layout-articles"&lt;/code&gt; que actúa como un wrapper de las noticias, obtener todos los tags &lt;code&gt;h1 class="title"&lt;/code&gt;, y de allí extraer la etiqueta &lt;code&gt;a&lt;/code&gt; que contiene el título y la URL de las noticias.&lt;/p&gt;

&lt;p&gt;Esto es solo un sencillo ejemplo para que vayas entendiendo la idea, y que te servirá para comprender mejor lo que vamos a programar.&lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Qué vamos a programar?
&lt;/h2&gt;

&lt;p&gt;Existe un sitio genial llamado &lt;a href="http://simpledesktops.com/"&gt;Simple Desktops&lt;/a&gt; que contiene una colección super cool de wallpapers totalmente fancy, y nuestro bot se encargará de recorrer las distintas páginas de esta web y descargar automáticamente todos los wallpapers 👏👏👏. &lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l41lUJ1YoZB1lHVPG/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l41lUJ1YoZB1lHVPG/giphy.gif" alt="Homer's bird"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como ves, lo divertido del &lt;em&gt;scraping&lt;/em&gt; es que el limite lo pone tu imaginación.&lt;/p&gt;

&lt;p&gt;Pero primero analicemos la estructura del sitio y el código HTML, ya que esto nos permitirá comprender que pasos debe seguir nuestro bot para cumplir su objetivo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La web contiene una paginación tipo &lt;code&gt;/browse/&lt;/code&gt;, &lt;code&gt;/browse/1/&lt;/code&gt;, &lt;code&gt;/browse/2/&lt;/code&gt;, etc., donde se muestran los wallpapers.&lt;/li&gt;
&lt;li&gt;Cada wallpaper es un &lt;code&gt;div class="desktop"&lt;/code&gt; que dentro contiene una etiqueta &lt;code&gt;img&lt;/code&gt;. El atributo &lt;code&gt;src&lt;/code&gt; de esta etiqueta es lo que nos interesa ya que contiene la URL para descargar el wallpaper.&lt;/li&gt;
&lt;li&gt;El sitio usa un generador de thumbnails que viene implícito en la URL de las imágenes, pero si eliminamos el texto que hace referencia al resize accedemos a la imagen original: Apple_Park.png~~.295x184_q100.png~~ 😎.&lt;/li&gt;
&lt;li&gt;La URL hacia la próxima página la podemos obtener del tag &lt;code&gt;a class="more"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con la información anterior podemos ver que el algoritmo debe hacer lo siguiente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Comenzará haciendo un request a la URL &lt;code&gt;/browse/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Del código HTML debe obtener las URL de los wallpapers&lt;/li&gt;
&lt;li&gt;Luego debe formatear las URL para quitar el resize&lt;/li&gt;
&lt;li&gt;Procesar las descargas de las imágenes&lt;/li&gt;
&lt;li&gt;Obtener la URL de la página siguiente y volver a comenzar&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Genial, ahora que ya sabemos lo que tenemos que hacer, empecemos con la parte divertida... &lt;strong&gt;¡a codear! 🎈&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ¿Como programar un bot en Python?
&lt;/h2&gt;

&lt;p&gt;Estas son las librerías que vamos a usar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/os.html"&gt;os&lt;/a&gt;: para manejo de rutas de archivos y carpetas&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/re.html"&gt;re&lt;/a&gt;: para expresiones regulares&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.python.org/3/library/shutil.html"&gt;shutil&lt;/a&gt;: para operaciones con archivos&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://requests.readthedocs.io/es/latest/"&gt;requests&lt;/a&gt;: para realizar peticiones HTTP&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/"&gt;BeautifulSoup&lt;/a&gt;: para parsear el código HTML, es el corazón de nuestro bot ❤️&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;BeautifulSoup&lt;/em&gt; y &lt;em&gt;requests&lt;/em&gt; son dos librerías que no vienen incluidas con Python, por lo que tendrás que instalarlas con &lt;code&gt;pip&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ pip install beautifulsoup4
$ pip install requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para hacer el código más legible y fácil de debugear iremos separando la lógica en funciones, cada una de las cuales cumplirá una tarea particular.&lt;/p&gt;

&lt;p&gt;Bien, primero te recomiendo que crees una carpeta para este proyecto y dentro el archivo &lt;code&gt;simpledesktop-bot.py&lt;/code&gt;, al cual comenzaremos importando las librerías:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;shutil&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;requests.exceptions&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;HTTPError&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El punto de entrada a nuestra app será la función &lt;code&gt;init()&lt;/code&gt;, que funciona como un &lt;em&gt;constructor&lt;/em&gt;. Allí setearemos los datos iniciales, como la URL del sitio web, el path desde donde comenzara a correr el bot, y el directorio donde guardaremos los wallpapers. Por defecto se creará la carpeta &lt;code&gt;wallpapers&lt;/code&gt; dentro del directorio de nuestro proyecto y allí haremos las descargas. Para ello primero chequeamos con &lt;code&gt;os.path.exists&lt;/code&gt; si este directorio ya existe, y de no existir lo creamos con &lt;code&gt;os.makedirs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último llamamos a la función &lt;code&gt;processPage()&lt;/code&gt; que iniciará el scraping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'http://simpledesktops.com'&lt;/span&gt;
    &lt;span class="n"&gt;first_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'/browse/'&lt;/span&gt;
    &lt;span class="n"&gt;download_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abspath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="s"&gt;'wallpapers'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;first_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;processPage()&lt;/code&gt; es un wrapper que se encargará de realizar las llamadas a las demás funciones. Por parámetro recibirá la URL inicial y con cada ejecución se vuelve a llamar recursivamente recibiendo la nueva página a procesar, lo cual nos permite hacer un loop que finalizará al alcanzar la última página.&lt;/p&gt;

&lt;p&gt;La primera función llamada es &lt;code&gt;getPageContent()&lt;/code&gt;, que recibe por parámetros las variables &lt;code&gt;url&lt;/code&gt; y &lt;code&gt;path&lt;/code&gt;, con las cuales hace el request HTTP y devuelve un diccionario con estos datos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;images&lt;/em&gt;: es una lista con las URL de los wallpapers a descargar&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;next_page&lt;/em&gt;: contiene la URL de la siguiente página a procesar&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La segunda función que ejecuta es &lt;code&gt;downloadWallpaper()&lt;/code&gt; a la cual le pasaremos las URL de los wallpapers y se encargará de procesar las descargas.&lt;/p&gt;

&lt;p&gt;Por último tenemos la recursión, verificamos si &lt;code&gt;next_page&lt;/code&gt; tiene un valor asignado y volvemos a llamar a &lt;code&gt;processPage()&lt;/code&gt; con el nuevo &lt;code&gt;path&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;PATH:'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'========================='&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;wallpapers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getPageContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;downloadWallpaper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'This page does not contain any wallpaper'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="n"&gt;processPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;download_directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'THIS IS THE END, BUDDY'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como dije anteriormente &lt;code&gt;getPageContent()&lt;/code&gt; es la primer función llamada por &lt;code&gt;processPage()&lt;/code&gt;, y su objetivo es retornar las URL de los wallpapers y la URL de la página siguiente. &lt;/p&gt;

&lt;p&gt;Primero definimos las variables &lt;code&gt;image&lt;/code&gt; y &lt;code&gt;next_page&lt;/code&gt; que guardarán los datos a retornar, y las  inicializamos con valores por defecto.&lt;/p&gt;

&lt;p&gt;Luego llamamos a la función &lt;code&gt;requestPage()&lt;/code&gt; (&lt;em&gt;para que el código sea más fácil de leer he abstraído el request HTTP a su propia función, que veremos más adelante&lt;/em&gt;) que nos retornará el código HTML listo para ser manipulado. Y aquí es donde veremos la magia de BeautifulSoup! Primero vamos usar el método &lt;code&gt;find_all&lt;/code&gt;  para obtener todos los wallpapers que, tal como vimos en el análisis de la estructura HTML, están representados por el tag &lt;code&gt;div class="desktop"&lt;/code&gt;, y los guardamos en la variable &lt;code&gt;wallpapers&lt;/code&gt;. Luego iteramos estos elementos y usando el método &lt;code&gt;find&lt;/code&gt; buscaremos la etiqueta &lt;code&gt;img&lt;/code&gt;, de la cual obtendremos el atributo &lt;code&gt;src&lt;/code&gt; que contiene la URL del wallpaper. Con este dato iremos completando nuestra lista &lt;code&gt;images&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por último buscamos el tag &lt;code&gt;a class="more"&lt;/code&gt;, extraemos su URL del atributo &lt;code&gt;href&lt;/code&gt; y lo asignamos a la variable &lt;code&gt;next_page&lt;/code&gt; que creamos al principio de la función.&lt;/p&gt;

&lt;p&gt;Retornamos &lt;code&gt;images&lt;/code&gt; y &lt;code&gt;next_page&lt;/code&gt; en un diccionario.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;getPageContent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;next_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requestPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Search wallpapers URL
&lt;/span&gt;        &lt;span class="n"&gt;wallpapers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'div'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'desktop'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;wp&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'img'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'src'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

        &lt;span class="c1"&gt;# Search for next page URL
&lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;more_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'more'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
            &lt;span class="n"&gt;next_page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;more_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'href'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'images'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'next_page'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;next_page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anteriormente usamos la función &lt;code&gt;requestPage()&lt;/code&gt;, que tal como dijimos, se encarga del request HTTP y de retornar el HTML ya parseado. Para el request usamos &lt;code&gt;requests.get&lt;/code&gt; y guardamos el payload en la variable &lt;code&gt;raw_html&lt;/code&gt;. Por último parseamos el HTML plano con &lt;em&gt;BeautifulSoup&lt;/em&gt; y lo retornamos.&lt;/p&gt;

&lt;p&gt;Con &lt;code&gt;try/except&lt;/code&gt; nos aseguramos de interceptar los errores y mostrar sus respectivos mensajes de error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;requestPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;raw_html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'html.parser'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Error parsing HTML code'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La segunda función llamada por &lt;code&gt;processPage()&lt;/code&gt; es &lt;code&gt;downloadWallpaper()&lt;/code&gt;, que recibe la lista de URL y descarga los wallpapers.&lt;/p&gt;

&lt;p&gt;La primer tarea de esta función es hacer una pequeña modificación a las URL, porque recordemos que el sitio web usa un generador de thumbnails que viene implícito en el nombre de la imagen, y sin esta modificación estaríamos descargando un wallpaper de &lt;em&gt;300x189 px&lt;/em&gt;. Quitando este resize vamos a poder descargar las imágenes en su tamaño original. &lt;br&gt;
Veamos un ejemplo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="http://static.simpledesktops.com/uploads/desktops/2020/03/30/piano.jpg.300x189_q100.png"&gt;http://static.simpledesktops.com/uploads/desktops/2020/03/30/piano.jpg.300x189_q100.png&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pongamos la atención en el nombre del wallpaper, vemos que en primer lugar se incluye el nombre del archivo con su extensión original (piano.jpg) y luego el "código" del resize (300x189_q100.png). Lo que necesitamos es obtener la misma URL pero sin esta última parte, para lo cual vamos a usar una expresión regular.&lt;/p&gt;

&lt;p&gt;Con la regex &lt;code&gt;'^.+?(\.png|jpg)'&lt;/code&gt; buscamos la primer ocurrencia de &lt;code&gt;.png&lt;/code&gt; o &lt;code&gt;.jpg&lt;/code&gt; comenzando desde el inicio de la URL. Si hay match obtenemos todo ese string, con lo cual nos quedará la URL sin el resize, y si no hay match quiere decir que no encuentra la extensión de la imagen y por lo tanto no es una URL válida.&lt;/p&gt;

&lt;p&gt;Siguiendo con el código, en la variable &lt;code&gt;file_path&lt;/code&gt; generamos la ruta completa a la imagen y chequeamos si ya existe en nuestro disco para no volver a descargarla. Si la imagen no existe haremos lo siguiente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usamos &lt;code&gt;request.get&lt;/code&gt; para obtener la imagen por &lt;em&gt;streaming&lt;/em&gt; y guardamos la referencia a este objeto en la variable &lt;code&gt;wp_file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Con la función &lt;code&gt;open&lt;/code&gt; abrimos el archivo local (que será creado en este momento, aunque se encontrará vacío) en modo binario y escritura, y lo referenciamos con el nombre de variable &lt;code&gt;output_file&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Por último usamos &lt;code&gt;shutil.copyfileobj&lt;/code&gt; para copiar el contenido de &lt;code&gt;wp_file&lt;/code&gt; dentro de &lt;code&gt;output_file&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Con esto ya tendremos descargado el wallpaper en nuestro disco.&lt;/p&gt;

&lt;p&gt;Los bloques &lt;code&gt;with&lt;/code&gt; nos permitirán liberar automáticamente la memoria usada por Python para el request HTTP y la creación del archivo local, por lo cual podemos proceder a descargar el siguiente wallpaper.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;downloadWallpaper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;wallpapers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;match_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'^.+?(\.png|jpg)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;formated_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match_url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rfind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
            &lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;formated_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;wp_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'wb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;copyfileobj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wp_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Wallpaper URL is invalid'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eso es todo, solo resta incluir la llamada a la función &lt;code&gt;init()&lt;/code&gt; que da inicio a la ejecución del código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para poner a correr nuestro bot abrimos una consola en el directorio del proyecto y ejecutamos el comando &lt;code&gt;python3 simpledesktop-bot.py&lt;/code&gt;, y veremos algo como lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python3 simpledesktop-bot.py

PATH: /browse/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/sphericalharmonics1.png
/Users/MyUser/simple-desktop-scraper/wallpapers/Dinosaur_eye_2.png
/Users/MyUser/simple-desktop-scraper/wallpapers/trippin.png
...

PATH: /browse/2/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/Apple_Park.png
/Users/MyUser/simple-desktop-scraper/wallpapers/triangles.png
/Users/MyUser/simple-desktop-scraper/wallpapers/thanksgiving_twelvewalls.png
...

PATH: /browse/3/
=========================
/Users/MyUser/simple-desktop-scraper/wallpapers/minimalistic_rubik_cube_2880.png
/Users/MyUser/simple-desktop-scraper/wallpapers/Nesting_Dolls.png
/Users/MyUser/simple-desktop-scraper/wallpapers/flat_bamboo_wallpaper.png

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

&lt;/div&gt;



&lt;p&gt;El código completo lo podes encontrar en el repositorio de GitHub y si te gustó dejale una estrellita al repo 😉&lt;br&gt;
&lt;a href="https://github.com/luciano-im/SimpleDesktop-Bot"&gt;SimpleDesktop-Bot&lt;/a&gt;&lt;/p&gt;



&lt;h2&gt;
  
  
  Conclusiones
&lt;/h2&gt;

&lt;p&gt;En primer lugar gracias por haber llegado hasta acá, significa mucho para mí que hayas leído este post.&lt;/p&gt;

&lt;p&gt;Espero que hayas podido aprender algo nuevo ya que ese es mi objetivo, y si es así entonces dejame un comment o mandame un tweet porque me gustaría saberlo.&lt;/p&gt;

&lt;p&gt;También me gustaría conocer sus propios bot, así que si te animas a desarrollar uno contame porque me interesa saber. Y si crees que podes aportar a nuestro Simple Desktop bot (porque también es tuyo) entonces animate a mandarme un pull request. No hay cosa que me gustaría más.&lt;/p&gt;

&lt;p&gt;Si te gusta mi contenido me ayudarías mucho difundiéndolo con tus amigos o en tu feed de Twitter, y si te gustaría que escriba sobre algo en particular dejame un comment. Espero tu feedback para ir mejorando con cada nuevo post ❤️.&lt;/p&gt;

</description>
      <category>python</category>
      <category>scraping</category>
      <category>html</category>
    </item>
    <item>
      <title>Comparti tu Localhost de forma segura con Ngrok y Localtunnel</title>
      <dc:creator>Luciano Muñoz</dc:creator>
      <pubDate>Sun, 10 May 2020 02:45:50 +0000</pubDate>
      <link>https://dev.to/luciano_dev/comparti-tu-localhost-de-forma-segura-con-ngrok-y-localtunnel-37ea</link>
      <guid>https://dev.to/luciano_dev/comparti-tu-localhost-de-forma-segura-con-ngrok-y-localtunnel-37ea</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://ngrok.com/"&gt;ngrok&lt;/a&gt;&lt;/strong&gt; y &lt;strong&gt;&lt;a href="https://localtunnel.github.io/www/"&gt;Localtunnel&lt;/a&gt;&lt;/strong&gt; son dos aplicaciones que nos permiten exponer en internet una conexión HTTPS hacia nuestro localhost, de manera que podemos compartir, por ejemplo, nuestro servidor web local; incluso aunque nos encontremos detrás de un firewall. No solo podemos permitir el acceso a nuestro servidor web, sino también a cualquier puerto TCP local donde estemos corriendo algún servicio, como un servidor SSH, FTP, o una base de datos.&lt;/p&gt;

&lt;p&gt;¿Qué logramos con esto?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Podemos hacer testing de nuestro sitio web desde el móvil, tablet o cualquier otro dispositivo de manera rápida y sencilla.&lt;/li&gt;
&lt;li&gt;Otros co-workers pueden acceder a nuestro servidor local de manera segura para revisar un proyecto en conjunto.&lt;/li&gt;
&lt;li&gt;Podemos hacer una demo con nuestros clientes en cuestión de segundos y sin necesidad de deployar a un servidor, configurar DNS, ni nada de eso. &lt;strong&gt;Es magia!&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En este post veremos las ventajas y desventajas de cada app para que puedan decidir si optan por una u otra, o las dos 😉.&lt;/p&gt;



&lt;h1&gt;
  
  
  ngrok
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Ngrok&lt;/em&gt; tiene la particularidad de que con la cuenta gratuita nos ofrece tunnels sin timeout, es decir que pueden estar corriendo indefinidamente, por ello les recomiendo que se &lt;a href="https://dashboard.ngrok.com/signup"&gt;creen una cuenta&lt;/a&gt; ya que es muy sencillo y lo pueden hacer logueandose con Google o GitHub si lo desean.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lo primero que debemos hacer es &lt;a href="https://ngrok.com/download"&gt;descargar ngrok&lt;/a&gt; para nuestro sistema operativo.&lt;/li&gt;
&lt;li&gt;Una vez descargado descomprimimos el ejecutable y lo copiamos en una carpeta de nuestra preferencia (yo lo tengo en la raíz del directorio donde guardo todos mis proyectos 🎈).&lt;/li&gt;
&lt;li&gt;Luego iniciamos sesión en nuestra cuenta de &lt;em&gt;ngrok&lt;/em&gt; y copiamos el &lt;a href="https://dashboard.ngrok.com/auth/your-authtoken"&gt;Authtoken&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Abrimos una consola en la carpeta donde copiamos la app y la vinculamos a nuestra cuenta con el comando:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ngrok authtoken &amp;lt;YOUR_AUTH_TOKEN&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ya podemos abrir una conexión a nuestro server:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ngrok http 80
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lo que hicimos con el último comando es abrir un túnel HTTP en el puerto 80. &lt;em&gt;ngrok&lt;/em&gt; nos va a mostrar algo como lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ngrok by @inconshreveable

Session Status            online
Account                   Luciano Muñoz (Plan: Free)
Version                   2.3.35
Region                    United States (us)
Web Interface             http://127.0.0.1:4040
Forwarding                http://b9ccb437.ngrok.io -&amp;gt; localhost:80
Forwarding                https://b9ccb437.ngrok.io -&amp;gt; localhost:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Como podemos ver &lt;em&gt;ngrok&lt;/em&gt; nos asigna una URL random &lt;code&gt;https://b9ccb437.ngrok.io&lt;/code&gt; y cualquiera que la tenga va a poder comunicarse con nuestro servidor local. Hace la prueba ingresando desde tu smartphone!&lt;/p&gt;

&lt;p&gt;Otra de las cosas cool de &lt;em&gt;ngrok&lt;/em&gt; es el inspector web donde podemos visualizar en tiempo real todo el trafico que esta pasando por nuestro tunnel, con detalle de los request, responses, headers, payload, etc. Para ingresar al inspector solo debemos acceder a la URL &lt;code&gt;http://127.0.0.1:4040&lt;/code&gt; desde el navegador.&lt;/p&gt;

&lt;p&gt;El punto en contra es que las URL persistentes son una característica de la versión paga, de modo que con nuestra cuenta &lt;em&gt;free&lt;/em&gt; al reiniciar el tunnel nos va a proporcionar una URL distinta. Pero, siempre tenes la opción de pagar por la app para contribuir con su desarrollo 😉 y obtener todas las funcionalidades.&lt;/p&gt;

&lt;p&gt;Por ultimo, como dije al principio del post, es posible crear un tunnel hacia cualquier puerto TCP, por ejemplo &lt;code&gt;ngrok tcp 22&lt;/code&gt;. Pero esto te lo dejo para que lo investigues por tu cuenta 👍!&lt;/p&gt;



&lt;h1&gt;
  
  
  Localtunnel
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Localtunnel&lt;/em&gt; esta escrito en javascript y se instala mediante &lt;a href="https://www.npmjs.com/get-npm"&gt;NPM&lt;/a&gt;, el gestor de paquetes de Node.js, lo que implica que debemos asegurarnos de tener &lt;a href="https://nodejs.org/es/"&gt;Node.js&lt;/a&gt; instalado previamente.&lt;/p&gt;

&lt;p&gt;La instalación es mucho mas sencilla que en el caso de &lt;em&gt;ngrok&lt;/em&gt; si ya contamos con los requerimientos de los que les hablé anteriormente. Abrimos una consola y tecleamos el siguiente comando para instalar &lt;em&gt;Localtunnel&lt;/em&gt; de forma global en nuestro sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install -g localtunnel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Ya podemos crear nuestro tunnel al puerto que deseamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lt --port 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Luego de ejecutar el comando anterior vamos a recibir una respuesta como la siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your url is: &amp;lt;https://bxtwmwsppb.localtunnel.me&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Podemos ver que ya tenemos nuestro tunnel creado hacia el puerto 80 de nuestro localhost.&lt;/p&gt;

&lt;p&gt;Cuando ejecutamos &lt;em&gt;Localtunnel&lt;/em&gt; sin parámetros extra nos proporciona una URL random, de la misma forma que lo hace &lt;em&gt;ngrok&lt;/em&gt;, pero si usamos el parámetro &lt;code&gt;--subdomain&lt;/code&gt; podemos solicitar un un subdominio personalizado, el cual podremos volver a utilizar cada vez que sea necesario, siempre y cuando dicho subdominio no este siendo utilizado ya por otra persona. Esto nos da la posibilidad de poder compartir siempre la misma URL dado que la misma será persistente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lt --port 80 --subdomain mylocalhost
your url is: &amp;lt;https://mylocalhost.localtunnel.me&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;&lt;em&gt;Localtunnel&lt;/em&gt; sin embargo no es tan estable como &lt;em&gt;ngrok&lt;/em&gt; por lo que debemos monitorear la consola cada cierto tiempo para verificar que el túnel sigue activo.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Pros y Cons
&lt;/h1&gt;



&lt;h3&gt;
  
  
  ngrok
&lt;/h3&gt;

&lt;p&gt;🔥   Es muy estable, puede estar corriendo por días sin problemas&lt;br&gt;
🔥   Tiene un inspector web para monitorear todo el trafico que pasa a través del tunnel&lt;br&gt;
👎   Las URL no son persistentes en la versión &lt;em&gt;free&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Localtunnel
&lt;/h3&gt;

&lt;p&gt;🔥   Tiene URL persistentes, lo que nos permite poder compartir siempre la misma URL&lt;br&gt;
👎   Es necesario monitorear la consola cada tanto para chequear que sigue activo porque no es del todo estable&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusiones
&lt;/h1&gt;

&lt;p&gt;Mis conclusiones en base a las ventajas y desventajas de cada app es que si necesitamos tunnels robustos que puedan permanecer corriendo por horas, incluso días, la mejor alternativa es &lt;em&gt;ngrok&lt;/em&gt;. Pero &lt;em&gt;Localtunnel&lt;/em&gt; gana cuando se trata de hacer una demo con un cliente, ya que gracias a los subdominios podemos compartirle una URL del tipo &lt;code&gt;proyecto.localtunnel.me&lt;/code&gt;, y queda más profesional por decirlo de alguna manera.&lt;/p&gt;

&lt;p&gt;Pero como siempre digo, proba las dos apps para que puedas sacar tus propias conclusiones, y usa lo que se adapte mejor a vos y a tu trabajo.&lt;/p&gt;



&lt;p&gt;Si conoces o usas otra app de este estilo que te parezca una buena alternativa, dejala en los comentarios o escribime por mis redes sociales. Me interesa conocer que herramientas usan día a día ❤️.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ngrok</category>
      <category>localtunnel</category>
    </item>
  </channel>
</rss>
