    /**************************************************
     * credit.c                                       *
     *                                                *
     * CS50                                           *
     *                                                *
     * Prompts the user for a credit card number and  *
     *                                                *
     * determines the type of the card.               *
     *************************************************/
     
    #include <cs50.h>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
     
    /* enumeration containing the result of the test on the credit card number ...
       frankly I do not know why I decided to do it that way ... */
    enum credit_card_type {AMEX, MASTERCARD, VISA, INVALID} type;
     
    // used to obtain a string equivalent of an enumerated value
    char card_type[][26] = {"AMEX", "MASTERCARD", "VISA", "INVALID"};
     
    void is_it_legit(long long int credit_card_number, int credit_card_number_length);
    void what_kinda_credit_card(long long int credit_card_number, int credit_card_number_length);
     
    int
    main(void)
    {
            // used to determine the length of the credit card number
            char temp_credit_card_number[17];
     
            // prompt the user for a credit card number
            printf("Enter a credit card number: ");
            long long int credit_card_number = GetLongLong();
     
            // "credit_card_number" converted to a string in order to determine its length
            snprintf(temp_credit_card_number, 17, "%lld", credit_card_number);
            int credit_card_number_length = strlen(temp_credit_card_number);
     
            what_kinda_credit_card(credit_card_number, credit_card_number_length);
     
            return 0;
    }
     
    /*
     * Test the legitimacy of the credit card number.
     */
    void
    is_it_legit(long long int credit_card_number, int credit_card_number_length)
    {
            long long int every_other_digit;
            long long int left_out_digit;
            int products_digits_sum = 0;
            int left_out_digits_sum = 0;
     
            /* isolate every other digits starting with the number's second-to-last digit,
               multiply it by 2, and then add those products' digits together */
            for (int i = credit_card_number_length - 2; i > -1; i -= 2 ) {
                    every_other_digit = ((long long int) (credit_card_number / pow(10, i))) % 10;
                    products_digits_sum += ((every_other_digit * 2) / 10) + ((every_other_digit * 2) % 10);
            }
     
            // isolate the digits which weren't multiplied by 2, and then add these digits together
            for (int i = credit_card_number_length - 1; i > -1; i -= 2) {
                    left_out_digit = ((long long int) (credit_card_number / pow(10, i))) % 10;
                    left_out_digits_sum += left_out_digit;
            }
     
            int final_sum = products_digits_sum + left_out_digits_sum;
     
            // test weather the last digit of "final_sum" is 0 or not
            if (final_sum % 10 == 0)
                    // print type of credit card
                    printf("%s\n", card_type[type]);
            else
                    // print invalid message
                    printf("%s\n", card_type[3]);
    }
     
    /*
     * Determine the type of the credit card.
     */
    void
    what_kinda_credit_card(long long int credit_card_number, int credit_card_number_length)
    {
            // these variables store the first or two first digits of a credit card number.
            int visa_first_digit_13 = (credit_card_number / pow(10, 12));
            int visa_first_digit_16 = (credit_card_number / pow(10, 15));
            int amex_two_first_digits = (credit_card_number / pow(10, 13));
            int mastercard_two_first_digits = (credit_card_number / pow(10, 14));
     
            switch (credit_card_number_length) {
                case 13:
                        // VISA ?
                        if (visa_first_digit_13 == 4) {
                                /* the integer value "2" is assigned to the variable "result".
                                   In the enumeration "credit_card_type" the integer constant 2
                                   is named VISA */
                                type = 2;
                                is_it_legit(credit_card_number, credit_card_number_length);
                        } else
                                // print invalid message
                                printf("%s\n", card_type[3]);
                        break;
                       
                case 15:
                        // AMEX ?
                        if ((amex_two_first_digits == 34) || (amex_two_first_digits == 37)) {
                                type = 0;
                                is_it_legit(credit_card_number, credit_card_number_length);
                        } else
                                printf("%s\n", card_type[3]);
                        break;
     
                case 16:
                        // VISA ?
                        if (visa_first_digit_16 == 4) {
                                type = 2;
                                is_it_legit(credit_card_number, credit_card_number_length);
                              // MASTERCARD ?
                        } else if ((mastercard_two_first_digits == 51)
                                   || (mastercard_two_first_digits == 52)
                                   || (mastercard_two_first_digits == 53)
                                   || (mastercard_two_first_digits == 54)
                                   || (mastercard_two_first_digits == 55)) {
                                type = 1;
                                is_it_legit(credit_card_number, credit_card_number_length);
                        } else
                                printf("%s\n", card_type[3]);
                        break;
     
                default:
                        printf("%s\n", card_type[3]);
            }
    }
