<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блоги: заметки с тегом CS50</title>
<link>https://blogengine.me/blogs/tags/cs50/</link>
<description>Автоматически собираемая лента заметок, написанных в блогах на Эгее</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.0 (v4079e)</generator>

<itunes:subtitle>Автоматически собираемая лента заметок, написанных в блогах на Эгее</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>Scrabble in C</title>
<guid isPermaLink="false">126033</guid>
<link>https://dsokolovskiy.com/blog/all/scrabble-in-c/</link>
<pubDate>Sun, 25 Feb 2024 18:38:13 +0500</pubDate>
<author>Daniel Sokolovskiy</author>
<comments>https://dsokolovskiy.com/blog/all/scrabble-in-c/</comments>
<description>
&lt;p&gt;&lt;a href="https://dsokolovskiy.com/blog/"&gt;Daniel Sokolovskiy&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;In the second week of &lt;a href="/blog/tags/cs50/"&gt;CS50&lt;/a&gt;, I was introduced to the notion of arrays and then given the following problem to solve as a practice:&lt;/p&gt;
&lt;div class="question"&gt;&lt;p&gt;In the game of &lt;a href="https://www.scrabblepages.com/scrabble/rules/"&gt;Scrabble&lt;/a&gt;, players create words to score points, and the number of points is the sum of the point values of each letter in the word. For example, if we wanted to score the word “CODE”, we would note that the ‘C’ is worth 3 points, the ‘O’ is worth 1 point, the ‘D’ is worth 2 points, and the ‘E’ is worth 1 point. Summing these, we get that “CODE” is worth 7 points.&lt;/p&gt;
&lt;p&gt;Implement a program in C that determines the winner of a short Scrabble-like game. Your program should prompt for input twice: once for “Player 1” to input their word and once for “Player 2” to input their word. Then, depending on which player scores the most points, your program should either print “Player 1 wins!”, “Player 2 wins!”, or “Tie!” (in the event the two players score equal points).&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;First, I outlined the general steps needed to solve this problem:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Get text inputs from the user;&lt;/li&gt;
&lt;li&gt;Calculate the score of each input;&lt;/li&gt;
&lt;li&gt;Show the winner.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For the first step, I’ll creat two variables named &lt;i&gt;word1&lt;/i&gt; and &lt;i&gt;word2&lt;/i&gt; respectively, and assign each to the value of the respective user input using the &lt;i&gt;get_string&lt;/i&gt; function from the CS50 library:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(void)
{
    // Prompt the user for two words
    string word1 = get_string(&amp;quot;Player 1: &amp;quot;);
    string word2 = get_string(&amp;quot;Player 2: &amp;quot;);

    // Compute the score of each word

    // Print the winner
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That was easy. The trickiest part here, of course, is the second step, which is to assign each letter of the alphabet its unique score points value.&lt;/p&gt;
&lt;p&gt;Here are the values:&lt;/p&gt;
&lt;div class="e2-text-table"&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;A&lt;/td&gt;
&lt;td style="text-align: center"&gt;B&lt;/td&gt;
&lt;td style="text-align: center"&gt;C&lt;/td&gt;
&lt;td style="text-align: center"&gt;D&lt;/td&gt;
&lt;td style="text-align: center"&gt;E&lt;/td&gt;
&lt;td style="text-align: center"&gt;F&lt;/td&gt;
&lt;td style="text-align: center"&gt;G&lt;/td&gt;
&lt;td style="text-align: center"&gt;H&lt;/td&gt;
&lt;td style="text-align: center"&gt;I&lt;/td&gt;
&lt;td style="text-align: center"&gt;J&lt;/td&gt;
&lt;td style="text-align: center"&gt;K&lt;/td&gt;
&lt;td style="text-align: center"&gt;L&lt;/td&gt;
&lt;td style="text-align: center"&gt;M&lt;/td&gt;
&lt;td style="text-align: center"&gt;N&lt;/td&gt;
&lt;td style="text-align: center"&gt;O&lt;/td&gt;
&lt;td style="text-align: center"&gt;P&lt;/td&gt;
&lt;td style="text-align: center"&gt;Q&lt;/td&gt;
&lt;td style="text-align: center"&gt;R&lt;/td&gt;
&lt;td style="text-align: center"&gt;S&lt;/td&gt;
&lt;td style="text-align: center"&gt;T&lt;/td&gt;
&lt;td style="text-align: center"&gt;U&lt;/td&gt;
&lt;td style="text-align: center"&gt;V&lt;/td&gt;
&lt;td style="text-align: center"&gt;W&lt;/td&gt;
&lt;td style="text-align: center"&gt;X&lt;/td&gt;
&lt;td style="text-align: center"&gt;Y&lt;/td&gt;
&lt;td style="text-align: center"&gt;Z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;8&lt;/td&gt;
&lt;td style="text-align: center"&gt;5&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;10&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;8&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Now that I know about arrays, I can create an array called &lt;i&gt;points&lt;/i&gt; with a size of 26 and the type of integer, and assign values as follows:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(void)
{
    // Prompt the user for two words
    string word1 = get_string(&amp;quot;Player 1: &amp;quot;);
    string word2 = get_string(&amp;quot;Player 2: &amp;quot;);

    // Compute the score of each word
    int points[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};

    // Print the winner
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I don’t quite like the length of that like, but it seems there is not much to do about it since all values are set by the rules of the game.&lt;/p&gt;
&lt;p&gt;Now that I know a little bit about functions too, I’ll create a separate function for computing the score. This should make the code more efficient and better designed, especially since I need to use it twice for calculating the score for each word.&lt;/p&gt;
&lt;p&gt;I’ll call this function &lt;i&gt;calculate_score&lt;/i&gt;, with one input parameter of the type of string, and output of integer. I can also straight away create a variable called &lt;i&gt;score&lt;/i&gt; with the type of integer, as this is ultimately what I want to get from this function:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;int calculate_score(string word)
{
    int score = 0;

    return score;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, the big question is how to assign each letter a corresponding score value. Well, turns out that every string is basically just an array of characters. Let’s take the word CODE as an example. We can imagine it as an array as follows, keeping in mind the zero-based indexing of arrays, i.e. starting counting from 0:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;c word[i]
word[0] = C
word[1] = O
word[2] = D
word[3] = E&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Knowing this, I can create a loop to ‘scan’ through the word character by character. For this loop to work, I would to know the length of the word, and luckily such a function already exists in the &lt;i&gt;string.h&lt;/i&gt; library and is called &lt;i&gt;strlen&lt;/i&gt;:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;for (int i = 0; i &amp;lt; strlen(word); i++)
{
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What I don’t quite like about this loop though, is that every time it works, it makes the function repeat that many times. To optimise this, let me create another variable called &lt;i&gt;len&lt;/i&gt; with its value equal to the length of a word, and then use this variable as the condition of the loop:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;for (int i = 0, len = strlen(word); i &amp;lt; len; i++)
{
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, how to make the loop ‘know’ which score value corresponds to each letter? There is actually a trick that still blows my mind even after completing this task. Since every character has its numeric value in the &lt;a href="https://www.w3schools.com/charsets/ref_html_ascii.asp"&gt;ASCII code&lt;/a&gt;, we can use this information to ‘offset’ characters from one array to another and this way map them together.&lt;/p&gt;
&lt;p&gt;Let’s take the capital letter ‘C’ from the word CODE as I used the example. Its numeric value in ASCII is 67, and the trick is to subtract the value of the letter A, which equals 65. Why A? Because it’s the first letter of the alphabet, and if we subtract it from another letter, we’ll know its place in the array. So &lt;i&gt;67 – 65 = 2&lt;/i&gt;, and that is exactly the index number we need from the &lt;i&gt;points&lt;/i&gt; array.&lt;/p&gt;
&lt;p&gt;To make it more visual, here is a similar exercise for all letters of the word CODE:&lt;/p&gt;
&lt;div class="e2-text-table"&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Letter&lt;/td&gt;
&lt;td style="text-align: center"&gt;ASCII&lt;/td&gt;
&lt;td style="text-align: left"&gt;Index&lt;/td&gt;
&lt;td style="text-align: right"&gt;Points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;C&lt;/td&gt;
&lt;td style="text-align: center"&gt;67&lt;/td&gt;
&lt;td style="text-align: left"&gt;67 – 65 = [2]&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;O&lt;/td&gt;
&lt;td style="text-align: center"&gt;79&lt;/td&gt;
&lt;td style="text-align: left"&gt;79 – 65 = [14]&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;D&lt;/td&gt;
&lt;td style="text-align: center"&gt;68&lt;/td&gt;
&lt;td style="text-align: left"&gt;68 – 65 = [3]&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;E&lt;/td&gt;
&lt;td style="text-align: center"&gt;69&lt;/td&gt;
&lt;td style="text-align: left"&gt;69 – 65 = [4]&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;... which means the word CODE gives the Scrabble score of 7 (as 3 + 1 + 2 +1), and that is indeed correct. It works like a charm!&lt;/p&gt;
&lt;p&gt;To make array indexing a little more obvious, I’ll add it to the score table too:&lt;/p&gt;
&lt;div class="e2-text-table"&gt;
&lt;table cellpadding="0" cellspacing="0" border="0"&gt;
&lt;tr&gt;
&lt;td&gt;Letter:&lt;/td&gt;
&lt;td style="text-align: center"&gt;A&lt;/td&gt;
&lt;td style="text-align: center"&gt;B&lt;/td&gt;
&lt;td style="text-align: center"&gt;C&lt;/td&gt;
&lt;td style="text-align: center"&gt;D&lt;/td&gt;
&lt;td style="text-align: center"&gt;E&lt;/td&gt;
&lt;td style="text-align: center"&gt;F&lt;/td&gt;
&lt;td style="text-align: center"&gt;G&lt;/td&gt;
&lt;td style="text-align: center"&gt;H&lt;/td&gt;
&lt;td style="text-align: center"&gt;I&lt;/td&gt;
&lt;td style="text-align: center"&gt;J&lt;/td&gt;
&lt;td style="text-align: center"&gt;K&lt;/td&gt;
&lt;td style="text-align: center"&gt;L&lt;/td&gt;
&lt;td style="text-align: center"&gt;M&lt;/td&gt;
&lt;td style="text-align: center"&gt;N&lt;/td&gt;
&lt;td style="text-align: center"&gt;O&lt;/td&gt;
&lt;td style="text-align: center"&gt;P&lt;/td&gt;
&lt;td style="text-align: center"&gt;Q&lt;/td&gt;
&lt;td style="text-align: center"&gt;R&lt;/td&gt;
&lt;td style="text-align: center"&gt;S&lt;/td&gt;
&lt;td style="text-align: center"&gt;T&lt;/td&gt;
&lt;td style="text-align: center"&gt;U&lt;/td&gt;
&lt;td style="text-align: center"&gt;V&lt;/td&gt;
&lt;td style="text-align: center"&gt;W&lt;/td&gt;
&lt;td style="text-align: center"&gt;X&lt;/td&gt;
&lt;td style="text-align: center"&gt;Y&lt;/td&gt;
&lt;td style="text-align: center"&gt;Z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Score:&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;8&lt;/td&gt;
&lt;td style="text-align: center"&gt;5&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;10&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;8&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Index:&lt;/td&gt;
&lt;td style="text-align: center"&gt;0&lt;/td&gt;
&lt;td style="text-align: center"&gt;1&lt;/td&gt;
&lt;td style="text-align: center"&gt;2&lt;/td&gt;
&lt;td style="text-align: center"&gt;3&lt;/td&gt;
&lt;td style="text-align: center"&gt;4&lt;/td&gt;
&lt;td style="text-align: center"&gt;5&lt;/td&gt;
&lt;td style="text-align: center"&gt;6&lt;/td&gt;
&lt;td style="text-align: center"&gt;7&lt;/td&gt;
&lt;td style="text-align: center"&gt;8&lt;/td&gt;
&lt;td style="text-align: center"&gt;9&lt;/td&gt;
&lt;td style="text-align: center"&gt;10&lt;/td&gt;
&lt;td style="text-align: center"&gt;11&lt;/td&gt;
&lt;td style="text-align: center"&gt;12&lt;/td&gt;
&lt;td style="text-align: center"&gt;13&lt;/td&gt;
&lt;td style="text-align: center"&gt;14&lt;/td&gt;
&lt;td style="text-align: center"&gt;15&lt;/td&gt;
&lt;td style="text-align: center"&gt;16&lt;/td&gt;
&lt;td style="text-align: center"&gt;17&lt;/td&gt;
&lt;td style="text-align: center"&gt;18&lt;/td&gt;
&lt;td style="text-align: center"&gt;19&lt;/td&gt;
&lt;td style="text-align: center"&gt;20&lt;/td&gt;
&lt;td style="text-align: center"&gt;21&lt;/td&gt;
&lt;td style="text-align: center"&gt;22&lt;/td&gt;
&lt;td style="text-align: center"&gt;23&lt;/td&gt;
&lt;td style="text-align: center"&gt;24&lt;/td&gt;
&lt;td style="text-align: center"&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;This system doesn’t quite work for the lowercase letters though, because the ASCII values of the lowercase letters are different from the capital letters. However, it simply means that we need to subtract the value of the lowercase letter ‘a’ instead of the capital ‘A’.&lt;/p&gt;
&lt;p&gt;So it seems I need an &lt;i&gt;if statement&lt;/i&gt; within the loop to calculate the score depending on the case of the letters using &lt;i&gt;isupper&lt;/i&gt; and &lt;i&gt;islower&lt;/i&gt; functions from the &lt;i&gt;ctype.h&lt;/i&gt; library, which I’ll include in the header too:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;int calculate_score(string word)
{
    // Keep track of the score
    int score = 0;

    // Compute the score for each character
    for (int i = 0, len = strlen(word); i &amp;lt; len; i++)
    {
        if (isupper(word[i]))
        {
            score += points[word[i] - 'A'];
        }
        else if (islower(word[i]))
        {
            score += points[word[i] - 'a'];
        }
    }
    return score;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Since I’m using the &lt;i&gt;points&lt;/i&gt; array in this function, I need to move it out from the main’s local scope to the global scope. The rest is easy: all I need to do is to call the function &lt;i&gt;calculate_score&lt;/i&gt; (twice, for each word) and then compare players’ scores to determine the winner.&lt;/p&gt;
&lt;p&gt;And here is my final code:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;ctype.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

// points assigned to each letter of the alphabet
int points[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10};

int calculate_score(string word);

int main(void)
{
    // Prompt the user for two words
    string word1 = get_string(&amp;quot;Player 1: &amp;quot;);
    string word2 = get_string(&amp;quot;Player 2: &amp;quot;);

    // Compute the score of each word
    int score1 = calculate_score(word1);
    int score2 = calculate_score(word2);

    // Print the winner
    if (score1 &amp;gt; score2)
    {
        printf(&amp;quot;Player 1 wins!\n&amp;quot;);
    }
    else if (score1 &amp;lt; score2)
    {
        printf(&amp;quot;Player 2 wins!\n&amp;quot;);
    }
    else
    {
        printf(&amp;quot;Tie!\n&amp;quot;);
    }
}

int calculate_score(string word)
{
    // Keep track of the score
    int score = 0;

    // Compute the score for each character
    for (int i = 0, len = strlen(word); i &amp;lt; len; i++)
    {
        if (isupper(word[i]))
        {
            score += points[word[i] - 'A'];
        }
        else if (islower(word[i]))
        {
            score += points[word[i] - 'a'];
        }
    }
    return score;
}&lt;/code&gt;&lt;/pre&gt;</description>
</item>

<item>
<title>Credit card validation in C</title>
<guid isPermaLink="false">126030</guid>
<link>https://dsokolovskiy.com/blog/all/credit-card-validation-in-c/</link>
<pubDate>Sun, 25 Feb 2024 14:25:23 +0500</pubDate>
<author>Daniel Sokolovskiy</author>
<comments>https://dsokolovskiy.com/blog/all/credit-card-validation-in-c/</comments>
<description>
&lt;p&gt;&lt;a href="https://dsokolovskiy.com/blog/"&gt;Daniel Sokolovskiy&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;I &lt;a href="/blog/all/super-mario-pyramids-in-c/"&gt;keep learning programming&lt;/a&gt;, and today I share my baby walkthrough of the second homework from the CS50 course titled Credit.&lt;/p&gt;
&lt;p&gt;As a quick disclaimer, I used only tools I’ve learned from the two lessons I had so far.&lt;/p&gt;
&lt;p&gt;Here is the problem to solve:&lt;/p&gt;
&lt;div class="question"&gt;&lt;p&gt;A credit (or debit) card, of course, is a plastic card with which you can pay for goods and services. Printed on that card is a number that’s also stored in a database somewhere, so that when your card is used to buy something, the creditor knows whom to bill. There are a lot of people with credit cards in this world, so those numbers are pretty long: American Express uses 15-digit numbers, MasterCard uses 16-digit numbers, and Visa uses 13- and 16-digit numbers. And those are decimal numbers (0 through 9), not binary, which means, for instance, that American Express could print as many as 10^15 = 1,000,000,000,000,000 unique cards! (That’s, um, a quadrillion.)&lt;/p&gt;
&lt;p&gt;Actually, that’s a bit of an exaggeration, because credit card numbers actually have some structure to them. All American Express numbers start with 34 or 37; most MasterCard numbers start with 51, 52, 53, 54, or 55 (they also have some other potential starting numbers which we won’t concern ourselves with for this problem); and all Visa numbers start with 4. But credit card numbers also have a “checksum” built into them, a mathematical relationship between at least one number and others. That checksum enables computers (or humans who like math) to detect typos (e. g., transpositions), if not fraudulent numbers, without having to query a database, which can be slow. Of course, a dishonest mathematician could certainly craft a fake number that nonetheless respects the mathematical constraint, so a database lookup is still necessary for more rigorous checks.&lt;/p&gt;
&lt;p&gt;Write a program that prompts the user for a credit card number and then reports (via printf) whether it is a valid American Express, MasterCard, or Visa card number, per the definitions of each’s format herein. So that we can automate some tests of your code, we ask that your program’s last line of output be AMEX\n or MASTERCARD\n or VISA\n or INVALID\n, nothing more, nothing less. For simplicity, you may assume that the user’s input will be entirely numeric (i.e., devoid of hyphens, as might be printed on an actual card) and that it won’t have leading zeroes. But do not assume that the user’s input will fit in an int! Best to use get_long from CS50’s library to get users’ input.&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;First, I’ll prompt a user to input a number using the &lt;i&gt;get_long&lt;/i&gt; function from the CS50 library:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

int main(void)
{
    long card_number = get_long(&amp;quot;Number: &amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Next, I’ll do what seems to be the most challenging part of the problem, which is to calculate the checksum of a credit card. In the problem description, they provide additional information on Luhn’s Algorithm that determines the validity of a card as follows:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together.&lt;/li&gt;
&lt;li&gt;Add the sum to the sum of the digits that weren’t multiplied by 2.&lt;/li&gt;
&lt;li&gt;If the total’s last digit is 0, the number is valid!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let’s take the card number 4003600000000014 as an example. For the sake of visibility, let me underline every other digit, starting with the number’s second-to-last digit:&lt;/p&gt;
&lt;p&gt;&lt;u&gt;4&lt;/u&gt; 0 &lt;u&gt;0&lt;/u&gt; 3 &lt;u&gt;6&lt;/u&gt; 0 &lt;u&gt;0&lt;/u&gt; 0 &lt;u&gt;0&lt;/u&gt; 0 &lt;u&gt;0&lt;/u&gt; 0 &lt;u&gt;0&lt;/u&gt; 0 &lt;u&gt;1&lt;/u&gt; 4&lt;/p&gt;
&lt;p&gt;How to extract those digits from a number in C? Turns out, in maths, there is a great operation that can give us the remainder after dividing one number by another, and it’s called &lt;i&gt;modulo&lt;/i&gt;, or mod. You can totally start laughing here, but honestly, I never heard of it before. For example, &lt;i&gt;1234 % 10 = 4&lt;/i&gt; (with modulo operation being expressed by the percent sign), since 4 is the last digit in the number 1234.&lt;/p&gt;
&lt;p&gt;Okay, that was the last digit. But how to get to the second-to-last digit, and then get every other digit from there? This might be not as obvious (at least it wasn’t at first to me), but since we’re dealing with whole numbers, a simple division by 10 basically moves us to one character in a number at a time. For example, &lt;i&gt;1234 / 10 = 123,4&lt;/i&gt;, but since the integer numbers get truncated, the result is actually 123.&lt;/p&gt;
&lt;p&gt;Pretty cool, huh? Now let’s try to get every second number using the combination of division and modulo operations in the code:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

long card_number;
int main(void)
{
    // Prompting a user to input a credit card number
    card_number = get_long(&amp;quot;Number: &amp;quot;);

    // Calculating checksum
    int last_digit;
    int second_to_last_digit;

    while (card_number &amp;gt; 0)
    {
        // Removing the last digit
        last_digit = card_number % 10;
        card_number /= 10;

        // Removing the second last digit
        second_to_last_digit = card_number % 10;
        card_number /= 10;
        printf(&amp;quot;%i&amp;quot;, second_to_last_digit);
    }
    printf(&amp;quot;\n&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code prints 10000604, which are exactly the digits we need from the card number &lt;u&gt;4&lt;/u&gt;0&lt;u&gt;0&lt;/u&gt;3&lt;u&gt;6&lt;/u&gt;0&lt;u&gt;0&lt;/u&gt;0&lt;u&gt;0&lt;/u&gt;0&lt;u&gt;0&lt;/u&gt;0&lt;u&gt;0&lt;/u&gt;0&lt;u&gt;1&lt;/u&gt;4. Keep in mind it’s not a number ten million six hundred four, but individual digits printed one after another. The order of digits is reversed, though it’s irrelevant in this case.&lt;/p&gt;
&lt;p&gt;Next, according to Luhn’s Algorithm, I need to multiply each digit by 2 and get the sum of all of them combined. And I haven’t found a better solution than again using the same modulo and division operations, but this time on the extracted digits:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

long card_number;
int main(void)
{
    // Prompting a user to input a credit card number
    card_number = get_long(&amp;quot;Number: &amp;quot;);

    // Calculating checksum
    int every_second_digit = 0;
    int last_digit;
    int second_to_last_digit;
    int digit1;
    int digit2;

    while (card_number &amp;gt; 0)
    {
        // Removing the last digit and adding to every_other_digit
        last_digit = card_number % 10;
        card_number /= 10;

        // Removing the second last digit
        second_to_last_digit = card_number % 10;
        card_number /= 10;

        // Mupliplying second last digit
        second_to_last_digit *= 2;

        // Adding digits together to get the sum of every_second_digit
        digit1 = second_to_last_digit % 10;
        digit2 = second_to_last_digit / 10;
        every_second_digit += digit1 + digit2;
    }
    printf(&amp;quot;%i&amp;quot;, every_second_digit);
    printf(&amp;quot;\n&amp;quot;);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I’m pretty sure it could be done more elegantly, but I’m using only the knowledge I have so far from the first week of introduction to programming. Importantly, this code works, providing the result of the number 13, as you would expect from the sum of digits 2 + 1 + 2 + 8. Yay!&lt;/p&gt;
&lt;p&gt;Lastly, to finish off the checksum, I’m going to find every other digit, add them together, and then add both sums in the final &lt;i&gt;checksum&lt;/i&gt; variable:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

long card_number;
int main(void)
{
    // Prompting a user to input a credit card number
    card_number = get_long(&amp;quot;Number: &amp;quot;);

    // Calculating checksum
    int every_second_digit = 0;
    int every_other_digit = 0;
    int checksum = 0;
    int last_digit;
    int second_to_last_digit;
    int digit1;
    int digit2;

    while (card_number &amp;gt; 0)
    {
        // Removing the last digit and adding to every_other_digit
        last_digit = card_number % 10;
        card_number /= 10;
        every_other_digit += last_digit;

        // Removing the second last digit
        second_to_last_digit = card_number % 10;
        card_number /= 10;

        // Mupliplying second last digit
        second_to_last_digit *= 2;

        // Adding digits together to get the sum of every_second_digit
        digit1 = second_to_last_digit % 10;
        digit2 = second_to_last_digit / 10;
        every_second_digit += digit1 + digit2;
    }

    // Getting checksum
    checksum = every_second_digit + every_other_digit;

    printf(&amp;quot;%i\n&amp;quot;, checksum);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This code now prints the number 20, which is exactly the kind of value I want from a valid credit card. The hardest part is done!&lt;/p&gt;
&lt;p&gt;Next, I’ll calculate the number of digits in the card number using a simple loop:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Counting the number of digits in the card number
    long n = card_number;
    int number_of_digits = 0;
    do
    {
        n /= 10;
        number_of_digits++;
    }
    while (n != 0);&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To keep the value of that &lt;i&gt;card_number&lt;/i&gt; intact, I added a new variable called &lt;i&gt;n&lt;/i&gt; and assigned its value to &lt;i&gt;card_number&lt;/i&gt;, so I can do the maths with the &lt;i&gt;n&lt;/i&gt; instead. In plain English, that loop says the following: while the card number is not equal to zero, divide the card number by 10, and for every division increase the number of &lt;i&gt;number_of_digits&lt;/i&gt; variable which I use as a counter by one.&lt;/p&gt;
&lt;p&gt;For example, if I were to type in the number 1234, it would go as follows:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;1234 / 10 = 123; the counter increases from 0 to 1;&lt;/li&gt;
&lt;li&gt;123,4 / 10 = 12; the counter increases from 1 to 2;&lt;/li&gt;
&lt;li&gt;12,34 / 10 = 1; the counter increases from 2 to 3;&lt;/li&gt;
&lt;li&gt;1 / 0 = 10; the counter increases from 3 to 4;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now the card number gets equal to zero, and the loop ends with the counter equal to 4, which is the correct number of digits in the number 1234.&lt;/p&gt;
&lt;p&gt;Next, I’ll make another counter to get the first two digits of the card number using pretty much the same logic:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Getting the first two digits of the card number
    int first_two_digits = 0;
    long i = card_number;
    while (i &amp;gt; 100)
    {
        i /= 10;
        first_two_digits = i;
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lastly, I’ll check the validity of the checksum and then check what credit company the card belongs to based of the card number length and starting digits.&lt;/p&gt;
&lt;p&gt;So here is my final code:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// A program in C that checks the validity of a given credit card number

#include &amp;lt;cs50.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

long card_number;
int main(void)
{
    // Prompting a user to input a credit card number
    card_number = get_long(&amp;quot;Number: &amp;quot;);

    // Counting the number of digits in the card number
    long n = card_number;
    int number_of_digits = 0;
    do
    {
        n /= 10;
        number_of_digits++;
    }
    while (n != 0);

    // Getting first two digits of the card number
    int first_two_digits = 0;
    long i = card_number;
    while (i &amp;gt; 100)
    {
        i /= 10;
        first_two_digits = i;
    }

    // Calculating checksum
    int every_second_digit = 0;
    int every_other_digit = 0;
    int checksum = 0;
    int last_digit;
    int second_to_last_digit;
    int digit1;
    int digit2;

    while (card_number &amp;gt; 0)
    {
        // Removing last digit and adding to every_other_digit
        last_digit = card_number % 10;
        card_number /= 10;
        every_other_digit += last_digit;

        // Removing the second last digit
        second_to_last_digit = card_number % 10;
        card_number /= 10;

        // Mupliplying the second last digit
        second_to_last_digit *= 2;

        // Adding digits together to get the sum of every_second_digit
        digit1 = second_to_last_digit % 10;
        digit2 = second_to_last_digit / 10;
        every_second_digit += digit1 + digit2;
    }

    // Getting checksum
    checksum = every_second_digit + every_other_digit;

    // Checking for the card validity
    int validity = checksum % 10;
    if (validity == 0)
    {
        if ((number_of_digits == 15) &amp;amp;&amp;amp; (first_two_digits == 34 || first_two_digits == 37))
        {
            printf(&amp;quot;AMEX\n&amp;quot;);
        }
        else if ((number_of_digits == 16) &amp;amp;&amp;amp; (first_two_digits &amp;gt;= 51 &amp;amp;&amp;amp; first_two_digits &amp;lt;= 55))
        {
            printf(&amp;quot;MASTERCARD\n&amp;quot;);
        }
        else if ((number_of_digits == 16 || number_of_digits == 13) &amp;amp;&amp;amp; (first_two_digits / 10 == 4))
        {
            printf(&amp;quot;VISA\n&amp;quot;);
        }
        else
        {
            printf(&amp;quot;INVALID\n&amp;quot;);
        }
    }
    else
    {
        printf(&amp;quot;INVALID\n&amp;quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Update&lt;/h2&gt;
&lt;p&gt;A week later after posting this solution, I decided to get back to this problem and see if I could improve the code, particularly focusing on the checksum part as it’s essentially the main part.&lt;/p&gt;
&lt;p&gt;Here is my updated code for this function:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// Calculate checksum using Luhn's Algorithm
int calculate_checksum(long long number)
{
    int sum = 0;
    int digit;
    bool is_second_digit = false;

    while (number &amp;gt; 0)
    {
        digit = number % 10; // Get the last digit
        number /= 10; // Reduce the number by one digit

        if (is_second_digit)
        {
            digit *= 2;
            sum += digit % 10 + digit / 10; // Split double numbers into single digits, e.g. 12 into 1 and 2
        }
        else
        {
            sum += digit;
        }

        // Switch the boolean, alternating between odd and even digits
        is_second_digit = !is_second_digit;
    }

    return sum;
}&lt;/code&gt;&lt;/pre&gt;</description>
</item>


</channel>
</rss>