<?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: Rusu Emanuel</title>
    <description>The latest articles on DEV Community by Rusu Emanuel (@emanuel191).</description>
    <link>https://dev.to/emanuel191</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%2F865313%2F2b47b59d-f5d4-4664-80a4-09b424dbd2d1.jpeg</url>
      <title>DEV Community: Rusu Emanuel</title>
      <link>https://dev.to/emanuel191</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emanuel191"/>
    <language>en</language>
    <item>
      <title>Binary search trees🌳</title>
      <dc:creator>Rusu Emanuel</dc:creator>
      <pubDate>Sun, 24 Jul 2022 13:35:00 +0000</pubDate>
      <link>https://dev.to/emanuel191/binary-search-trees-51e3</link>
      <guid>https://dev.to/emanuel191/binary-search-trees-51e3</guid>
      <description>&lt;h2&gt;
  
  
  👋Heeelloo everybody! 🔥🚀
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
-&amp;gt; This post is about &lt;strong&gt;binary search trees&lt;/strong&gt;🌳. They are represented by &lt;strong&gt;nodes linked together&lt;/strong&gt; to simulate a hierarchy, and these nodes are positioned &lt;strong&gt;following a rule&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;-&amp;gt; I will walk you through the implementation of a binary search tree. Working with trees &lt;strong&gt;requires knowledge about pointers&lt;/strong&gt;, &lt;strong&gt;the memory layout of a C program&lt;/strong&gt;, &lt;strong&gt;memory allocation&lt;/strong&gt;, &lt;strong&gt;and a good understanding of recursion&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;-&amp;gt; We focus on binary search tree🌳 because this is a &lt;strong&gt;time-efficient&lt;/strong&gt; data structure. We call it &lt;strong&gt;binary&lt;/strong&gt; because every node &lt;strong&gt;can have at most two children&lt;/strong&gt;. It is a &lt;strong&gt;search tree&lt;/strong&gt; because it &lt;strong&gt;respects a particular condition&lt;/strong&gt; which says that &lt;strong&gt;every node with a value smaller than the root node is going to be placed on the left of the root node, and every node with a value bigger than the root node is going to be placed in the right of the root node&lt;/strong&gt;. This rule is applied recursively for every right subtree and left subtree.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;Searching&lt;/strong&gt;, &lt;strong&gt;accessing&lt;/strong&gt;, &lt;strong&gt;inserting&lt;/strong&gt;, and &lt;strong&gt;deleting&lt;/strong&gt; in a binary search tree🌳 are &lt;strong&gt;usually&lt;/strong&gt; done in &lt;strong&gt;O(log n)&lt;/strong&gt;. But there is a chance that a binary search tree can have a structure &lt;strong&gt;similar to a linked list&lt;/strong&gt;, and the operations mentioned above will be done in &lt;strong&gt;O(n)&lt;/strong&gt;. This situation is a drawback for the tree data structure and it happens when every new node has either a &lt;strong&gt;smaller&lt;/strong&gt; value than the last node, or a &lt;strong&gt;bigger&lt;/strong&gt; value  than the last node. Try to draw a binary search tree with these values: &lt;code&gt;10, 9, 8, 7, 6, 5, 4&lt;/code&gt; and with these values: &lt;code&gt;4, 5, 6, 7, 8, 9, 10&lt;/code&gt; and see what happens.&lt;/p&gt;

&lt;p&gt;-&amp;gt; Happily, another tree🌳 data structure, &lt;strong&gt;AVL&lt;/strong&gt;, is an improvement of classical trees. &lt;strong&gt;AVL&lt;/strong&gt; is a &lt;strong&gt;self-balancing&lt;/strong&gt; tree, and by balancing, we avoid the situation when the tree can become a linked list. But this is another discussion.&lt;/p&gt;

&lt;p&gt;-&amp;gt; We can implement trees with more than two children, &lt;strong&gt;but time complexity will not change&lt;/strong&gt;. Only the logarithm base will change, but &lt;strong&gt;it doesn't matter in complexities&lt;/strong&gt;, so again, the time complexity will be &lt;strong&gt;O(log n&lt;/strong&gt;) in the best case and &lt;strong&gt;O(n)&lt;/strong&gt; in the worst case.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  1. First step: creating a &lt;code&gt;Node&lt;/code&gt; data type
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;To work with a tree data structure&lt;/strong&gt;, we need to &lt;strong&gt;create a new data type&lt;/strong&gt;, a &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; data type. Trees🌳 use nodes. Here we define our &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; data type as having three attributes: an unsigned long long variable - &lt;strong&gt;representing the information to be stored&lt;/strong&gt;(also it can be any primitive or abstract data type. I used a primitive data type for simplicity), &lt;strong&gt;a reference to the left child&lt;/strong&gt;, and &lt;strong&gt;a reference to the right child&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
struct Node
{
    unsigned long long data;
    Node* left;
    Node* right;
};

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

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  2. Second step: generating &lt;code&gt;Node&lt;/code&gt; variables
&lt;/h2&gt;

&lt;p&gt;After we define how a &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; data type looks, we &lt;strong&gt;need to be able to create variables of that type&lt;/strong&gt;. We are working with heap memory, so we must &lt;strong&gt;dynamically allocate memory&lt;/strong&gt; for our new nodes—the &lt;strong&gt;new&lt;/strong&gt; operator requests memory &lt;strong&gt;of the size of our data type&lt;/strong&gt;. Then we initialize data attribute and references. The &lt;strong&gt;nullptr&lt;/strong&gt; keyword was introduced in C++, representing 0 as an adress and only as an adress; &lt;strong&gt;nullptr&lt;/strong&gt; is a keyword with pointer type. On the other hand, &lt;strong&gt;NULL&lt;/strong&gt; is by default 0 and is not always a pointer. I will post about the difference between &lt;code&gt;nullptr&lt;/code&gt; and &lt;code&gt;NULL&lt;/code&gt; in the future. Because we are working with pointers and we are in C++, is better to use &lt;strong&gt;nullptr&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Node* CreateNode(unsigned long long Data)
{
    Node* newNode = new Node;

    newNode-&amp;gt;data = Data;
    newNode-&amp;gt;left = nullptr;
    newNode-&amp;gt;right = nullptr;

    return newNode;
}

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

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  3. Third step: inserting nodes
&lt;/h2&gt;

&lt;p&gt;After we defined how our &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; data type looks and we made sure that we can create variables of that type, we need to be able to &lt;strong&gt;put these variables in such a way that respects the definition of a binary search tree&lt;/strong&gt;. We will create a function for inserting in a binary search tree. I prefer the recursive method as it is shorter. We need &lt;strong&gt;two arguments&lt;/strong&gt; for that function: &lt;strong&gt;the root node&lt;/strong&gt; and &lt;strong&gt;the information/object to be stored&lt;/strong&gt;. If the root is null, then we know that it is time to create a new &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt;  variable and insert it. If the &lt;strong&gt;value&lt;/strong&gt; of information/object is &lt;strong&gt;greater&lt;/strong&gt; than the &lt;strong&gt;value&lt;/strong&gt; of the &lt;strong&gt;actual root node&lt;/strong&gt;, then we go to the &lt;strong&gt;right&lt;/strong&gt;; if not, then we go to the &lt;strong&gt;left&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
void InsertNode(Node*&amp;amp; Root, unsigned long long Data)
{
    if (Root == nullptr) Root = CreateNode(Data);
    else if (Data &amp;gt; Root-&amp;gt;data) InsertNode(Root-&amp;gt;right, Data);
    else InsertNode(Root-&amp;gt;left, Data);
}

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

&lt;/div&gt;



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

&lt;h2&gt;
  
  
  4. Fourth step: printing a binary search tree
&lt;/h2&gt;

&lt;p&gt;We created a &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; data type, and we made sure that we could generate &lt;strong&gt;&lt;code&gt;Node&lt;/code&gt;&lt;/strong&gt; variables and we made sure that we could insert them correctly. Now we need to think about how we can &lt;strong&gt;see&lt;/strong&gt; our data structure. For this, we need to use &lt;strong&gt;algorithms for depth traversals or breadth traversal&lt;/strong&gt;. There are four possible algorithms: &lt;strong&gt;inorder&lt;/strong&gt;, &lt;strong&gt;preorder&lt;/strong&gt;, &lt;strong&gt;postorder&lt;/strong&gt; and &lt;strong&gt;level order traversal&lt;/strong&gt;. I use preorder for this example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
void Print(Node* Root)
{
    if (Root)
    {
        cout &amp;lt;&amp;lt; Root-&amp;gt;data &amp;lt;&amp;lt; ' ';
        Print(Root-&amp;gt;left);
        Print(Root-&amp;gt;right);
    }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
We are done. We have all pieces for working with a binary search tree. &lt;br&gt;
Here is the complete code🔥:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#include &amp;lt;iostream&amp;gt;
using namespace std;


struct Node
{
    unsigned long long data;
    Node* left;
    Node* right;
};


Node* CreateNode(unsigned long long Data)
{
    Node* newNode = new Node;

    newNode-&amp;gt;data = Data;
    newNode-&amp;gt;left = nullptr;
    newNode-&amp;gt;right = nullptr;

    return newNode;
}


void InsertNode(Node*&amp;amp; Root, unsigned long long Data)
{
    if (Root == nullptr) Root = CreateNode(Data);
    else if (Data &amp;gt; Root-&amp;gt;data) InsertNode(Root-&amp;gt;right, Data);
    else InsertNode(Root-&amp;gt;left, Data);
}


void Print(Node* Root)
{
    if (Root)
    {
        cout &amp;lt;&amp;lt; Root-&amp;gt;data &amp;lt;&amp;lt; ' ';
        Print(Root-&amp;gt;left);
        Print(Root-&amp;gt;right);
    }
}


int main()
{
    Node* root = nullptr;
    unsigned long long i = 0, nodesNumber;
    cout &amp;lt;&amp;lt; "Number of nodes to be added: "; cin &amp;gt;&amp;gt; nodesNumber; cout &amp;lt;&amp;lt; '\n';

    while (i &amp;lt; nodesNumber)
    {
        unsigned long long number; cout &amp;lt;&amp;lt; "Value of node: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';
        InsertNode(root, number);
        ++i;
    }

    cout &amp;lt;&amp;lt; "Binary search tree printed: "; Print(root);
    cout &amp;lt;&amp;lt; '\n';

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;This is a basic structure. I wanted to give you the &lt;strong&gt;main idea&lt;/strong&gt;. We can also create a &lt;strong&gt;Tree&lt;/strong&gt;🌳 data type and think about &lt;strong&gt;Tree&lt;/strong&gt;🌳 as an object with attributes rather than a simple variable called root. But from here, you can improve/change this implementation as you like. Feel free to explore.🗺️ and be curious.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
❗Observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I focused on the idea rather than on a real-world scenario where I must consider validations and other stuff. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have used &lt;strong&gt;C++&lt;/strong&gt; programming language.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Emanuel Rusu👨‍🎓&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can visit my &lt;a href="https://github.com/Emanuel181"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or you can find me on &lt;a href="https://ro.linkedin.com/in/emanuel1"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next topic: &lt;strong&gt;Intern reprezentation of primitive data types&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See you next time! 👋&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>cpp</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Sieve of Eratosthenes</title>
      <dc:creator>Rusu Emanuel</dc:creator>
      <pubDate>Fri, 10 Jun 2022 18:13:00 +0000</pubDate>
      <link>https://dev.to/emanuel191/sieve-of-eratosthenes-50hp</link>
      <guid>https://dev.to/emanuel191/sieve-of-eratosthenes-50hp</guid>
      <description>&lt;p&gt;Heeelloooo everyone!🔥😎&lt;/p&gt;

&lt;p&gt;As I told you in the previous post, I am going to write about the Sieve of Eratosthenes. Commonly, this algorithm comes together with the primality of a number problem. It is used in contests, websites with algorithmic problems, competitive programming, Olympiads, and maybe at university admission competitions. Sieve of Eratosthenes finds all prime numbers between an interval. It is a time-efficient algorithm because instead of checking all numbers between a given interval, we can mark some numbers as &lt;code&gt;not primes&lt;/code&gt; without even checking them. This way, we avoid unnecessary analyses.&lt;br&gt;
On the other hand, it is not a space-efficient algorithm. We have to keep track of numbers marked as &lt;code&gt;not primes&lt;/code&gt; and numbers marked as &lt;code&gt;primes&lt;/code&gt; if we don't store this information &lt;code&gt;(number, marked/unmarked)&lt;/code&gt; we can't implement the Sieve of Eratosthenes idea. Enough introduction. Let's dig in.&lt;/p&gt;

&lt;p&gt;Problem to solve:  Print all prime numbers between &lt;code&gt;2&lt;/code&gt; and &lt;code&gt;n&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Idea🤔
&lt;/h2&gt;

&lt;p&gt;We have to analyze numbers from &lt;code&gt;2&lt;/code&gt; to &lt;code&gt;n&lt;/code&gt;. Firstly, we write them down:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ... n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, we will do something which is called &lt;code&gt;marking&lt;/code&gt;. To illustrate this, I will use &lt;code&gt;strikethrough digits&lt;/code&gt;. A &lt;code&gt;strikethrough digit&lt;/code&gt; means a &lt;code&gt;marked number&lt;/code&gt;, so &lt;code&gt;not a prime number&lt;/code&gt;; a &lt;code&gt;simple number&lt;/code&gt; means an &lt;code&gt;unmarked number&lt;/code&gt;, so a &lt;code&gt;prime number&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we begin from &lt;code&gt;2&lt;/code&gt; till &lt;code&gt;n&lt;/code&gt;, and for every number, we mark all its multiples till &lt;code&gt;n&lt;/code&gt; inclusive. &lt;/p&gt;

&lt;p&gt;We are at &lt;code&gt;2&lt;/code&gt;, so we mark &lt;code&gt;4&lt;/code&gt;, &lt;code&gt;6&lt;/code&gt;, &lt;code&gt;8&lt;/code&gt;, &lt;code&gt;10&lt;/code&gt;, &lt;code&gt;12&lt;/code&gt;, &lt;code&gt;14&lt;/code&gt;, &lt;code&gt;16&lt;/code&gt;, &lt;code&gt;18&lt;/code&gt;, &lt;code&gt;20&lt;/code&gt;, &lt;code&gt;22&lt;/code&gt;, &lt;code&gt;24&lt;/code&gt;, &lt;code&gt;26&lt;/code&gt; and all numbers &lt;code&gt;2 * k&lt;/code&gt;, with &lt;code&gt;k &amp;gt; 1&lt;/code&gt; and stop when &lt;code&gt;2 * k &amp;gt; n&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;2 3 ̷4 5 ̷6 7 ̷8 9 ̷1̷0 11 ̷1̷2 13 ̷1̷4 15 ̷1̷6 17 ̷1̷8 19 ̷2̷0 21 ̷2̷2 23 ̷2̷4 25 2̷6 ... n&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;br&gt;
We move at &lt;code&gt;3&lt;/code&gt; so we mark &lt;code&gt;6&lt;/code&gt;, &lt;code&gt;9&lt;/code&gt;, &lt;code&gt;12&lt;/code&gt;, &lt;code&gt;15&lt;/code&gt;, &lt;code&gt;18&lt;/code&gt;, &lt;code&gt;21&lt;/code&gt;, &lt;code&gt;24&lt;/code&gt; and all numbers &lt;code&gt;3 * k&lt;/code&gt;, with &lt;code&gt;k &amp;gt; 1&lt;/code&gt; and stop when &lt;code&gt;3 * k &amp;gt; n&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;2 ̷3 ̷4 5 ̷6 7 ̷8 ̷9̷ ̷1̷0 11 ̷1̷2 13 ̷1̷4 ̷1̷5 ̷1̷6 17 ̷1̷8 19 ̷2̷0 ̷2̷1 ̷2̷2 23 ̷2̷4 25 2̷6 ... n&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We continue this process by taking every number till &lt;code&gt;n&lt;/code&gt; and marking all its multiples till &lt;code&gt;n&lt;/code&gt; inclusive.&lt;/p&gt;

&lt;p&gt;By the end of this algorithm, the numbers that &lt;code&gt;remained unmarked&lt;/code&gt; are &lt;code&gt;only prime numbers&lt;/code&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  Let's take an example:
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;
Let's find all prime numbers until &lt;code&gt;22(n)&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;List all numbers till &lt;code&gt;n = 22&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start from &lt;code&gt;2&lt;/code&gt; and mark all its multiples smaller or equal than &lt;code&gt;22&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2 3 ̷4 5 ̷6 7 ̷8 9 ̷1̷0 11 ̷1̷2 13 ̷1̷4 15 ̷1̷6 17 ̷1̷8 19 ̷2̷0 21 ̷2̷2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Move to &lt;code&gt;3&lt;/code&gt; and mark all its multiples smaller or equal than &lt;code&gt;22.&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;2 3 ̷4 5 ̷6 7 ̷8 ̷9̷ ̷1̷0 11 ̷1̷2 13 ̷1̷4 ̷1̷5 ̷1̷6 17 ̷1̷8 19 ̷2̷0 ̷2̷1 ̷2̷2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If we want to move to &lt;code&gt;4&lt;/code&gt;, we can see that it's multiples smaller &lt;br&gt;
than &lt;code&gt;22&lt;/code&gt; are already marked, similarly with &lt;code&gt;5&lt;/code&gt;, &lt;code&gt;6&lt;/code&gt;, &lt;code&gt;7&lt;/code&gt;, &lt;code&gt;...&lt;/code&gt;, &lt;br&gt;
&lt;code&gt;22&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;2 3 ̷4 5 ̷6 7 ̷8 ̷9̷ ̷1̷0 11 ̷1̷2 13 ̷1̷4 ̷1̷5 ̷1̷6 17 ̷1̷8 19 ̷2̷0 ̷2̷1 ̷2̷2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write down unmarked numbers:&lt;/strong&gt; &lt;code&gt;2 3 5 7 11 13 17 19&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Done!&lt;br&gt;
Congratulations!🥳 You found all primes numbers using the &lt;strong&gt;Sieve of Eratosthenes&lt;/strong&gt; algorithm.&lt;/p&gt;


&lt;h2&gt;
  
  
  Maybe you want to see the code but let me explain it before.👨‍🏫
&lt;/h2&gt;

&lt;p&gt;First, I will use a straightforward algorithm and then optimize it as we go deeper and deeper.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As I said in the beginning, we need to write down the numbers from &lt;code&gt;2&lt;/code&gt; to &lt;code&gt;n.&lt;/code&gt; We do that by using a boolean array like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#define MAX 1000000001
bool sieve[MAX];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why do we use such a big number? Because we don't know how big the interval is, we give as much freedom as possible; note that this number may not work for your computer, and you will need to make it smaller.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;br&gt;
Then I said that we needed to mark numbers somehow. In Sieve of Eratosthenes, we use a &lt;code&gt;global array&lt;/code&gt;, and &lt;code&gt;global variables&lt;/code&gt; are automatically initialized with &lt;code&gt;0&lt;/code&gt;. We use that to our advantage instead of a &lt;code&gt;for&lt;/code&gt; to set all memory spaces manually with &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We are doing marking like this:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Why? I know that using &lt;code&gt;1&lt;/code&gt; for primes and &lt;code&gt;0&lt;/code&gt; for not primes would have been more intuitive but declaring an array in global scope, it got initialized with &lt;code&gt;0&lt;/code&gt;, so it is just a waste to overwrite all memory spaces with &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then we mark in advance &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;1&lt;/code&gt; because we know these numbers are not prime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sieve[0] = sieve[1] = 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we start to iterate from &lt;code&gt;2&lt;/code&gt; till &lt;code&gt;n&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;for (unsigned long long i = 2; i &amp;lt;= n; ++i)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For every &lt;code&gt;i&lt;/code&gt;, we mark all its multiples smaller or equal than &lt;code&gt;n&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;for (unsigned long long j = 2; j &amp;lt;= n / i; ++j) sieve[i * j] = 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We iterate till &lt;code&gt;n / i&lt;/code&gt; because this division gave us the biggest number, which can be multiplied by &lt;code&gt;j&lt;/code&gt;, which is smaller or equals to &lt;code&gt;n&lt;/code&gt;, so iterating till this number, we can guarantee that we marked all multiples of &lt;code&gt;i&lt;/code&gt; smaller than &lt;code&gt;n&lt;/code&gt;. &lt;code&gt;sieve[i * j]&lt;/code&gt; is the &lt;code&gt;multiple&lt;/code&gt; of &lt;code&gt;i&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The last thing we have to do is to iterate the interval and print all &lt;code&gt;unmarked values&lt;/code&gt;. We do that by asking if &lt;code&gt;sieve[i] == 0&lt;/code&gt; in a &lt;code&gt;for&lt;/code&gt; loop like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    for (unsigned long long i = 2; i &amp;lt;= n; ++i)
    {
        if (sieve[i] == 0) cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; ' ';
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first version of our algorithm is done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#include &amp;lt;iostream&amp;gt;
using namespace std;


#define MAX 1000000001
bool sieve[MAX];


void PrintSieveofEratosthenes(unsigned long long n)
{
    for (unsigned long long i = 2; i &amp;lt;= n; ++i)
    {
        if (sieve[i] == 0) cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; ' ';
    }
}


void SieveofEratosthenes(unsigned long long n)
{
    sieve[0] = sieve[1] = 1;

    for (unsigned long long i = 2; i &amp;lt;= n; ++i)
    {
        for (unsigned long long j = 2; j &amp;lt;= n / i; ++j) sieve[i * j] = 1;
    }

}


int main()
{
    unsigned long long n; cin &amp;gt;&amp;gt; n;
    SieveofEratosthenes(n);
    PrintSieveofEratosthenes(n);

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;I like to refactor this a bit. I consider that the function call for printing is a bit unnecessary because we can print numbers inside the first loop. We know that if &lt;code&gt;sieve[i] == 0&lt;/code&gt; we found a prime number. Here is another version that I like more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#include &amp;lt;iostream&amp;gt;
using namespace std;


#define MAX 1000000001
bool sieve[MAX];


void SieveofEratosthenes(unsigned long long n)
{
    sieve[0] = sieve[1] = 1;

    for (unsigned long long i = 2; i &amp;lt;= n; ++i)
    {
        for (unsigned long long j = 2; j &amp;lt;= n / i; ++j) sieve[i * j] = 1;

        if (sieve[i] == 0) cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; ' ';
    }
}


int main()
{
    unsigned long long n; cin &amp;gt;&amp;gt; n;
    SieveofEratosthenes(n);

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;Now we get into optimizations. Sieve of Eratosthenes is more than two loops. If you read till now, congratulations!🥳&lt;/p&gt;




&lt;p&gt;We know that every &lt;code&gt;even number&lt;/code&gt; greater than &lt;code&gt;2&lt;/code&gt; is not prime. We can mark in advance these numbers by beginning from &lt;code&gt;4&lt;/code&gt; and iterating from &lt;code&gt;2&lt;/code&gt; to &lt;code&gt;2&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;for(unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because we &lt;code&gt;marked even numbers before&lt;/code&gt;, we don't need to analyse them again so we can start from &lt;code&gt;i = 3&lt;/code&gt; and increment it by &lt;code&gt;2&lt;/code&gt;. This way we take into consideration only &lt;code&gt;odd&lt;/code&gt; numbers.&lt;/p&gt;

&lt;p&gt;Then we can iterate only till &lt;code&gt;√n&lt;/code&gt; using &lt;code&gt;i * i &amp;lt;= n&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;
    sieve[0] = sieve[1] = 1;
    for (unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;

    for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
    {
        for (unsigned long long j = 2; j &amp;lt;= n/i; ++j) sieve[i*j] = 1;
    }

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

&lt;/div&gt;



&lt;p&gt;We can optimize how we iterate through multiples of every number. We can begin from &lt;code&gt;i * i&lt;/code&gt; because all numbers till &lt;code&gt;i * i&lt;/code&gt; have been already marked; and increment &lt;code&gt;j&lt;/code&gt; with &lt;code&gt;i&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;
    sieve[0] = sieve[1] = 1;
    for (unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;

    for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
    {
        for (unsigned long long j = i * i; j &amp;lt;= n; j+=i) sieve[j] = 1;
    }

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

&lt;/div&gt;



&lt;p&gt;We can iterate with &lt;code&gt;j += 2 * i&lt;/code&gt; to ignore odd numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    sieve[0] = sieve[1] = 1;
    for (unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;

    for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
    {
        for (unsigned long long j = i * i; j &amp;lt;= n; j += 2 * i) sieve[j] = 1;
    }

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

&lt;/div&gt;



&lt;p&gt;Here is the final code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

#define MAX 1000000001
bool sieve[MAX];


void PrintSieveofEratosthenes(unsigned long long n)
{
    for (int i = 2; i &amp;lt;= n; ++i)
    {
        if (sieve[i] == 0) cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; ' ';
    }
}


void SieveofEratosthenes(unsigned long long n)
{
    sieve[0] = sieve[1] = 1;

    for (unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;

    for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
    {
        for (unsigned long long j = i * i; j &amp;lt;= n; j += 2* i) sieve[j] = 1;
    }
}


int main()
{
    unsigned long long n; cin &amp;gt;&amp;gt; n;
    SieveofEratosthenes(n);
    PrintSieveofEratosthenes(n);

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;This block of code gives time complexity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
{
    for (unsigned long long j = i * i; j &amp;lt;= n; j += 2 * i) sieve[j] = 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first loop performs &lt;code&gt;√n&lt;/code&gt; operations because we iterate till &lt;code&gt;i * i &amp;lt;= n&lt;/code&gt;. The idea of the second loop is to mark all multiples of &lt;code&gt;i&lt;/code&gt;. So, it will perform &lt;code&gt;n / i&lt;/code&gt; steps. It is a known formula that if you want to find out how many divisors of a number till &lt;code&gt;n&lt;/code&gt; are, you divide &lt;code&gt;n / your_number&lt;/code&gt;. So for every &lt;code&gt;i&lt;/code&gt; we will perform &lt;code&gt;n / i&lt;/code&gt; steps. (technically, we perform fewer steps because I increased &lt;code&gt;j&lt;/code&gt; with &lt;code&gt;2 * i&lt;/code&gt; to avoid iterating through even multiples of &lt;code&gt;i&lt;/code&gt;, but ignore that. What I did is not enough to decrease the order of complexity anyway).&lt;/p&gt;

&lt;p&gt;For every &lt;code&gt;i&lt;/code&gt; till &lt;code&gt;√n&lt;/code&gt; we perform &lt;code&gt;n / i&lt;/code&gt; operations, where &lt;code&gt;i is prime&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The ecuation is: &lt;br&gt;
&lt;code&gt;√n * (n/3 + n/4 + n/5 + n/6 + n/7 + ...)&lt;/code&gt;&lt;br&gt;
= &lt;code&gt;√n * n * (1/3 + 1/4 + 1/5 + 1/6 + 1/7 + ...)&lt;/code&gt;&lt;br&gt;
The third factor, according to &lt;a href="https://en.wikipedia.org/wiki/Divergence_of_the_sum_of_the_reciprocals_of_the_primes"&gt;Euler&lt;/a&gt; grows the same as &lt;code&gt;ln(ln(n))&lt;/code&gt;&lt;br&gt;
So the time complexity is: &lt;code&gt;O(√n * n * ln(ln(n)))&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Observations❗:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Note that I used &lt;code&gt;unsigned long long&lt;/code&gt; for variables, and operations like &lt;code&gt;raising to power&lt;/code&gt; can easily exceed &lt;code&gt;unsigned long long&lt;/code&gt;, so be careful with input numbers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can play around with &lt;code&gt;#define MAX 1000000001&lt;/code&gt; and &lt;code&gt;#define MAX_PRIMES 100000001&lt;/code&gt;. Try to find which is the maximum limit accepted by your computer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To make this algorithm space-efficient, you can use a &lt;code&gt;vector container&lt;/code&gt; from the &lt;code&gt;STL&lt;/code&gt; library like this &lt;code&gt;vector &amp;lt;bool&amp;gt; vector_name&lt;/code&gt;. Before that, include &lt;code&gt;vector library&lt;/code&gt; like &lt;code&gt;#include &amp;lt;vector&amp;gt;&lt;/code&gt;. That container is not a regular one. It is a memory-optimization of &lt;code&gt;template classes&lt;/code&gt; like &lt;code&gt;vector &amp;lt;T&amp;gt;&lt;/code&gt;, which uses only &lt;code&gt;n/8&lt;/code&gt; bytes of memory. Many modern processors work faster with bytes because they can be accessed directly. &lt;code&gt;vector &amp;lt;T&amp;gt;&lt;/code&gt; template class works directly with bits. But these things require knowledge about &lt;code&gt;template classes&lt;/code&gt;, which are very powerful in &lt;code&gt;C++&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This algorithm can be optimized even more using &lt;code&gt;bits operations&lt;/code&gt; to achieve linear time. But &lt;code&gt;ln(ln(n))&lt;/code&gt; can be approximated to &lt;code&gt;O(1)&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;And here is the bonus algorithm for testing primality I spoke about in the post before(probably the fastest for checking primality)🏎️:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


#define MAX 1000000001
#define MAX_PRIMES 100000001
bool sieve[MAX];
unsigned long long primeNumbers[MAX_PRIMES];


void SieveofEratosthenes(unsigned long long n)
{
    sieve[0] = sieve[1] = 1;

    for (unsigned long long i = 4; i &amp;lt;= n; i += 2) sieve[i] = 1;

    for (unsigned long long i = 3; i * i &amp;lt;= n; i += 2)
    {
        for (unsigned long long j = i * i; j &amp;lt;= n; j += 2 * i) sieve[j] = 1;
    }


    unsigned long long k = 0;
    for (int i = 2; i &amp;lt;= n; ++i)
    {
        if (sieve[i] == 0) primeNumbers[k++] = i;
    }
}


bool IsPrime(unsigned long long Number)
{
    unsigned long long k = 0;

    while (Number &amp;gt; 1)
    {
        unsigned long long power = 0;

        if (Number % primeNumbers[k] == 0)
        {
            Number /= primeNumbers[k];
            ++power;
        }

        if (power) return false;

        ++k;

        if (primeNumbers[k] * primeNumbers[k] &amp;gt; Number) return true;
    }
}


int main()
{
    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';
    SieveofEratosthenes(number);

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Emanuel Rusu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can visit my &lt;a href="https://github.com/Emanuel181"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Or you can find me on [Linkedin] &lt;/p&gt;

&lt;a href="https://ro.linkedin.com/in/emanuel1?trk=profile-badge"&gt;Rusu Emanuel&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next topic: &lt;strong&gt;Binary search trees🌳&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See you next time ! 👋&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>programming</category>
      <category>computerscience</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Algorithms for primes number - introduction</title>
      <dc:creator>Rusu Emanuel</dc:creator>
      <pubDate>Wed, 25 May 2022 22:00:52 +0000</pubDate>
      <link>https://dev.to/emanuel191/primality-test-introduction-439c</link>
      <guid>https://dev.to/emanuel191/primality-test-introduction-439c</guid>
      <description>&lt;p&gt;Heellooo everybody🔥, Welcome back! 😎&lt;/p&gt;

&lt;p&gt;Determining if a number is prime is a common problem in high school, the Olympics, and some contests or websites with algorithmic problems. Mathematicians have a high focus on prime numbers, they are really useful in cryptography area and in math in general. Being a prime number is a property studied in number theory, a really nice chapter for computer science which I will talk about in future posts.&lt;/p&gt;

&lt;p&gt;There are plenty of solutions. All solutions return the correct answer, but &lt;strong&gt;the difference is their time and space complexity&lt;/strong&gt;, a &lt;strong&gt;core concept&lt;/strong&gt; in programming. We always search for &lt;strong&gt;the most efficient approach&lt;/strong&gt;. I don’t want to cover complexity analysis in this post, but I will briefly present some complexities.&lt;/p&gt;




&lt;p&gt;The first algorithm is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    unsigned long long cnt{ 0 };

    for (unsigned long long i = 1; i &amp;lt;= Number; ++i)
    {
        if (Number % i == 0) ++cnt;
    }

    if (cnt &amp;gt;= 3) return 0;

    return 1;
}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;This is the most basic solution. It follows exactly the mathematically definition of prime numbers - &lt;strong&gt;A prime number has exactly two divisors&lt;/strong&gt;. We iterate from 1 until we reach our number, trying to find how many divisors exist. If there are more than 2, we return &lt;code&gt;0(false)&lt;/code&gt; or &lt;code&gt;1(true)&lt;/code&gt; if the number of divisors is smaller than 2. It is a good approach if you are new to algorithms.&lt;/p&gt;

&lt;p&gt;We iterate the whole interval between 1 and the number passed as argument. This gave us a linear complexity, &lt;code&gt;O(n)&lt;/code&gt;. Although this sounds good, we make some useless analyses for some numbers.&lt;/p&gt;

&lt;p&gt;The first optimization we can do is &lt;strong&gt;to stop right when we find that there are more than two divisors&lt;/strong&gt;, so our solution will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    unsigned long long cnt{ 0 };

    for (unsigned long long i = 1; i &amp;lt;= Number; ++i)
    {
        if (Number % i == 0) ++cnt;

        if (cnt &amp;gt;= 3) return 0;
    }

    return 1;
}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}



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

&lt;/div&gt;



&lt;p&gt;Our complexity &lt;strong&gt;still doesn't decrease&lt;/strong&gt;, but it is worth optimization, which makes our code better.&lt;/p&gt;

&lt;p&gt;We can continue our improvements by not beginning to iterate from 1 because we know that 1 is the divisor for any number. Also, we can only iterate &lt;strong&gt;till the half of the number&lt;/strong&gt; because we count for its divisors, and divisors of a number can be &lt;strong&gt;found till the half of the number&lt;/strong&gt;. In this case, we can get rid of the divisor's counter because we start from 2 and stop at half, so it &lt;strong&gt;is enough to find only one&lt;/strong&gt; divisor to say that the number &lt;strong&gt;is not prime&lt;/strong&gt;. So our code will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    for (unsigned long long i = 2; i &amp;lt;= Number / 2; ++i)
    {
        if (Number % i == 0) return 0;
    }

    return 1;
}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}

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

&lt;/div&gt;



&lt;p&gt;Spoiler alert, our &lt;strong&gt;time complexity didn’t change&lt;/strong&gt;. It is still a linear algorithm.&lt;br&gt;
Why?&lt;br&gt;
Because we make O(n/2) steps, and if we rewrite this like O(1/2 * n), 1/2 is constant, and we &lt;strong&gt;don’t care about constants&lt;/strong&gt;, so we &lt;strong&gt;remove&lt;/strong&gt; them, and we have O(n).&lt;/p&gt;

&lt;p&gt;Another optimization is to iterate &lt;strong&gt;till the square root of the number&lt;/strong&gt;. We know that divisors of a number are in pairs, so if we don’t find divisors between &lt;code&gt;[2, square root of the number]&lt;/code&gt;, we will not find any divisors from the &lt;code&gt;[square root of the number, number]&lt;/code&gt;. The code will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    for (unsigned long long i = 2; i * i &amp;lt;= Number; ++i)
    {
        if (Number % i == 0) return 0;
    }

    return 1;
}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the time complexity has changed. It became &lt;code&gt;O(sqrt(n))&lt;/code&gt; because we iterate over &lt;code&gt;sqrt(n)&lt;/code&gt; numbers. Even if we exclude 1, which will be O(sqrt(n) - 1), 1 is constant, so we don’t care. Thus we remove it.&lt;/p&gt;

&lt;p&gt;Note that we used &lt;code&gt;i * i &amp;lt;= n&lt;/code&gt; instead of using &lt;code&gt;sqrt(n)&lt;/code&gt;. This is because &lt;code&gt;sqrt(n)&lt;/code&gt; is a function which require time to complete and we prefer to avoid this time taken by calling &lt;code&gt;sqrt(n)&lt;/code&gt;. Even worse will be to write the for loop like this &lt;code&gt;for (unsigned long long i = 1; i &amp;lt;= sqrt(Number); ++i)&lt;/code&gt;. Writting code like this will repeatedly calling &lt;code&gt;sqrt()&lt;/code&gt; function at every iteration wasting time and performance. Of course you can call &lt;code&gt;sqrt()&lt;/code&gt; one time, save it into a variable and write something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unsigned long long square = sqrt(Number);
for (unsigned long long i = 1; i &amp;lt;= square; ++i)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But still we have another function call which require time. A cleaner and better way is to use &lt;code&gt;i * i &amp;lt;= Number&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now I will show a final version.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Firstly we know that 0 and 1 are not primes.&lt;/li&gt;
&lt;li&gt;Secondly, we know that every even number except 2 is not prime&lt;/li&gt;
&lt;li&gt;Thirdly we see that it is enough if we can iterate till the square root of the number.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    if (Number == 0 || Number == 1) return 0;

    else if (Number % 2 == 0 &amp;amp;&amp;amp; Number != 2) return 0;

    else
    {
        for (unsigned long long i = 3; i * i &amp;lt;= Number; i += 2)
        {
            if (Number % i == 0) return 0;
        }
    }

    return 1;

}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We iterate over 2 numbers at once because we begin from 3, and if we iterate over 1 number at once, we will iterate over even numbers as well, but we &lt;strong&gt;already checked if our number is even at the previous step&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observation: This algorithm is commonly used for contests and Olympics.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another algorithm used for the primality test is the one for &lt;strong&gt;finding prime factors&lt;/strong&gt;. When we have a power greater than 0, this means that we found a divisor so we can &lt;strong&gt;stop&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


bool IsPrime(unsigned long long Number)
{
    unsigned long long divisor = 2;

    while (Number &amp;gt; 1)
    {
        unsigned long long power = 0;

        if (Number % divisor == 0)
        {
            Number /= divisor;
            ++power;
        }

        if (power) return false;

        ++divisor;

        if (divisor * divisor &amp;gt; Number) return true;
    }
}


int main()
{

    unsigned long long number; cout &amp;lt;&amp;lt; "Enter number: "; cin &amp;gt;&amp;gt; number; cout &amp;lt;&amp;lt; '\n';

    IsPrime(number) == 1 ? cout &amp;lt;&amp;lt; "Prime\n" : cout &amp;lt;&amp;lt; "Not prime\n";

    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time complexity here is &lt;code&gt;O(sqrt(n))&lt;/code&gt; in the wrost case. Because in a better case, the number is a power of divisor, for example, &lt;code&gt;Number = m^k&lt;/code&gt;, where &lt;code&gt;m = 1, 2, 3, 4,...&lt;/code&gt; and we perform &lt;code&gt;k&lt;/code&gt; divisions which is &lt;code&gt;O(log(n))&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;Finally, we have done.&lt;/p&gt;

&lt;p&gt;There can be many other improvements for the algorithms I showed and many others algorithms for the primality problem, but I think this is a solid introduction. Next time, I will show you another interesting algorithm called &lt;strong&gt;Sieve of Eratosthenes&lt;/strong&gt;, used to find all prime numbers in a given interval. As a bonus, I will show you how this algorithm &lt;strong&gt;can be combined&lt;/strong&gt; with the algorithm above to check the &lt;strong&gt;primality&lt;/strong&gt; of a number. It is going to be a &lt;strong&gt;complex&lt;/strong&gt; and fun algorithm.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Emanuel Rusu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can visit my &lt;a href="https://github.com/Emanuel181"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or you can find me on &lt;a href="https://www.linkedin.com/in/rusu-emanuel/"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next topic: &lt;strong&gt;Sieve of Eratosthenes&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See you next time ! 👋&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>cpp</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Simple and interesting way to convert from base 10 using recursion</title>
      <dc:creator>Rusu Emanuel</dc:creator>
      <pubDate>Wed, 25 May 2022 09:02:33 +0000</pubDate>
      <link>https://dev.to/emanuel191/simple-and-interesting-way-to-convert-from-base-10-using-recursion-583n</link>
      <guid>https://dev.to/emanuel191/simple-and-interesting-way-to-convert-from-base-10-using-recursion-583n</guid>
      <description>&lt;h2&gt;
  
  
  👋Heeelloo everybody! 🔥🚀
&lt;/h2&gt;

&lt;p&gt;As you read above, I will show you a really excellent and exciting way to convert a number from base 10 to smaller bases using the power of recursion.💪&lt;/p&gt;




&lt;p&gt;Before we jump into the code, I will list some observations to make sure that you understand what input the program can take.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Variables are declared: &lt;strong&gt;unsigned long long&lt;/strong&gt; for the input number, so you can enter any &lt;strong&gt;strict&lt;/strong&gt; positive number till &lt;strong&gt;2^64 - 1&lt;/strong&gt; and I used &lt;strong&gt;unsigned short&lt;/strong&gt; for the base you can choose to convert to. You can choose &lt;strong&gt;between base 2 till base 10&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I focused on the idea rather than on a real-world scenario where I must consider validations and other stuff. Of course, this code can be extended to support bases up from 10 and things such as quick conversions, but I will cover these things in the future.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I have used &lt;strong&gt;C++&lt;/strong&gt; programming language.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  So, what is the idea ?🤔🤔
&lt;/h2&gt;

&lt;p&gt;Commonly, we repetitively divide the number by the base until the number becomes zero, then we take every rest of the divisions in reverse order, and this is the new number. This process is tough, and it requires extra variables. &lt;/p&gt;

&lt;p&gt;Recursion does a good job here. We recursively call the same function with the new number divided until we hit the base case(the number becomes 0), then stack frames from recursion are resumed beginning from the end, so in reverse order. Now, in memory, every stack frame resulting from function calls contains a number, and the only thing we have to do is print &lt;strong&gt;[that number] % [the base]&lt;/strong&gt; as the last instruction for every stack frame.&lt;/p&gt;




&lt;h2&gt;
  
  
  Here is the code🔥
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;


void Convert(unsigned long long Number, const unsigned short BaseToConvert)
{
    if (Number)
    {
        Convert(Number / BaseToConvert, BaseToConvert);
        cout &amp;lt;&amp;lt; Number % BaseToConvert;
    }
}


int main()
{
    unsigned long long number; cout &amp;lt;&amp;lt; "Number to convert: "; cin &amp;gt;&amp;gt; number;

    unsigned short baseToConvert; cout &amp;lt;&amp;lt; "\nNew base: "; cin &amp;gt;&amp;gt; baseToConvert;

    cout &amp;lt;&amp;lt; "\nNumber converted: "; Convert(number, baseToConvert); cout &amp;lt;&amp;lt; '\n';
    return 0;
}

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

&lt;/div&gt;






&lt;p&gt;Thank you for reading !😃&lt;br&gt;
I hope you enjoyed reading and found this interesting.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Emanuel Rusu&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can visit my &lt;a href="https://github.com/Emanuel181"&gt;GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Or you can find me on &lt;a href="https://www.linkedin.com/in/rusu-emanuel/"&gt;Linkedin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next topic: &lt;strong&gt;Algorithms for primes number - introduction&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See you next time ! 👋&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
