pulling cards at random until getting one of each - loops

1 of 10 different cards, randomly distributed, in each box
Any one collecting all 10 cards at the end of the first 21 days will receive 2 weeks paid vacation
every day until Johnny collects all 10 cards.
How many boxes of cereal must Johnny’s mother purchase to collect at least one of each card?
At the end of the program display a sentence indicating whether or not Johnny won the trip. Run the program a few times and compare the results.
it prints out only 01 and 0 for sum of cards dont know why the loop isn't doing the right values.
import java.util.Random;
public class Cereal{
public static void main(String []args) {
String [] wCards = {"eevee","jirachi","pichu","Taillow","flying pikachu","Togekiss","Blastoise","raichu","flareon","lanturn"};
int e=0,j=0,p=0,t=0,fp=0,toge=0,b=0,r=0,f=0,l=0,sum=0,pull;
int[] pokeCards= {e,j,p,t,fp,toge,b,r,f,l};
Random rand = new Random(10);
boolean card = false;
while (card == false) {
pull = rand.nextInt();
if(pull ==0)
e++;
if(pull == 1)
j++;
if(pull== 2)
p++;
if(pull == 3)
t++;
if(pull == 4)
fp++;
if(pull == 5)
toge++;
if(pull == 6)
b++;
if(pull == 7)
r++;
if(pull == 8)
f++;
if(pull== 9)
l++;
for(int i =0; i < pokeCards.length; i++) {
if(pokeCards[i] >= 0) {
card = true;}
sum+= pokeCards[i];
}
System.out.println("Acme Cereal Inc. Disney World Contest Simulation\n");
System.out.println("Total number of boxes of cereal purchased : " + sum);
System.out.println("Card#\tCArd\tNumber of cards collected");
for(int k=0; k < wCards.length;k++) {
System.out.println(k+1 + "\t" + wCards[k] + "\t\t" + pokeCards[k]+1);
}
if(sum<21){
System.out.println("You won a Vacation");
}else {
System.out.println(" sorry no Vacation");
}
}
}
}

Related

My CS50 Credit code is not producing any output after adding a check for type of credit card

The calculating if the card is valid is correct as I tested that and the code performed correctly there, so I removed that section from under the Do section loop to appease stackoverflow. The problem comes from deciding what type of card was used; the program does nothing and waits for the next command in the console. I'm just not seeing what the issue is. Below is my code and I tested with card number 4003600000000014, the result should've printed out "Visa":
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// Array to store the individual digits of the card
long card, card_copy;
int pos = 0, sum = 0, card_id;
do
{
card = get_long("CC#: ");
card_copy = card;
while(card != 0)
{
if(pos % 2 != 0)
{
int temp = 2 * (card % 10);
// For #s > 9
if(temp > 9)
{
sum += (temp % 10 + temp / 10);
}
else
{
sum += temp;
}
}
else
{
sum += card % 10;
}
card /= 10; // Divides card # to remove the decimal place
// and moves to the next digit in CC
pos++;
}
}
while(card != 0);
if(sum % 10 == 0)
{
// Divides card to only have the first 2 digits
card_id = card_copy / (pow(10, pos - 1));
// Divides card to only have first digit; 4 for Visa
int visa_id = card_copy / (pow(10, pos - 2));
// 16-digit; start with 51, 52, 53, 54, or 55
if(pos == 15 && (card_id >= 51 && card_id <= 55))
{
printf("MasterCard");
}
// 15-digit; start with 34 or 37
else if(pos == 14 && (card_id == 34 || card_id == 37))
{
printf("American Express");
}
// 13-digit; start with 4
else if(pos == 12 && visa_id == 4)
{
printf("Visa");
}
// 16-digit; start with 4
else if(pos == 15 && visa_id == 4)
{
printf("Visa");
}
}
else
{
printf("Invalid: %d\n", sum);
}
}
The long type has a maximum value of 2147483647. This wouldn't hold the shortest card type I know which is 12 digits.
Either change to unsigned long long or better still use a string.

What is wrong with my code for CS50 credit problem?

Why is my code wrong?? I don't know why... This problem is to get a card number from the user and tell whether it is a valid card number or an invalid card number. It could either be an American Express card, MasterCard, or a Visa. American Express card has 15 digits and must either start with 34 or 36, while MasterCard has 16 digits and can start with 51, 52, 53, 54, 55. The Visa card must either have 13 or 16 digits, and must start with a 4. This problem also uses the Luhn's algorithm wherein to check if a card number is valid every other number starting from the tens place multiplied by two, then if added the digits no their product but their digits, so if you multiply 8 by 2 its 16 so you must add 1 + 6 and the other numbers. Then once you got the sum you must add them to the ones you didn't multiply by 2, then lastly if their sum is divisible by 10 then it is valid. I really don't know where I went wrong I've been looking at my code for almost 3 hours. Also noob programmer here..
#include<stdio.h>
int main(void)
{
//declare and initialize card number
long long number = 0;
//ask user for their credit card number
do
{
printf("Number: ");
scanf("%lli", &number);
}
while (number < 0);
//declare and initialize a counter for the number of the digits
int counter = 0;
long long temp = number;
//loop to count the number of digits
while (temp > 0)
{
temp /= 10;
counter++;
}
//statement for invalid digits
if (counter != 13 && counter != 15 && counter != 16)
{
printf("Invalid number of digits\n");
}
//array to store the digits individually
int digits[counter];
// loop to store the digits in the array
for (int i = 0; i < counter; i++)
{
digits[i] = number % 10;
number /= 10;
}
//loop to multiply every other digit by 2
for (int j = 1; j < counter; j += 2)
{
digits[j] *= 2;
}
// loop to separate then add digits that are greater than 10
for (int x = 1; x < counter; x += 2)
{
if (digits[x] > 10)
{
int s = digits[x] % 10;
digits[x] /= 10;
digits[x] = (digits[x] % 10) + s;
}
}
int sum = 0;
//loop to get the sum of all numbers
for (int y = 0; y < counter; y++)
{
sum += digits[y];
}
sum %= 10;
switch (sum)
{
case '0':
if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7)))
{
printf("American Express\n");
}
else if (counter == 16 && digits[15] == 5)
{
printf("Master Card\n");
}
else if (counter == 13 && digits [12] == 4)
{
printf("Visa\n");
}
else if (counter == 16 && digits[15] == 4)
{
printf("Visa\n");
}
break;
default:
printf("Invalid\n");
break;
}
}
There are three errors, and I'm ashamed that it took myself so long to spot especially the second one.
if (digits[x] > 10) is a kind of off-by-one error. Rather than greater than 10, the Description of the Luhn algorithm says: If the result of this doubling operation is greater than 9 …, so this has to be if (digits[x] > 9).
case '0': must rather be case 0:, since sum is an integer, not a character representation.
if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7))) fails because the digits have been modified by the algorithm in-place, so the 7 has become a 5. We could write if (counter == 15 && (digits[14] == 3 && (digits[13] == 4 || digits[13] == 7*2-9))) instead; same for else if (counter == 16 && digits[15] == 5).

Detect valid credit card number algorithm

I just enrolled in the online CS50 course and doing the pset1 about detecting valid credit card number. However, my algorithm does not work well as I expected. I used debugging tool to see step by step result, as long as variable i run from 1 to 9 it works perfectly, all values are added to the sum correctly. But when it comes to i = 10 and so on, the numNotSquared got assigned -8 and numSquared got assigned -16 and it keeps like that until the end of the number. Please help me with that, thank you.
// Headers and libraries
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// Prompt user for card number
long cardNumber = get_long("Enter card number: ");
// Get the length of input
int length = floor(log10(cardNumber)) + 1;
// Range validation
if (length < 13 || length > 16)
{
printf("INVALID\n");
}
int numSquared = 0;
int numNotSquared = 0;
int sum = 0;
// Algorithm to detect valid card
// Based on Luhn's algorithm (https://lab.cs50.io/cs50/labs/2020/x/credit/)
for (int i = 1; i <= length; i++)
{
// If digit is on odd position then mutiply by two
if (i % 2 != 0)
{
{
numSquared = ((int)(cardNumber / pow(10, length - i)) % 10) * 2;
}
// If the total is >= 10, then sum the products' digit
if (numSquared >= 10)
{
sum += ((numSquared % 10) + 1);
}
else
{
sum += numSquared;
}
}
// If digit is on even position then add to the sum
else
{
numNotSquared = (int)(cardNumber / pow(10, length - i)) % 10;
sum += numNotSquared;
}
}
// Find remainder of (total / 10)
if (sum % 10 == 0)
{
if (floor(cardNumber / pow(10, length - 1)) == 4)
{
printf("VISA\n");
}
else
{
int firstTwoDigits = floor(cardNumber / pow(10, length - 2));
if (firstTwoDigits == 34 || firstTwoDigits == 37)
{
printf("AMEX\n");
}
else if (firstTwoDigits == 51 || firstTwoDigits == 52 || firstTwoDigits == 53 || firstTwoDigits == 54 || firstTwoDigits == 55)
{
printf("MASTERCARD\n");
}
}
}
else
{
printf("INVALID\n");
}
}

'if' statement in C not executing even though conditions are met

I'm a first time programmer trying to complete a simple command line program as part of the first assignment for an online course I am taking, but I seem to have hit a roadblock that I can't figure out with GDB or my own research.
After hours of rewrites, and hours of debugging, I finally got the code below to compile. The program is supposed to take a credit card number as an input, and then check whether it's valid per the specifications of the assignment. I used a test number from here: PayPal Test Credit Cards
The odd thing is, when I enter an AMEX card number, it correctly produces the text "AMEX", but when I try a Visa or a Master Card, it prints "INVALID".
In GDB I broke at the Verify function and it seems to incorrectly skip these two if/else if statements without proceeding to the Checksum function even though conditions appear to be met.
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
...
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
...
The AMEX line of code that correctly executes is:
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
The arguments for all three lines seem to be formatted exactly the same. That is far as I could get in GDB though. I would print totalDigits, firstDigit, and secondDigit in GDB right before stepping through the above two non-executing lines and everything looked correct. So I'm stumped, why is the AMEX line executing, but not the others?
Thanks in advance everyone. This is the first program after hello.c that I've tried to write, so I am open to absolutely any criticism or suggestions if it looks like I'm doing something weird/wrong.
Full code:
checker.c
#include <stdio.h>
#include <stdlib.h>
int MAX = 16;
int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);
int main (void)
{
int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;
do
{
printf("Please enter a credit card number:\n");
scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.
switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
case 1 :
printf("VISA\n");
break;
case 2 :
printf("MASTERCARD\n");
break;
case 3 :
printf("AMEX\n");
break;
case 0 :
printf("INVALID\n");
break;
default :
printf("INVALID\n");
}
free(output);
return 0;
}
int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{
int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;
while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
totalDigits = totalDigits + 1;
i++;
}
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
return 1;
}
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
return 2;
}
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
{
return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
return 0;
}
}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.
int i = 0;
arrayReversed[0] = 0;
if (i < (MAX - 1) && x >= 10)
{
do
{
arrayReversed[i] = x % 10;
x = x / 10;
i++;
}
while (i < (MAX -1) && x >= 10);
}
if (i < MAX && x >= 1 && x <= 9)
{
arrayReversed[i] = (int) x;
x = (x - x);
}
if (x == 0)
{
int j = 0;
do
{
array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
j++;
i--;
}
while (j < MAX && i >= 0);
array[j] = -1;
}
free(arrayReversed);
return array;
}
int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);
while (i >= 0)
{
sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
i -= 2;
}
while (j >= 0)
{
sum2 = (cardNumber[j] + sum2);
j -= 2;
}
if (((sum1 + sum2) % 10) == 0)
{
return 0;
}
else
{
return 1;
}
}
Your first problem is here:
if (firstDigit == 4 && totalDigits == (13 | 16) && ...
You need to write:
if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...
Your first check is looking for 0x1D == 29 as the number of digits (because, as paisanco points out in a comment, the | operator is the bitwise OR operator), and no credit card needs 29 digits (yet, and not for a long time to come). Note the extra parentheses for clarity and accuracy. Don't mess around risking removing them — the code won't work properly again. And in general, be explicit if your condition has both && and || operators and use parentheses to group terms explicitly.
You have similar problems elsewhere. As it happens, (4 | 7) is the same value as 7, so the condition works when the second digit is 7 (but not when it is 4). But it doesn't mean what you intended it to mean.
Computer languages don't work the same as human languages. Get used to writing out the condition somewhat more verbosely. Some other languages provide shorthands for these conditions; C is not such a language.

C programming exercise?

I'm reading a book on C programming and try to do the exercises:
Write a program that prints a horizontal histogram consisting of stars(*). One star for every number there can be in the interval 0 ... 70.
#include <stdio.h>
void draw_stars(int number_of_stars) {
int counter = 0;
for(counter = 0; counter < number_of_stars; counter++) {
printf("*");
}
printf("\n");
}
int main(void) {
int counter1, counter2, ones, tens, zero, one, two, three, four, five, six, seven, eight, nine = 0;
for(tens = 0; tens < 7; tens++) {
if(tens == 0)
zero = zero + 1;
if(tens == 1)
one = one + 10;
if(tens == 2)
two = two + 10;
if(tens == 3)
three = three + 10;
if(tens == 4)
four = four + 10;
if(tens == 5)
five = five + 10;
if(tens == 6)
six = six + 10;
if(tens == 7)
seven = seven + 10;
for(ones = 0; ones < 9; ones++) {
if(ones == 0)
zero++;
if(ones == 1)
one++;
if(ones == 2)
two++;
if(ones == 3)
three++;
if(ones == 4)
four++;
if(ones == 5)
five++;
if(ones == 6)
six++;
if(ones == 7)
seven++;
if(ones == 8)
eight++;
if(ones == 9)
nine++;
}
}
draw_stars(zero);
draw_stars(one);
draw_stars(two);
draw_stars(three);
draw_stars(four);
draw_stars(five);
draw_stars(six);
draw_stars(seven);
draw_stars(eight);
draw_stars(nine);
}
For some reason my program enters a infinite loop printing stars. But I can't find out why?
I haven't been able to come up with any other solution, but I still think it's ugly and bloated. How would a real C programmer solve this?
Edit:
After reading and understanding the chapter about arrays in the book, I was able to write a more clean version of the program. I'm posting it here as it might help other beginners understand the use of arrays. Writing an identical program in terms of output, but using different functionality of the language is a great learning experience.
#include <stdio.h>
#define TENS 7
void draw_stars(int stars) {
int star_counter = 0;
for (star_counter = 0; star_counter < stars; star_counter++)
printf("%c", '*');
}
int main(void) {
int number_array[10];
int tens_counter, ones_counter;
for (ones_counter = 0; ones_counter < 10; ones_counter++)
number_array[ones_counter] = 0;
for (tens_counter = 0; tens_counter < TENS; tens_counter++) {
if (tens_counter != 0)
number_array[tens_counter] += 10;
else
number_array[tens_counter] += 1;
for (ones_counter = 0; ones_counter < 10; ones_counter++)
number_array[ones_counter]++;
}
for (ones_counter = 0; ones_counter < 10; ones_counter++) {
draw_stars(number_array[ones_counter]);
printf("\n");
}
}
Initialize all variables:
int counter1=0, counter2=0, ones=0, tens=0, zero=0, one=0..
BTW, for better performance,
replace if with else if except the first one in the block. Why do you want to check all if conditions when you already know only one is true?
FYI, when a condition is true in Else if, all other ifs are skipped.
If you wanted to initialize all ints to zero, you should write:
int counter1=0, counter2=0, ...
Now only nine is init by 0, other variables contain rubbish - arbitrary values.
in main() you have to initialize all variable with zero like
int counter1=0,counter2=0 and so on
otherwise it take garbage value and perform operation with those values and then output will be like
********
*****************
*****************
*****************
*****************
*****************
*****************
*******
*******

Resources