Validating credit cards - c

I'm very new to C language much less programming in general and am working through the cs50 edx course. I encountered this problem in week 1 where I'm supposed to validate credit cards given their characteristics (they're in the comments).
After hours worth of research and trials, I managed to solve it though I think it's way too long and I am 90% sure it can be shortened with loops. I added the long version that works and an iteration of it which uses loops that I just can't get to work. Any advice would help and be very much appreciated!
#include <stdio.h>
#include <cs50.h>
int main(void)
{
//user input for credit card number
long creditCard = get_long("Credit Card: ");
//initialize array for finding digits
int digit[16];
int oddDigits[8];
//separate all digits as variables in array digits[]
digit[0] = ((creditCard / 1000000000000000) % 10);
digit[1] = ((creditCard / 100000000000000) % 10);
digit[2] = ((creditCard / 10000000000000) % 10);
digit[3] = ((creditCard / 1000000000000) % 10);
digit[4] = ((creditCard / 100000000000) % 10);
digit[5] = ((creditCard / 10000000000) % 10);
digit[6] = ((creditCard / 1000000000) % 10);
digit[7] = ((creditCard / 100000000) % 10);
digit[8] = ((creditCard / 10000000) % 10);
digit[9] = ((creditCard / 1000000) % 10);
digit[10] = ((creditCard / 100000) % 10);
digit[11] = ((creditCard / 10000) % 10);
digit[12] = ((creditCard / 1000) % 10);
digit[13] = ((creditCard / 100) % 10);
digit[14] = ((creditCard / 10) % 10);
digit[15] = (creditCard % 10);
//double the value of every other digit as oddDigits[]
oddDigits[0] = digit[0] * 2;
oddDigits[1] = digit[2] * 2;
oddDigits[2] = digit[4] * 2;
oddDigits[3] = digit[6] * 2;
oddDigits[4] = digit[8] * 2;
oddDigits[5] = digit[10] * 2;
oddDigits[6] = digit[12] * 2;
oddDigits[7] = digit[14] * 2;
//the first part in finding the sum of every other digit
for (int o = 0; o < 8; o++) {
if (oddDigits[o] > 9) {
oddDigits[o] -= 9;
}
}
//part 2 of finding the sum of every other digit
int sum = 0;
for (int s = 0; s < 8; s++) {
sum += oddDigits[s];
}
//sum of everything else
for (int s2 = 1; s2 < 16; s2 += 2) {
sum += digit[s2];
}
//check if last digit is 0
int check = sum % 10;
//last part of validation
if (check != 0)
printf("INVALID\n");
//type of card
else {
if (digit[0] == 0 && digit[1] == 3 && (digit[2] == 4 || digit[2] == 7)) //15 digits starting with either 34 or 37
{
printf("AMAX\n");
}
else if (digit[0] == 5 && (digit[1] == 1 || digit[1] == 2 || digit[1] == 3 || digit[1] == 4 || digit[1] == 5)) //16 digits starting with either 51 - 54
{
printf("MASTERCARD\n");
}
else if (digit[0] == 4) //16 digits starting with 4
{
printf("VISA\n");
}
else if (digit[0] == 0 && digit[1] == 0 && digit[2] == 0 && digit[3] == 4) //13 digits starting with 4
{
printf("VISA\n");
}
else
{
printf("INVALID\n");
}
}
}
The only part I changed is where I try to get every digit of the number using for loops and the part where I try to double every other digit... I did a test where after the loop it will print all the digits separately and it always prints 1 no matter what and I'm wondering what I'm doing wrong here...
//initialize array for finding digits
int digit[16];
int oddDigits[8];
//separate all digits as variables in array digits[]
for (int d = 0; d < 16; d++) {
for (long i = 1000000000000000; i > 9; i /= 10) {
digit[d] = ((creditCard / i) % 10);
}
}
//double the value of every other digit as oddDigits[]
for (int n = 0; n < 8; n++) {
for (int t = 0; t < 15; t += 2) {
oddDigits[n] = digit[t]*2;
}
}

While you are separating all digits as variables in array digits[], the for loop runs till.
digit[14] = ((creditCard / 10) % 10);
to fix this change it as
for (long i = 1000000000000000; i > 0; i /= 10)
{
digit[d] = ((creditCard / i) % 10);
}
ie change 9 to 0. in this way, the last iteration of the loop will run
digit[15] = ((creditCard/1) % 10);
which is same as
digit[15] = (creditCard % 10);
now see, the outer loop is running 16 times. the inner loop is also running 16 times and the inner loop is running only once per iteration of the outer loop. So one of the loops is redundant. remove the outer loop. keep the d variable as 0 and increment it by 1 after dividing the digit. i.e.
int d = 0;
//separate all digits as variables in array digits[]
for (long i = 1000000000000000; i > 9; i /= 10)
{
digit[d] = ((creditCard / i) % 10);
d++;
}
You can also do it like this
long i = 1000000000000000;
for (int d = 0; d < 16; d++)
{
digit[d] = ((creditCard / i) % 10);
i /= 10;
}
Either one will work.
Now this part //double the value of every other digit as oddDigits[]
It can also be done with 1 loop. In your code, the variable t is just double of the variable n in each step. So, you don't need the t variable too. (just replace t by 2*n)
//double the value of every other digit as oddDigits[]
for (int n = 0; n < 8; n++)
{
oddDigits[n] = digit[2*n]*2;
}

Related

Remove digits from number without reversing the number

I got an exercise where I need to create a function that get two parameters, number (long) and digit (int) and I have to remove the digit from the number and return it.
When I do the exercise I reverse the number and in the end I reverse it again to get the original number.
I wanted to know if there is a way to do the exercise without reversing the number twice.
long myFunction(long number, int digit){
int tmp = 0;
if (digit <= 9 && digit >= 0){
while (number != 0){
if (number % 10 != digit){
tmp = (tmp + (number % 10)) * 10;
}
number = number / 10;
}
tmp = tmp / 10;
int rev = 0, remainder;
while (tmp != 0) { // Reverse an Integer
remainder = tmp % 10;
rev = rev * 10 + remainder;
tmp /= 10;
}
return rev;
}
return number;
}
A different approach could be to track the position of the digit you want to add to the result (by multiplying it by 10position). This way, you won't have to reverse the number when you're done:
long removeDigit(long number, int digit) {
long result = 0L;
long multiplier = 1L;
while (number > 0L) {
int currDigit = (int) number % 10;
if (currDigit != digit) {
result += multiplier * currDigit;
multiplier *= 10;
}
number /= 10;
}
return result;
}

Changing a value of an integer in a function

I have a problem with the function 'multiply2' which doesn't change values of ccn1 to ccn8. It has to multiply them by 2, and if the result is equal or more than 10, than take products of this equation and add them together (i.e. 7 * 2 = 14, so 1 + 4 = 5). The whole thing would work, but I've noticed that the function 'multiply2' keeps the value of pX to itself, and I'd like to overwrite values of ccn1 to ccn8, and then sum all values together (ccn1 to ccn16). Please help :(
PS: I'm new at this so please be gentle, I'm sure it looks like a mess to you.
The program compiles as it is with no errors, mind you, it does include cs50.h library for "get_long_long" function which prompts a user for a credit card number
I've tried to use pointers but clearly I don't fully understand the concept! I've managed to dereference *pX which assigned values of ccn1, ccn2, etc. but they still don't update in main.
the whole problem described here: https://docs.cs50.net/2018/x/psets/1/credit/credit.html#tl-dr
Thank you!
# include <cs50.h>
# include <stdio.h>
# include <math.h>
void multiply2 (int * pX);
long long ccn;
//a program to check the credit card number and print out if it's American Express, Visa, or MasterCard. if else - ILVALID.
int main(void)
{
//prompt user for a credit card number
ccn = get_long_long("Number: ");
//every second digit starting from second to last
int ccn1 = (ccn % 100) / 10;
int ccn2 = (ccn % 10000) / 1000;
int ccn3 = (ccn % 1000000) / 100000;
int ccn4 = (ccn % 100000000) / 10000000;
int ccn5 = (ccn % 10000000000) / 1000000000;
int ccn6 = (ccn % 1000000000000) / 100000000000;
int ccn7 = (ccn % 100000000000000) / 10000000000000;
int ccn8 = (ccn % 10000000000000000) / 1000000000000000;
//printf("%i\n%i\n%i\n%i\n%i\n%i\n%i\n%i\n", ccn1, ccn2, ccn3, ccn4, ccn5, ccn6, ccn7, ccn8);
//all the other digits
int ccn9 = (ccn % 10);
int ccn10 = (ccn % 1000) / 100;
int ccn11 = (ccn % 100000) / 10000;
int ccn12 = (ccn % 10000000) / 1000000;
int ccn13 = (ccn % 1000000000) / 100000000;
int ccn14 = (ccn % 100000000000) / 10000000000;
int ccn15 = (ccn % 10000000000000) / 1000000000000;
int ccn16 = (ccn % 1000000000000000) / 100000000000000;
//printf("%i\n%i\n%i\n%i\n%i\n%i\n%i\n%i\n", ccn9, ccn10, ccn11, ccn12, ccn13, ccn14, ccn15, ccn16);
if (((ccn >= 340000000000000 && ccn <= 349999999999999) || (ccn >= 370000000000000 && ccn <= 379999999999999)) ||
((ccn >= 5100000000000000 && ccn <= 5199999999999999) || (ccn >= 5500000000000000 && ccn <= 5599999999999999)) ||
((ccn >= 4000000000000 && ccn <= 4999999999999) || (ccn >= 4000000000000000 && ccn <= 4999999999999999)))
{
multiply2(&ccn1);
multiply2(&ccn2);
multiply2(&ccn3);
multiply2(&ccn4);
multiply2(&ccn5);
multiply2(&ccn6);
multiply2(&ccn7);
multiply2(&ccn8);
int sum = (ccn1 + ccn2 + ccn3 + ccn4 + ccn5 + ccn6 + ccn7 + ccn8 + ccn9 + ccn10 + ccn11 + ccn12 + ccn13 + ccn14 + ccn16);
printf("%i\n", sum);
}
/NOTHING FROM ABOVE - INVALID
else
{
printf("INVALID\n");
}
}
void multiply2 (int * pX)
{
if ((*pX *2) >= 10)
{
*pX = ((*pX * 2) % 10) + 1;
printf("%i\n", *pX);
}
else
{
printf("%i\n", (*pX * 2));
}
}
Your function multiply2 changes the value of the passed parameter only in case its value is at least 5.
Try this:
void multiply2(int* pX)
{
*pX = *pX * 2; /* Multiply value by 2 */
if (*pX >= 10)
*pX = (*pX % 10) + 1; /* Adjust if value greater than or equal to 10 */
printf("%d\n", *pX);
}

C program not displaying value

when i call my multi() it will calculate the binary number just fine, but won't calculate the adding(). If i switch the two in order, it will calculate the adding() and not calculate the multi(). Is there a reason why the second function call isn't displaying its value? It will print the printf, but not the value. Any help would be great.
#include <stdio.h>
long binary1, binary2, binary3, binary4, multiply = 0;
int binaryproduct(int, int);
int digit, factor = 1;
int multi();
int adding();
int main()
{
binary3 = binary1;
binary4 = binary1;
printf("Enter the first binary number: ");
scanf("%ld", &binary1);
printf("Enter the second binary number: ");
scanf("%ld", &binary2);
multi();
printf("\n");
adding();
}
int adding()
{
int i = 0, remainder = 0, sum[20];
while (binary3 != 0 || binary4 != 0) {
sum[i++] =(binary3 % 10 + binary4 % 10 + remainder) % 2;
remainder =(binary3 % 10 + binary4 % 10 + remainder) / 2;
binary1 = binary3 / 10;
binary2 = binary4 / 10;
}
if (remainder != 0) {
sum[i++] = remainder;
}
--i;
printf("Sum of two binary numbers: ");
while (i >= 0) {
printf("%d", sum[i--]);
}
return 0;
}
int multi()
{
while (binary2 != 0) {
digit = binary2 % 10;
if (digit == 1) {
binary1 = binary1 * factor;
multiply = binaryproduct(binary1, multiply);
} else {
binary1 = binary1 * factor;
}
binary2 = binary2 / 10;
factor = 10;
}
printf("Product of two binary numbers: %ld", multiply);
return 0;
}
int binaryproduct(int binary3, int binary4)
{
int i = 0, remainder = 0, sum[20];
int binaryprod = 0;
while (binary1 != 0 || binary2 != 0) {
sum[i++] =(binary1 % 10 + binary2 % 10 + remainder) % 2;
remainder =(binary1 % 10 + binary2 % 10 + remainder) / 2;
binary1 = binary1 / 10;
binary2 = binary2 / 10;
}
if (remainder != 0) {
sum[i++] = remainder;
}
--i;
while (i >= 0) {
binaryprod = binaryprod * 10 + sum[i--];
}
return binaryprod;
}
Your globals aren't being initialized. In you adding() function you use:
binary1 = binary3/10
binary2 = binary4/10
and in the binaryproduct function you have two local ints named binary3, binary4 that you don't use.
You should be using unique names, initializing you variables, use local variables in places where globals are unnecessary.

My program stops looping and i cannot figure out why

if the user inputs the "value" as 1223445 the output should read as follows:
After change #1: 12235
After change #2: 135
the code is meant to take out two consecutive numbers with the same value. the first loop works but then it stops and I cannot figure why. here is the code:
{
int count;
int y;
int z;
int b;
int c;
int d;
int a;
int ct;
y = 0;
z = 1;
d = 0;
count = 0;
if (value > 0)
while ((z * 10 + z) != (y % 100))
{
y = value % 10 + y * 10;
z = y % 10;
value /= 10;
count = count + 1;
}
value = value * pow(10, count - 2);
y = y / 100;
count = count - 3;
while(y > 0)
{
b = y % 10;
c = pow(10, count);
d = d + c * b;
y = y / 10;
count = count - 1;
}
value = value + d;
ct = 1;
printf("After change #%d: %d\n", ct, value);
a = value;
while (a > 1)
{
if((a % 100) - (a % 10) - (10 * (a % 10)) == 0)
Change(value);
else
a = a / 10;
}
return;
}
Here's a simple solution: (not sure how you want to handle odd numbered repeats e.g. '111', '11111')
public static long strip(long value, long sum) {
if(value==0) return sum;
long tens = value % 100;
long ones = value % 10;
if(ones*10 == tens-ones) {
return strip(value /100, sum);
}
if(sum==0) sum +=(value%10);
else {
long x = (long)Math.ceil((Math.log10(sum)));
sum =(long) (Math.pow(10,x) * ones + sum);
}
return strip(value /10, sum);
}

Euler 160 : Find the non trivial 5 digits of the factorial

Given a number find the 5 digits before the trailing 0. 9! = 362880
so f(9)=36288 10! = 3628800 so f(10)=36288 20! = 2432902008176640000
so f(20)=17664 Find f(1,000,000,000,000)
For this I have computed the f(10^6) and then f(10^12) =
(f(10^6))^(10^6) for computing the f(n) ... I am computing the
factorial by removing any 5 and corresponding 2 so that all the
trailing zeros are removed.
But I am getting a wrong answer.
Is there a problem in approach or some silly mistake ?
Code for reference
long long po(long long n, long long m, long long mod) {
if (m == 0) return 1;
if (m == 1) return n % mod;
long long r = po(n, m / 2, mod) % mod;
if (m % 2 == 0) return (r * r) % mod;
return (((r * r) % mod) * n) % mod;
}
void foo() {
unsigned long long i, res = 1, m = 1000000 , c = 0, j, res1 = 1, mod;
mod = ceil(pow(10, 9));
cout << mod << endl;
long long a = 0, a2 = 0, a5 = 0;
for (i = 1 ; i <= m; i++) {
j = i;
while (j % 10 == 0)
j /= 10;
while (j % 2 == 0) {
j /= 2;
a2++;
}
while (j % 5 == 0) {
j /= 5;
a5++;
}
res = (res * j ) % mod;
}
a = a2 - a5;
for (i = 1; i <= a; i++)
res = (res * 2) % mod;
for (i = 1; i <= 1000000; i++) {
res1 = (res1 * res) % mod;
}
cout << res1 << endl;
}
Your equality f(10^12) = (f(10^6))^(10^6) is wrong. f() is based on factorials, not powers.
Your assumptions are erroneous:
f(10^12) is not the same as f(10^6)^(10^6).
in order to get the low order non 0 digits of the factorial, it does not suffice to remove all multiples of 10, 2 and 5 from the multiplicands. Removing the multiples of 10 is a good idea, for 5 and 2, you should remove the factor 2 or 5 only if the other multiplicand is a multiple of 5 and 2 respectively.
You should simplify the code and compute modulo some power of 10, but 10^9 seems too high as 10^9 * 10^12 will overflow 64-bit type unsigned long long.

Resources