Learning C, need some assistance with "Greedy" CS50 solution - c

I am very new to C. I come from a python background. I would like to know where I went wrong with my code.
I am doing the cs50 greedy problem. What is wrong with my code? It works with some numbers but others don't work. I am trying to get an input from the user asking how much change to give back, then calculate the minimum number of coins I can give back using only $.25, $.10, $.05, $.01
#include <cs50.h>
#include <stdio.h>
int main(void)
{
float n;
do
{
n = get_float("How much change is owed?\n");
}
while(n == EOF);
int minimumamountofcoins = 0;
if (n/.25 >=1){
do
{
n -= .25;
minimumamountofcoins++;
}
while (n/.25 >= 1);
}
if (n/.1 >=1){
do
{
n -= .1;
minimumamountofcoins++;
}
while (n/.1 >=1);
}
if(n/.05 >=1){
do
{
n -= .05;
minimumamountofcoins++;
}
while (n/.05 >=1);
}
if (n/.01 >=1){
do
{
n -= .01;
minimumamountofcoins++;
}
while (n/.01 >=1);
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}
New code: (works perfectly except when entering 4.2)
#include <cs50.h>
#include <stdio.h>
int main(void)
{
float n;
do
{
n = get_float("How much change is owed?\n");
}
while(n == EOF);
int cents = (int)(n * 100);
int minimumamountofcoins = 0;
if (cents/25 >= 1){
while (cents/25 >= 1)
{
cents -= 25;
minimumamountofcoins++;
}
}
if (cents/10 >= 1){
while (cents/10 >= 1)
{
cents -= 10;
minimumamountofcoins++;
}
}
if(cents/5 >= 1){
while (cents/5 >= 1)
{
cents -= 5;
minimumamountofcoins++;
}
}
if (cents/1 >= 1){
while (cents/1 >= 1)
{
cents -= 1;
minimumamountofcoins++;
}
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}

Since you did not include test cases, I did my own. Here are some of the cases for which your algorithm does not return the correct answer:
.04, .11, .17, .19, .21, .26, .32, etc.
These cases all fail when calculating the number of pennies (in the final do-while loop), and they all return one less coin then they should. This is because of error with floating-point numbers. With print statements, I discovered that when the division for the final penny was being calculated, the same thing occurred each time:
n/.01 = 0.99999999
This is obviously not intended, as this should be equal to 1, and the final penny should be added to the total. Thus, your code, which works in theory, is broken because of floating-point numbers.
To avoid this, you could do any number of things, such as keeping track of dollars and cents separately as integers, change the condition to be n/.01 >= .9999 instead of n/.01 >= 1, treat the amount of money you are doing the calculations on as an integer number of cents, or any other number of things.
Personally, I prefer that last option, treating the amount of money as an integer number of cents. This is easy to do, as all you have to do to convert from dollars to cents is multiply by 100. Thus, the easiest thing to do is to use this same algorithm, except use integers.
Thus, the code would look something like this:
int main(){
float n;
//code that parses in the amount of money, n now stores that amount
int cents = (int)(n * 100);
int minimumamountofcoins = 0;
if (cents/25 >= 1){
while (cents/25 >= 1)
{
cents -= 25;
minimumamountofcoins++;
}
}
if (cents/10 >= 1){
while (cents/10 >= 1)
{
cents -= 10;
minimumamountofcoins++;
}
}
if(cents/5 >= 1){
while (cents/5 >= 1)
{
cents -= 5;
minimumamountofcoins++;
}
}
if (cents/1 >= 1){
while (cents/1 >= 1)
{
cents -= 1;
minimumamountofcoins++;
}
}
printf("The minimum amount of coins is %d\n", minimumamountofcoins);
}

Related

Cannot figure out how to properly increment a variable inside of a while loop, C

EDIT: After re-writing my code in my IDE, for the 8th time today, I have made rookie mistake of giving my inputs a false data type, that has been fixed but my outputs still are incorrect.
Details about my goal: When making change, odds are you want to minimize the number of coins you’re dispensing for each customer.
Well, suppose that a cashier owes a customer some change and in that cashier’s drawer are quarters (25¢), dimes (10¢), nickels (5¢), and pennies (1¢). The problem to be solved is to decide which coins and how many of each to hand to the customer.
Expected Result:
Change owed: 0.41
4
Actual result:
Change owed: 0.41
3
#include <math.h>
#include <cs50.h>
#include <stdio.h>
int main (void)
{
float dollars;
int changeowed = 0;
do
{
dollars = get_float ("Change owed: ");
}
while (dollars < 0);
float cents = round(dollars * 100);
while (cents >= 25)
{
cents = cents - 25;
changeowed++;
}
while (cents > 10)
{
cents = cents - 10;
changeowed++;
}
while (cents > 5)
{
cents = cents - 5;
changeowed++;
}
while (cents > 1)
{
cents = cents - 1;
changeowed++;
}
printf("%i \n", changeowed);
}
Here's the problem: There are 4 loops, one for quarters, one for dimes, one for nickels, and one for pennies. The first loop condition is correct:
while (cents >= 25)
The other three are incorrect:
while (cents > 10)
while (cents > 5)
while (cents > 1)
These all need to be changed to use >= in place of >.
you can do it much simple for any nominals. Use integer types.
int nominals[] = {100, 25, 10, 5, 1, 0};
void getNominals(double money, int *result)
{
unsigned ncents = money * 100.0;
int *nm = nominals;
while(*nm && ncents)
{
*result++ = ncents / *nm;
ncents %= *nm++;
}
}
int main(void)
{
int result[sizeof(nominals) / sizeof(nominals[0])] = {0};
getNominals(4.36, result);
for(size_t index = 0; nominals[index]; index++)
{
printf("%d = %d\n", nominals[index], result[index]);
}
}
https://godbolt.org/z/WdYxxr

Greedy calculator in C

I need to create a greedy calculator that accepts only .25, .10, .5 and .1.
I need to print the minimum amount of coins needed to fulfil the change.
This is going on a loop and I can't see what to do to fix it.
I am still learning, go easy on me :)
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
int coins = 0;
int change;
int i;
do {
change = get_float("How much change? ");
}
while (change <= 0); /* condition for acceptance*/
int cents = round(change * 100);
if (cents > 0) { /* run all whiles we get to 1c*/
while ((cents - 25) >= 25) { /* run 25c */
coins += 1;
}
while ((cents - 10) >= 10) { /* run 10c*/
coins += 1;
}
while ((cents - 5) >= 5) { /* run 5c*/
coins += 1;
}
while ((cents - 1) >= 1) { /* run 1c*/
coins += 1;
}
} else {
printf("%d", coins);
}
}
There are multiple problems in your code:
change is defined as an int, so the amount entered by the user is truncated before the computation even starts, producing an incorrect result.
you do not update cents in any of the loops, so you get an infinite loop if any of these conditions is true.
note that the conditions are incorrect: (cents - 25) >= 25 is true if cents is greater or equal to 50.
the test if (cents > 0) is incorrect. You would only print the number of coins if cents <= 0.
the last loop is useless, the number of remaining cents is the number of pennies to count.
Here is a modified version:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
float change;
do {
change = get_float("How much change? ");
}
while (change <= 0); /* condition for acceptance*/
int cents = round(change * 100); /* avoid rounding issues */
int coins = 0;
while (cents >= 25) { /* count quarters */
cents -= 25;
coins += 1;
}
while (cents >= 10) { /* count dimes */
cents -= 10;
coins += 1;
}
while (cents >= 5) { /* count nickels */
cents -= 5;
coins += 1;
}
count += cents; /* count pennies */
printf("%d\n", coins);
return 0;
}
The cents variable never changes. (cents - 25) indeed returns the value of current cents minus 25, but you don't assign it to cents variable, so one of those 4 while loops will always be true.
There is also another probem: get_float function returns float while change variable is int, if the user were to enter a value less than 1, such as .5, it would be casted to 0 and prompt again and again until the user enters a value greater than 1. Also note you would probably get a wrong answer for any non-integer input.

Cs50 pset1-cash expected "18\n", not "22\n"

I'm a begginer in C and I'm taking cs50. I'm having trouble with pset1/cash. I have no idea what is wrong with my code. The program first asks the user how much change is owed and then spits out the minimum number of coins with which said change can be made. It works fine with most inputs but when I check it I get expected "18\n", not "22\n" Please, what do I need to change?
#include <stdio.h>
#include <cs50.h>
int main(void)
{
float change;
int cents, cents2, cents3, cents4;
int total = 0;
//Ask for user input and check
do
{
change = get_float("How much change?\n");
}
while (change < 0);
change = (change * 100) / 0.01;
//Multiply the float numbers
if (change < 1)
{
change *= 100;
}
else if (change < 10)
{
change *= 10;
}
//Change to int
cents = change;
//How many quarters
while (cents >= 2500)
{
cents -= 2500;
total++;
}
cents2 = cents;
//How many dimes
while (cents2 >= 1000)
{
cents2 -= 1000;
total++;
}
cents3 = cents2;
//How many nickels
while (cents3 >= 500)
{
cents3 -= 500;
total++;
}
cents4 = cents3;
//How many pennies
while (cents4 >= 100)
{
cents4 -= 100;
total++;
}
printf("%i\n", total);
}
Edit: I have finally found my error. In this line: change = (change * 100) / 0.01; I added 0.01 to it and now it works.
change = (change * 10000) + 0.01;
Use the round function to round up your numbers. In this part of your code, you need to add the round function.
change = (change * 100) / 0.01;
It has to be like this:
cents = round(change * 100);
This will round up the numbers to the nearest wholeIf you have other such problems, you can use a debugger such as debug50, in which you put a breakpoint by clicking in the right of the line number, then in your terminal window(the one where you execute clang) you should type:
~/pset1/cash/ $ debug50 ./cash
Or whatever your program is called. This will open the debugger and inside it you will find all the variables and what they are equal to. Press on the button next to the play button to move one line of code forward.
P.S
There are lots of questions exactly like yours. Just search your problem into the Search... at the top of your screen and I daresay you'll find an answer to your problem.

If statements within while loop not giving expected output in C

I am making programme to calculate the maximum amount of coins in change given a set amount of change. I take the change demanded as a positive float and convert it into an int by multiplying it by 100, so that the amount is in pennies. Upon testing, some values work but others, such as 4.2, do not, giving the answer 22 when it should be 18. I cannot work out why. Could some please help.
int main (void)
{
float change;
do
{
printf("How much change do you want?\n");
change = get_float();
} while (change < 0);
int change1 = change * 100;
int coins = 0;
while (change1 != 0)
{
if (change1 >= 25)
{
change1 -= 25;
coins++;
}
else if (change1 >= 10)
{
change1 -= 10;
coins++;
}
else if (change1 >= 5)
{
change1 -= 5;
coins++;
}
else if (change1 >= 1)
{
change1 -= 1;
coins++;
}
}
//Print change
printf("%i\n", coins);
}
Roundoff error:
When the machine stores 4.2, it is not exactly 4.2. Thus, when multiplied by 100, it gets to 419.99999..., which converts to the int 419. The way to fix this would be:
int change1 = change * 100 + 0.5;
This could also be checked by
printf("%i\n", change1)
after the calculation.
Hum i just want you show to prefer use ternary operator in this situation :
#include <stdio.h>
int main() {
float number;
int result;
int ctn_coin;
ctn_coin = 0;
printf("How much change do you want?\n");
scanf("%f", &number); result = number * 100.1;
while (result != 0)
{
result >= 25 ? result -= 25 :
result >= 10 ? result -= 10 :
result >= 5 ? result -= 5 :
result >= 1 ? result -= 1 : 0;
ctn_coin++;
}
printf("%i\n", ctn_coin);
return (0);
}

Why are the conditional statements in the while loop causing the program to pause selectively forever?

I am trying to figure out what the minimum number of coins required to pay back change is by using a "greedy algorithm". The program I have written below is working as expected if the user enters a multiple of only one of the constant integers. However, when it comes to to dealing with more than one coin, the program just pauses forever.
I think that the problem is in my CountGreed function's while loop on the conditional statements. I have tried finding answers but nothing I have come across seems to be giving me insight to guide me to understanding what the matter is with my logic.
I know this is trivial and there is repetition in the loop through the conditional statements which then brings me to the stated question. Multiples of 0.25, 0.10, 0.05 and 0.01 are working well if entered by the user. For example, 1.00, 1.25, 0.20 but not 0.30, 1.13, 0.26, etc.
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %i.\n", CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100;
int IntCents = (int)roundf(Cents);
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int SubCoinCount = 0;
int CoinCount = 0;
int Remainder = 0;
while (IntCents) {
if (IntCents >= Quarter) {
SubCoinCount = IntCents / Quarter;
CoinCount += SubCoinCount;
Remainder += IntCents % Quarter;
IntCents = Remainder;
} else if (IntCents < Quarter && IntCents >= Dime) {
SubCoinCount = IntCents / Dime;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
} else if (IntCents < Dime && IntCents >= Nickel) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Nickel;
IntCents = Remainder;
} else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
}
return CoinCount;
}
I pasted the whole main.c file so that the flow of my entire program can be seen clearly though the problem is with the loop. I have tried this on multiple compilers just to make sure that it is my fault.
This:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Nickel;
CoinCount += SubCoinCount;
Remainder += IntCents % Dime;
IntCents = Remainder;
}
should be this:
else if (IntCents < Nickel && IntCents >= Penny) {
SubCoinCount = IntCents / Penny; // <--- Change to Penny, or just remove
CoinCount += SubCoinCount;
Remainder += IntCents % Penny; // <--- Change to Penny
IntCents = Remainder;
}
Your four if cases are identical except for the denomination of the coin, which means they're crying out to be put into a separate function. Doing that is a great way to avoid making errors like this in one or some of your cases, because you're only writing it once.
I also suspect:
Remainder += IntCents % Dime;
should be:
Remainder = IntCents % Dime;
otherwise Remainder will increase endlessly, and IntCents will never get to zero. Remainder actually becomes unnecessary, in this case, and you can assign the result directly to IntCents.
But there's a simpler way of doing this entirely. Here's a suggested alternative, for your perusal:
#include <stdio.h>
// This cries out to be its own function
int coin_count(int cents, int denomination, int * remainder)
{
*remainder = cents % denomination;
return cents / denomination;
}
// Better way
int CountGreed(int IntCents)
{
static const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
while ( IntCents > 0 ) {
if ( IntCents >= Quarter ) {
CoinCount += coin_count(IntCents, Quarter, &IntCents);
} else if ( IntCents >= Dime ) {
CoinCount += coin_count(IntCents, Dime, &IntCents);
} else if ( IntCents >= Nickel ) {
CoinCount += coin_count(IntCents, Nickel, &IntCents);
} else if ( IntCents >= Penny ) {
CoinCount += coin_count(IntCents, Penny, &IntCents);
}
}
return CoinCount;
}
// Even better way
int CountGreed2(int IntCents)
{
static const int coins[4] = {25, 10, 5, 1};
int CoinCount = 0;
for ( int i = 0; i < 4; ++i ) {
if ( IntCents >= coins[i] ) {
CoinCount += coin_count(IntCents, coins[i], &IntCents);
}
}
return CoinCount;
}
int main(void) {
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed(96));
printf("Coins for $1.25 (should be 5): (%d)\n", CountGreed2(125));
printf("Coins for $1.00 (should be 4): (%d)\n", CountGreed2(100));
printf("Coins for $0.96 (should be 6): (%d)\n", CountGreed2(96));
return 0;
}
which outputs:
paul#local:~/Documents/src/sandbox$ ./coins
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
Coins for $1.25 (should be 5): (5)
Coins for $1.00 (should be 4): (4)
Coins for $0.96 (should be 6): (6)
paul#local:~/Documents/src/sandbox$
The need for a separate function in CountGreed2() is less obvious, since you're only writing it once anyway, but tastes vary.
#include "cs50.h" // Contains declaration for GetFloat()
#include <stdio.h>
#include <math.h>
float PromptChange(void); // Returns customer change in dollars
int ConvertToCents(float); // Returns a conversion from dollars to cents
int CountGreed(int); // Returns the minimum number of coins for which change can be made
int main (void)
{
float Dollars = PromptChange();
int Cents = ConvertToCents(Dollars);
int CoinCount = CountGreed(Cents);
printf("The minimum number of coins required to give back change is %d.\n",
CoinCount);
return 0;
}
float PromptChange(void)
{
float Dollars;
do {
printf ("Owed change: $");
Dollars = GetFloat ();
} while (Dollars < 0);
return Dollars;
}
// the original function ConvertToCents()
// will usually return an incorrect value
// typically off by 1
// This is because float values often cannot exactly represent
// the desired value
int ConvertToCents(float Dollars)
{
float Cents = Dollars * 100.0f; // note all values should be float
int IntCents = floor(Cents+.5f); // round up to whole penny
return IntCents;
}
int CountGreed(int IntCents)
{
const int Quarter = 25, Dime = 10, Nickel = 5, Penny = 1;
int CoinCount = 0;
int Remainder = IntCents; // get working value
// note following using integer divides
CoinCount = Remainder / Quarter; // max quarters
Remainder = Remainder % Quarter; // update working value
CoinCount += Remainder / Dime; // max dimes
Remainder = Remainder % Dime; // update working value
CoinCount += Remainder / Nickle; // max nickles
Remainder = Remainder % Nickle; // update working value
CoinCount += Remainder; // final pennys
return CoinCount;
}

Resources