Numbers acting strange in both Lua and C - c

I have written this program in Lua and C which is a greedy algorithm.
Greedy = function(num)
local q = 0;
local d = 0;
local n = 0;
local p = 0;
local x = 1;
while x == 1 do
if (num >= 0.25) then
q = q + 1;
num = num - 0.25;
print("q");
elseif (num >= 0.10) then
d = d + 1;
num = num - 0.10;
print("d");
elseif (num >= 0.05) then
n = n + 1;
num = num - 0.05;
print("n");
elseif (num >= 0.01) then
p = p + 1;
num = num - 0.01;
print("p");
end
if (num == 0) then
x = 0;
end
end
if (x == 0) then
local all = q+d+n+p;
print(all);
end
end
Greedy(1);
This code works fine with some numbers but if I try to calculate numbers like 0.90,0.04 or 0.12 it wont work and I have the same code written in C too. But I have the same problem with it.
#include <stdio.h>
int greedy(void){
int quarter = 0;
int dime = 0;
int nickel = 0;
int penny = 0;
float num = 0.40;
int x = 1;
while(x == 1){
if (num >= 0.25){
quarter = quarter + 1;
num = num - 0.25;
printf("q\n");
}else if(num >= 0.10){
dime = dime + 1;
num = num - 0.10;
printf("d\n");
}else if(num >= 0.05){
nickel = nickel + 1;
num = num - 0.05;
printf("n\n");
}else if(num >= 0.01){
penny = penny + 1;
num = num - 0.01;
printf("p\n");
};
if(num == 0){
x = 0;
};
};
if(x == 0){
int all = quarter + dime + nickel + penny;
printf("%i\n", all);
};
return 0;
};
int main(void){
greedy();
}
What did I do wrong?

The problem is that, many floating-point numbers can't be represented (using double or float) precisely, try this in Lua:
> print(0.9 == 0.9 - 0.2 + 0.1 + 0.1)
false
It should be equal in maths, but not here. The same for the C code.

Seeing your scope is counting your money, rewrite your code this way:
Greedy = function(num)
local q = 0;
local d = 0;
local n = 0;
local p = 0;
local x = 1;
num=num*100
while x == 1 do
if (num >= 25) then
q = q + 1;
num = num - 25;
print("q");
elseif (num >= 10) then
d = d + 1;
num = num - 10;
print("d");
elseif (num >= 5) then
n = n + 1;
num = num - 5;
print("n");
elseif (num >= 1) then
p = p + 1;
num = num - 1;
print("p");
end
if (num == 0) then
x = 0;
end
end
if (x == 0) then
local all = q+d+n+p;
print(all);
end
end
Greedy(1);

Related

Validating credit cards

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;
}

sum-digits function - C language

Digits Sum function
I have to write a function - digits sum,
for ex.: the number : 9887, 9+8+8+7= 32 , 3+2= 5
Will this function work well?
int sum_digits(int num){
if (num < 10)
return num;
int a = sum_digits (num / 10) + num % 10;
if (a > 9)
a = sum_digits (a / 10) + a % 10;
return a;
}
int sum_digits(int num){
if (num < 10)
return num;
int a = sum_digits (num / 10) + num % 10;
if (a > 10)
a += sum_digits (a / 10) + a % 10;
return a;
}
This will work.
Note that a= is replaced by a+= and a>9 is replaced by a>10

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);
}

Expression Result Unused Greedy Algorithm

I have run this program and get the error expression result unused. I may be doing something simple wrong, but I have spent the day trying to figure it out to no avail. Any help you can provide is greatly appreciated.
#include <stdio.h>
#include <cs50.h>
int main()
{
int x, y = 0;
printf("Enter the amount of change ");
x = GetFloat() * 100;
while (x != 0)
{
if (x >= 25)
{
x - 25;
y = y + 1;
}
if (x >= 10 && x < 25)
{
x - 10;
} y = y + 1;
if (x >= 5 && x < 10)
{
x - 5;
} y = y + 1;
if (x >= 1 && x < 5)
{ x - 1;
y= y + 1;
}
}
printf("The number of coins neccessary is %d", y);
}
if (x >= 25)
{
x - 25; // This accomplishes nothing
y = y + 1;
}
if (x >= 10 && x < 25)
{
x - 10; // This accomplishes nothing
} y = y + 1;
if (x >= 5 && x < 10)
{
x - 5; // This accomplishes nothing
} y = y + 1;
if (x >= 1 && x < 5)
{
x - 1; // This accomplishes nothing
y= y + 1;
}
In each of those lines you're subtracting a number from x, but you're doing nothing with the result. If you're trying to update x with the result, you need to do just like you're doing with y, and put x = in front of the expression.
So if you want x to go down by 25, you should write:
x = x - 25;
Alternatively, you can write the shorthand:
x -= 25; // Note the equal sign
All the 4 statements x - 25, x- 10, x- 5, x - 1 will turn out to be useless unless you assign that value to x;
Because you are trying to subtract the value from x, but you are not assigning the new value to x.
Here is the solution of your problem:
#include <stdio.h>
#include <cs50.h>
int main()
{
int x, y = 0;
printf("Enter the amount of change ");
x = GetFloat() * 100;
while (x != 0)
{
if (x >= 25)
{
x = x - 25; //or x-=25;
y = y + 1;
}
if (x >= 10 && x < 25)
{
x = x - 10; //or x-=10;
y = y + 1;
}
if (x >= 5 && x < 10)
{
x = x - 5; //or x-=5;
y = y + 1;
}
if (x >= 1 && x < 5)
{
x = x - 1; //or x-=1; or x--; or --x; :)
y = y + 1;
}
}
printf("The number of coins neccessary is %d", y);
}
I would remain to be convinced about your loop structure. There's the division operator that can be used to good effect:
int total = 0;
int ncoins;
int amount = GetFloat() * 100;
assert(amount >= 0);
ncoins = amount / 25;
total += ncoins;
amount -= ncoins * 25;
assert(amount < 25);
ncoins = amount / 10;
total += ncoins;
amount -= ncoins * 10;
assert(amount < 10);
ncoins = amount / 5;
total += ncoins;
amount -= ncoins * 5;
assert(amount < 5);
total += amount;
That's written out longhand; you could devise a loop, too:
int values[] = { 25, 10, 5, 1 };
enum { N_VALUES = sizeof(values) / sizeof(values[0]) };
int total = 0;
int ncoins;
int amount = GetFloat() * 100;
assert(amount >= 0);
for (int i = 0; i < N_VALUES && amount > 0; i++)
{
ncoins = amount / values[i];
total += ncoins;
amount -= ncoins * values[i];
}
assert(amount == 0);

C randomize with percents influence

Here's my ramdomize code:
int monstername;
monstername = rand() % 3;
but I want 0 with 70% of output 1 with 20% 2 with 10% how I can do this with C?
int monstername;
int random_var = rand() % 10;
if(random_var < 7) {
// 0-70%
monstername = 0;
}
else if(random_var < 9) {
// 70-90% here
monstername = 1;
}
else {
// 90-100% here
monstername = 2;
}
Try
int monstername;
int rn = rand();
if (rn < 0.7*RAND_MAX)
monstername = 0;
else if (rn < 0.9*RAND_MAX)
monstername = 1;
else
monstername = 2;
Assuming you don't care about modulo bias, you want something like:
int monstername;
int r = rand() % 10;
if (r < 7)
monstername = 0;
else if (r < 9)
monstername = 1;
else
monstername = 2;
If you do care about modulo bias, look into arc4random_uniform(3) instead of rand(3).
int weighted[10] = {0,1,0,0,1,0,0,2,0,0};
monstername = weighted[rnd() % 10];

Resources