simple C problem - c

I have had to start to learning C as part of a project that I am doing. I have started doing the 'euler' problems in it and am having trouble with the first one. I have to find the sum of all multiples of 3 or 5 below 1000. Could someone please help me. Thanks.
#include<stdio.h>
int start;
int sum;
int main() {
while (start < 1001) {
if (start % 3 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
if (start % 5 == 0) {
sum = sum + start;
start += 1;
} else {
start += 1;
}
printf("%d\n", sum);
}
return(0);
}

You've gotten some great answers so far, mainly suggesting something like:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int soln = 0;
for (i = 1; i < 1000; i++)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
soln += i;
}
}
printf("%d\n", soln);
return 0;
}
So I'm going to take a different tack. I know you're doing this to learn C, so this may be a bit of a tangent.
Really, you're making the computer work too hard for this :). If we figured some things out ahead of time, it could make the task easier.
Well, how many multiples of 3 are less than 1000? There's one for each time that 3 goes into 1000 - 1.
mult3 = ⌊ (1000 - 1) / 3 ⌋ = 333
(the ⌊ and ⌋ mean that this is floor division, or, in programming terms, integer division, where the remainder is dropped).
And how many multiples of 5 are less than 1000?
mult5 = ⌊ (1000 - 1) / 5 ⌋ = 199
Now what is the sum of all the multiples of 3 less than 1000?
sum3 = 3 + 6 + 9 + ... + 996 + 999 = 3×(1 + 2 + 3 + ... + 332 + 333) = 3×∑i=1 to mult3 i
And the sum of all the multiples of 5 less than 1000?
sum5 = 5 + 10 + 15 + ... + 990 + 995 = 5×(1 + 2 + 3 + ... + 198 + 199) = 5×∑i = 1 to mult5 i
Some multiples of 3 are also multiples of 5. Those are the multiples of 15.
Since those count towards mult3 and mult5 (and therefore sum3 and sum5) we need to know mult15 and sum15 to avoid counting them twice.
mult15 = ⌊ (1000 - 1) /15 ⌋ = 66
sum15 = 15 + 30 + 45 + ... + 975 + 990 = 15×(1 + 2 + 3 + ... + 65 + 66) = 15×∑i = 1 to mult15 i
So the solution to the problem "find the sum of all the multiples of 3 or 5 below 1000" is then
soln = sum3 + sum5 - sum15
So, if we wanted to, we could implement this directly:
#include <stdio.h>
int main(int argc, char * argv[])
{
int i;
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int sum3 = 0;
int sum5 = 0;
int sum15 = 0;
int soln;
for (i = 1; i <= mult3; i++) { sum3 += 3*i; }
for (i = 1; i <= mult5; i++) { sum5 += 5*i; }
for (i = 1; i <= mult15; i++) { sum15 += 15*i; }
soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
But we can do better. For calculating individual sums, we have Gauss's identity which says the sum from 1 to n (aka ∑i = 1 to n i) is n×(n+1)/2, so:
sum3 = 3×mult3×(mult3+1) / 2
sum5 = 5×mult5×(mult5+1) / 2
sum15 = 15×mult15×(mult15+1) / 2
(Note that we can use normal division or integer division here - it doesn't matter since one of n or n+1 must be divisible by 2)
Now this is kind of neat, since it means we can find the solution without using a loop:
#include <stdio.h>
int main(int argc, char *argv[])
{
int const mult3 = (1000 - 1) / 3;
int const mult5 = (1000 - 1) / 5;
int const mult15 = (1000 - 1) / 15;
int const sum3 = (3 * mult3 * (mult3 + 1)) / 2;
int const sum5 = (5 * mult5 * (mult5 + 1)) / 2;
int const sum15 = (15 * mult15 * (mult15 + 1)) / 2;
int const soln = sum3 + sum5 - sum15;
printf("%d\n", soln);
return 0;
}
Of course, since we've gone this far we could crank out the entire thing by hand:
sum3 = 3×333×(333+1) / 2 = 999×334 / 2 = 999×117 = 117000 - 117 = 116883
sum5 = 5×199×(199+1) / 2 = 995×200 / 2 = 995×100 = 99500
sum15 = 15×66×(66+1) / 2 = 990×67 / 2 = 495 × 67 = 33165
soln = 116883 + 99500 - 33165 = 233168
And write a much simpler program:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("233168\n");
return 0;
}

You could change your ifs:
if ((start % 3 == 0) || (start % 5 == 0))
sum += start;
start ++;
and don´t forget to initialize your sum with zero and start with one.
Also, change the while condition to < 1000.

You would be much better served by a for loop, and combining your conditionals.
Not tested:
int main()
{
int x;
int sum = 0;
for (x = 1; x <= 1000; x++)
if (x % 3 == 0 || x % 5 == 0)
sum += x;
printf("%d\n", sum);
return 0;
}

The answers are all good, but won't help you learn C.
What you really need to understand is how to find your own errors. A debugger could help you, and the most powerful debugger in C is called "printf". You want to know what your program is doing, and your program is not a "black box".
Your program already prints the sum, it's probably wrong, and you want to know why. For example:
printf("sum:%d start:%d\n", sum, start);
instead of
printf("%d\n", sum);
and save it into a text file, then try to understand what's going wrong.
does the count start with 1 and end with 999?
does it really go from 1 to 999 without skipping numbers?
does it work on a smaller range?

Eh right, well i can see roughly where you are going, I'm thinking the only thing wrong with it has been previously mentioned. I did this problem before on there, obviously you need to step through every multiple of 3 and 5 and sum them. I did it this way and it does work:
int accumulator = 0;
int i;
for (i = 0; i < 1000; i += 3)
accumulator += i;
for (i = 0; i < 1000; i +=5) {
if (!(i%3==0)) {
accumulator += i;
}
}
printf("%d", accumulator);
EDIT: Also note its not 0 to 1000 inclusive, < 1000 stops at 999 since it is the last number below 1000, you have countered that by < 1001 which means you go all the way to 1000 which is a multiple of 5 meaning your answer will be 1000 higher than it should be.

You haven't said what the program is supposed to do, or what your problem is. That makes it hard to offer help.
At a guess, you really ought to initialize start and sum to zero, and perhaps the printf should be outside the loop.

Really you need a debugger, and to single-step through the code so that you can see what it's actually doing. Your basic problem is that the flow of control isn't going where you think it is, and rather than provide correct code as others have done, I'll try to explain what your code does. Here's what happens, step-by-step (I've numbered the lines):
1: while (start < 1001) {
2: if (start % 3 == 0) {
3: sum = sum + start;
4: start += 1;
5: }
6: else {
7: start += 1;
8: }
9:
10: if (start % 5 == 0) {
11: sum = sum + start;
12: start += 1;
13: }
14: else {
15: start += 1;
16: }
17: printf("%d\n", sum);
18: }
line 1. sum is 0, start is 0. Loop condition true.
line 2. sum is 0, start is 0. If condition true.
line 3. sum is 0, start is 0. sum <- 0.
line 4. sum is 0, start is 0. start <- 1.
line 5. sum is 0, start is 1. jump over "else" clause
line 10. sum is 0, start is 1. If condition false, jump into "else" clause.
line 15. sum is 0, start is 1. start <- 2.
line 16 (skipped)
line 17. sum is 0, start is 2. Print "0\n".
line 18. sum is 0, start is 2. Jump to the top of the loop.
line 1. sum is 0, start is 2. Loop condition true.
line 2. sum is 0, start is 2. If condtion false, jump into "else" clause.
line 7. sum is 0, start is 2. start <- 3.
line 10. sum is 0, start is 3. If condition false, jump into "else" clause.
line 15. sum is 0, start is 3. start <- 4.
line 17. sum is 0, start is 4. Print "0\n".
You see how this is going? You seem to think that at line 4, after doing sum += 1, control goes back to the top of the loop. It doesn't, it goes to the next thing after the "if/else" construct.

You have forgotten to initialize your variables,

The problem with your code is that your incrementing the 'start' variable twice. This is due to having two if..else statements. What you need is an if..else if..else statement as so:
if (start % 3 == 0) {
sum = sum + start;
start += 1;
}
else if (start % 5 == 0) {
sum = sum + start;
start += 1;
}
else {
start += 1;
}
Or you could be more concise and write it as follows:
if(start % 3 == 0)
sum += start;
else if(start % 5 == 0)
sum += start;
start++;
Either of those two ways should work for you.
Good luck!

Here's a general solution which works with an arbitrary number of factors:
#include <stdio.h>
#define sum_multiples(BOUND, ...) \
_sum_multiples(BOUND, (unsigned []){ __VA_ARGS__, 0 })
static inline unsigned sum_single(unsigned bound, unsigned base)
{
unsigned n = bound / base;
return base * (n * (n + 1)) / 2;
}
unsigned _sum_multiples(unsigned bound, unsigned bases[])
{
unsigned sum = 0;
for(unsigned i = 0; bases[i]; ++i)
{
sum += sum_single(bound, bases[i]);
for(unsigned j = i + 1; bases[j]; ++j)
sum -= sum_single(bound, bases[i] * bases[j]);
}
return sum;
}
int main(void)
{
printf("%u\n", sum_multiples(999, 3, 5));
return 0;
}

Related

Trying to implement Luhn's Algorithm in C

Iam trying to implement Luhn's algorithm in the C language to check credit card validity, for those who don't know... this is it:
Multiply every other digit by 2, starting with the number’s
second-to-last digit, and then add those products’ digits together.
Add the sum to the sum of the digits that weren’t multiplied by 2.
If the total’s last digit is 0 (or, put more formally, if the total
modulo 10 is congruent to 0), the number is valid!
and to implement that, I looped through the whole number and if the number place I was in had a modulo 2 equal to 0 then I would multiply by two and add to a variable called totalEven.
if that wasn't the case I would add the number I was in to totalOdd without multiplication.
I would then increment the place by one and check the other numbers until I reach 16 (the max digits for a card).
I would later add both variables and check if the total modulo ten was equal to 0. If it means the credit card number is correct, else it is false.
here is the code:
#include <stdio.h>
#include <cs50.h>
//list of variables
//is the card valid
bool isValid = true;
// the creditcard number
long input;
//mod stands for modules, and is used to single out each number as seen later
int mod = 10;
//the location at which number I am checking
int place = 1;
//num is the number I am checking that has been singled out
int num = 0;
//total of numbers * 2 located at locations numbered with even numbers
int totalEven = 0;
//total of numbers located at locations numbered with odd numbers
int totalOdd = 0;
//gets input and stores it in well.. input
input = get_long("Number: ");
// a formula to single out a number, starting with the ones and then as you can see, mod is muliplied by 10 to go over the second number.
num = ((input % mod) - (input % (mod /10))) / (mod/10);
//loops 16 times
for(int i = 0; i < 16; i++)
{
// if the place is even execute below
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
//else do this
else if (place % 2 != 0)
{
totalOdd = totalOdd + num;
}
//moves to the next number
mod = mod * 10;
place++;
}
//fufils the last step of the algorithm
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
problem is that this block of code gives me invalid or !isValid even though the credit card number is supposed to be correct and I checked my "formula" and it works just fine...
I have absolutely no idea what to do... I am a humble hobbyist so plz don't roast me for the monstrosity above.
here is a complete version of the code
#include <stdio.h>
#include <cs50.h>
long power();
int main(void)
{
//AMERX 15 STRT 34 OR 37
//MC 16 STRT 51, 52, 53, 54, 55
//VZA 13 OR 16 STRT 4
long input;
bool isValid = true;
string type;
int mod = 10;
int place = 1;
int num = 0;
int totalEven = 0;
int totalOdd = 0;
do
{
input = get_long("Number: ");
}
while(input < 0);
for(int i = 0; i < 16; i++)
{
num = ((input % mod) - (input % (mod /10))) / (mod/10);
if(place % 2 == 0)
{
totalEven = totalEven + num * 2;
}
else
{
totalOdd = totalOdd + num;
}
mod = mod * 10;
place++;
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
printf("%i , %i", totalEven, totalOdd);
}
if (isValid == true){
if((input < (38 * power(10, 13)) && input >=(37 * power(10, 13))) || (input < (35 * power(10,13)) && input >= (34 * power(10, 13))))
{
type = "AMEX\n";
}
else if(input >= (51 * power(10, 14)) && input < (56 * power(10, 14)))
{
type = "MASTERCARD\n";
}
else if((input < (5 * power(10, 12)) && input >= (4 * power(10, 12))) || (input < (5 * power(10, 15)) && input >= (4 * power(10, 15))))
{
type = "VISA\n";
}
else{
type = "error\n";
}
}
else
{
type = "INVALID\n";
}
if((totalEven + totalOdd) % 10 == 0 )
{
isValid = true;
}
else
{
isValid = false;
}
printf("%s", type);
}
long power(int n, int p)
{
long result = 1;
for(int i = 0; i<p; i++)
{
result = result * n;
}
return result;
I'm not an expert in Luhn algorithm but when I read https://en.wikipedia.org/wiki/Luhn_algorithm it seems to me that you are doing it wrong.
Quote from https://en.wikipedia.org/wiki/Luhn_algorithm :
From the rightmost digit (excluding the check digit) and moving left, double the value of every second digit. The check digit is neither doubled nor included in this calculation; the first digit doubled is the digit located immediately left of the check digit. If the result of this doubling operation is greater than 9 (e.g., 8 × 2 = 16), then add the digits of the result (e.g., 16: 1 + 6 = 7, 18: 1 + 8 = 9) or, alternatively, the same final result can be found by subtracting 9 from that result (e.g., 16: 16 − 9 = 7, 18: 18 − 9 = 9).
I don't see anywhere in your code where you handle that bolded part.
Instead of
totalEven = totalEven + num * 2;
I think you need
int tmp = num * 2;
if (tmp > 9) tmp = tmp - 9;
totalEven = totalEven + tmp;
That said - I think you are making the implementation much more complex than needed by storing the input as a number. Instead of a number you could use an array of digits.
That is - instead of
long input = 1122334455667788
use
int digits[] = {8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1};
// Notice that index zero is the rightmost digit
In this way the algorithm is much more simple:
// Double every second element and check for overflow
for (idx = 1; idx < 16; idx += 2)
{
digits[idx] = 2 * digits[idx];
if (digits[idx] > 9) digits[idx] = digits[idx] - 9;
}
// Calculate the sum
sum = 0;
for (idx = 0; idx < 16; ++idx)
{
sum = sum + digits[idx];
}
If you must receive the input as a number, start by calling a function that converts the number to an array of digits. You can find many, many examples of how that conversion is done here on SO. Here Converting integer into array of digits is just one of many examples.
As I was looking at your code, there some mistakes I want to point out.
You forgot: #include <string.h> as you did declare string type in the code.
input = get_long("Number: "); should have its own do-while loop in case user inputs letters or incorrect numbers.
if(place % 2 == 0){
totalEven = totalEven + num * 2;
}
else if (place % 2 != 0){
totalEven = totalEven + num;
} should totalOdd = totalOdd + num for the second part
totalEven = totalEven + num * 2 is right and wrong at the same time. It only works if the number multiplied by 2 is less than 10. If the num * 2 >= 10, lets say num = 6, then 6 * 2 is 12 which would then be 1 + 2 + totalEven.
num = ((input % mod) - (input % (mod /10))) / (mod/10); This should be in the first for loop.
In #include <math.h>, there is a power function called pow which does exactly as your power() function.
Caution: I have made use of CS50X Library as the question seems to be the one from the same.
#include <stdio.h>
#include <cs50.h>
// Luhn's Algorithm
int main(void)
{
long cardNumber = get_long("Please, enter your card number: ");
int sum1 = 0, num = 0, remainder = 0, sum2 = 0;
long temp = cardNumber;
while (temp > 0)
{
num = ((temp / 10) % 10) * 2; // Multiplying every other digit by 2, starting with the number’s second-to-last digit
while (num > 0)
{
remainder = num % 10;
sum1 += remainder; // Adding those products’ digits together
num /= 10;
}
temp /= 100;
}
// So as to restore the initial values of remainder and temp for the use in next loop
remainder = 0;
temp = cardNumber;
while (temp > 0)
{
remainder = temp % 10;
sum2 += remainder; // Sum of the digits that weren’t multiplied by 2
temp /= 100;
}
((sum1 + sum2) % 10) == 0 ? printf("Valid\n") : printf("Invalid\n");
return 0;
}

Find the minimum number of steps to decrease N to zero

I'm facing some difficulties in the last few days while trying to finish the following task, I hope you guys can assist :
I'm given a single number N, and I'm allowed to perform any of the two operations on N in each move :
One - If we take 2 integers where N = x * y , then we can change the value of N to the maximum between x and y.
Two - Decrease the value of N by 1.
I want to find the minimum number of steps to reduce N to zero.
This is what I have so far, I'm not sure what is the best way to implement the function to find the divisor (someFindDevisorFunction), and if this 'f' function would actually produce the required output.
int f(int n)
{
int div,firstWay,secondWay;
if(n == 0)
return 0;
div = SomefindDivisorFunction(n);
firstWay = 1 + f(n-1);
if(div != 1)
{
secondWay = 1 + f(div);
if (firstWay < secondWay)
return firstWay;
return secondWay;
}
return firstWay;
}
For example, if I enter the number 150 , the output would be :
75 - 25 - 5 - 4 - 2 - 1 - 0
I see this a recursive or iterative problem.
OP's approach hints at recursive.
A recursive solution follows:
At each step, code counts the steps of the various alternatives:
steps(n) = min(
steps(factor1_of_n) + 1,
steps(factor2_of_n) + 1,
steps(factor3_of_n) + 1,
...
steps(n-1) + 1)
The coded solution below is inefficient, but it does explore all possibilities and gets to the answer.
int solve_helper(int n, bool print) {
int best_quot = 0;
int best_quot_score = INT_MAX;
int quot;
for (int p = 2; p <= (quot = n / p); p++) {
int rem = n % p;
if (rem == 0 && quot > 1) {
int score = solve_helper(quot, false) + 1;
if (score < best_quot_score) {
best_quot_score = score;
best_quot = quot;
}
}
}
int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;
if (best_quot_score < dec_score) {
if (print) {
printf("/ %d ", best_quot);
solve_helper(best_quot, true);
}
return best_quot_score;
}
if (print && n > 0) {
printf("- %d ", n - 1);
solve_helper(n - 1, true);
}
return dec_score;
}
int main() {
int n = 75;
printf("%d ", n);
solve(n, true);
printf("\n");
}
Output
75 / 25 / 5 - 4 / 2 - 1 - 0
Iterative
TBD
If you start looking for a divisor with 2, and work your way up, then the last pair of divisors you find will include the largest divisor. Alternatively you can start searching with divisor = N/2 and work down, when the first divisor found will have be largest divisor of N.
int minmoves(int n){
if(n<=3){
return n;
}
int[] dp=new int[n+1];
Arrays.fill(dp,-1);
dp[0]=0;
dp[1]=1;
dp[2]=2;
dp[3]=3;
int sqr;
for(int i=4;i<=n;i++){
sqr=(int)Math.sqrt(i);
int best=Integer.MAX_VALUE;
while(sqr >1){
if(i%sqr==0){
int fact=i/sqr;
best=Math.min(best,1+dp[fact]);
}
sqr--;
}
best=Math.min(best,1+dp[i-1]);
dp[i]=best;
}
return dp[n];
}

Maximizing count of distinct numbers that produce a given sum 'k'

I need help with this dynamic programming problem.
Given a positive integer k, find the maximum number of distinct positive integers that sum to k. For example, 6 = 1 + 2 + 3 so the answer would be 3, as opposed to 5 + 1 or 4 + 2 which would be 2.
The first thing I think of is that I have to find a subproblem. So to find the max sum for k, we need to find the max sum for the values less than k. So we have to iterate through the values 1 -> k and find the max sum for those values.
What confuses me is how to make a formula. We can define M(j) as the maximum number of distinct values that sum to j, but how do I actually write the formula for it?
Is my logic for what I have so far correct, and can someone explain how to work through this step by step?
No dynamic programming is need. Let's start with an example:
50 = 50
50 = 1 + 49
50 = 1 + 2 + 47 (three numbers)
50 = 1 + 2 + 3 + 44 (four numbers)
50 = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 14 (nine numbers)
Nine numbers is as far as we can go. If we use ten numbers, the sum would be at least 1 + 2 + 3 + ... + 10 = 55, which is greater than 50 - thus it is impossible.
Indeed, if we use exactly n distinct positive integers, then the lowest number with such a sum is 1+2+...+n = n(n+1)/2. By solving the quadratic, we have that M(k) is approximately sqrt(2k).
Thus the algorithm is to take the number k, subtract 1, 2, 3, etc. until we can't anymore, then decrement by 1. Algorithm in C:
int M(int k) {
int i;
for (i = 1; ; i++) {
if (k < i) return i - 1;
else k -= i;
}
}
The other answers correctly deduce that the problem essentially is this summation:
However this can actually be simplified to
In code this looks like : floor(sqrt(2.0 * k + 1.0/4) - 1.0/2)
The disadvantage of this answer is that it requires you to deal with floating point numbers.
Brian M. Scott (https://math.stackexchange.com/users/12042/brian-m-scott), Given a positive integer, find the maximum distinct positive integers that can form its sum, URL (version: 2012-03-22): https://math.stackexchange.com/q/123128
The smallest number that can be represented as the sum of i distinct positive integers is 1 + 2 + 3 + ... + i = i(i+1)/2, otherwise known as the i'th triangular number, T[i].
Let i be such that T[i] is the largest triangular number less than or equal to your k.
Then we can represent k as the sum of i different positive integers:
1 + 2 + 3 + ... + (i-1) + (i + k - T[i])
Note that the last term is greater than or equal to i (and therefore different from the other integers), since k >= T[i].
Also, it's not possible to represent k as the sum of i+1 different positive integers, since the smallest number that's the sum of i+1 different positive integers is T[i+1] > k because of how we chose i.
So your question is equivalent to finding the largest i such that T[i] <= k.
That's solved by this:
i = floor((-1 + sqrt(1 + 8k)) / 2)
[derivation here: https://math.stackexchange.com/questions/1417579/largest-triangular-number-less-than-a-given-natural-number ]
You could also write a simple program to iterate through triangular numbers until you find the first larger than k:
def uniq_sum_count(k):
i = 1
while i * (i+1) <= k * 2:
i += 1
return i - 1
for k in xrange(20):
print k, uniq_sum_count(k)
I think you just check if 1 + ... + n > k. If so, print n-1.
Because if you find the smallest n as 1 + ... + n > k, then 1 + ... + (n-1) <= k. so add the extra value, say E, to (n-1), then 1 + ... + (n-1+E) = k.
Hence n-1 is the maximum.
Note that : 1 + ... + n = n(n+1) / 2
#include <stdio.h>
int main()
{
int k, n;
printf(">> ");
scanf("%d", &k);
for (n = 1; ; n++)
if (n * (n + 1) / 2 > k)
break;
printf("the maximum: %d\n", n-1);
}
Or you can make M(j).
int M(int j)
{
int n;
for (n = 1; ; n++)
if (n * (n + 1) / 2 > j)
return n-1; // return the maximum.
}
Well the problem might be solved without dynamic programming however i tried to look at it in dynamic programming way.
Tip: when you wanna solve a dynamic programming problem you should see when situation is "repetitive". Here, since from the viewpoint of the number k it does not matter if, for example, I subtract 1 first and then 3 or first 3 and then 1; I say that "let's subtract from it in ascending order".
Now, what is repeated? Ok, the idea is that I want to start with number k and subtract it from distinct elements until I get to zero. So, if I reach to a situation where the remaining number and the last distinct number that I have used are the same the situation is "repeated":
#include <stdio.h>
bool marked[][];
int memo[][];
int rec(int rem, int last_distinct){
if(marked[rem][last_distinct] == true) return memo[rem][last_distinct]; //don't compute it again
if(rem == 0) return 0; //success
if(rem > 0 && last > rem - 1) return -100000000000; //failure (minus infinity)
int ans = 0;
for(i = last_distinct + 1; i <= rem; i++){
int res = 1 + rec(rem - i, i); // I've just used one more distinct number
if(res > ans) ans = res;
}
marked[rem][last_distinct] = true;
memo[rem][last_distinct] = res;
return res;
}
int main(){
cout << rec(k, 0) << endl;
return 0;
}
The time complexity is O(k^3)
Though it isn't entirely clear what constraints there may be on how you arrive at your largest discrete series of numbers, but if you are able, passing a simple array to hold the discrete numbers, and keeping a running sum in your functions can simplify the process. For example, passing the array a long with your current j to the function and returning the number of elements that make up the sum within the array can be done with something like this:
int largest_discrete_sum (int *a, int j)
{
int n, sum = 0;
for (n = 1;; n++) {
a[n-1] = n, sum += n;
if (n * (n + 1) / 2 > j)
break;
}
a[sum - j - 1] = 0; /* zero the index holding excess */
return n;
}
Putting it together in a short test program would look like:
#include <stdio.h>
int largest_discrete_sum(int *a, int j);
int main (void) {
int i, idx = 0, v = 50;
int a[v];
idx = largest_discrete_sum (a, v);
printf ("\n largest_discrete_sum '%d'\n\n", v);
for (i = 0; i < idx; i++)
if (a[i])
printf (!i ? " %2d" : " +%2d", a[i]);
printf (" = %d\n\n", v);
return 0;
}
int largest_discrete_sum (int *a, int j)
{
int n, sum = 0;
for (n = 1;; n++) {
a[n-1] = n, sum += n;
if (n * (n + 1) / 2 > j)
break;
}
a[sum - j - 1] = 0; /* zero the index holding excess */
return n;
}
Example Use/Output
$ ./bin/largest_discrete_sum
largest_discrete_sum '50'
1 + 2 + 3 + 4 + 6 + 7 + 8 + 9 +10 = 50
I apologize if I missed a constraint on the discrete values selection somewhere, but approaching in this manner you are guaranteed to obtain the largest number of discrete values that will equal your sum. Let me know if you have any questions.

Trailing zeroes in a Factorial

I am trying to write a code for calculating the number of trailing zeroes in a factorial of a specific number (large numbers). However, for small numbers, i get the correct result, but for large the deviations keeps increasing. What's wrong with my logic
#include <stdio.h>
int main(void) {
int t;
scanf("%d", &t);
while (t > 0) {
int factorten = 0, factorfive = 0, factortwo = 0, remainingfive = 0,
remainingtwo = 0;
unsigned int factors = 0;
unsigned int n;
scanf("%u", &n);
for (unsigned int i = n; i > 0; i--) {
if (i % 10 == 0) {
factorten++;
continue;
} else if (i % 5 == 0) {
factorfive++;
continue;
} else if (i % 2 == 0) {
// int new = i;
// while(new % 2 == 0)
//{
// new = new / 2;
factortwo++;
//}
continue;
}
}
factors = factors + factorten;
printf("%u\n", factors);
if (factorfive % 2 == 0 && factorfive != 0) {
factors = factors + (factorfive / 2);
} else {
remainingfive = factorfive % 2;
factors = factors + ((factorfive - remainingfive) / 2);
}
printf("%u\n", factors);
if (factortwo % 5 == 0 && factortwo != 0) {
factors = factors + (factortwo / 5);
} else {
remainingtwo = factortwo % 5;
factors = factors + ((factortwo - remainingtwo) / 5);
}
printf("%u\n", factors);
if ((remainingfive * remainingtwo % 10) == 0 &&
(remainingfive * remainingtwo % 10) != 0) {
factors++;
}
printf("%u\n", factors);
t--;
}
}
Sample Input:
6
3
60
100
1024
23456
8735373
Sample Output:
0
14
24
253
5861
2183837
My OUTPUT
0
13
23
235
5394
2009134
Edit: ignore the first two, they are suboptimal. The third algorithm is optimal.
I think this does what you're trying to do, but is a lot simpler and works:
int tzif(int n)
{
int f2 = 0, f5 = 0;
for (;n > 1; n--)
{
int x = n;
for (;x % 2 == 0; x /= 2)
f2++;
for (;x % 5 == 0; x /= 5)
f5++;
}
return f2 > f5 ? f5 : f2;
}
It counts 2-factors and 5-factors of numbers N...2. Then it returns the smaller of the two (because adding 2-factors is useless without adding 5-factors and vice-versa). Your code is too strange for me to analyze.
I think this should work too, because a factorial will have enough 2-factors to "cover" the 5-factors:
int tzif(int n)
{
int f5 = 0;
for (;n > 1; n--)
for (x = n;x % 5 == 0; x /= 5)
f5++;
return f5;
}
This only counts 5-factors and returns that.
Another method I think should work:
int tzif(int n)
{
int f5 = 0;
for (int d = 5; d <= n; d *= 5)
f5 += n / d;
return f5;
}
Count every fifth number (each has a 5-factor), then every 25-th number (each has another 5-factor), etc.
Have 3 counters - c2,c5,c10.
I think the checks should be
divisible by 5 but not by 10 -> c5++
divisible by 2 but not by 10 -> c2++
divisible by 10. Here if true, then count number of 0's. (c10++)
At last number of 0's will be
smaller_of(c2,c5) + c10
Try to code using this. Should work.
First the trailing 0 in N! are determined by factors 2 and 5 (10). The factors 2 always would be more that the factors 5 in this case you only need to calculate how factors 5 are in the N!.
(N!/5) would give you the number of multiple of 5 (5^1) in N!
(N!/25) would give you the number of multiple of 25 (5^2) in N!
(N!/125) would give you the number of multiple of 125 (5^3) in N!
...
(N!/5^n) would give you the number of multiple of 5^n in N!
When you add the multiple of 5 you are adding too the multiple of 25, 125, ..., 5^n, when you add multiple of 25 you are adding too the multiple of 125, ..., 5^n, etc...
In that case you only need to iterate the power of 5 less or equal than N and add the number of multiple of that 5 power.
Code:
long long trailing_zeros(long long N) {
long long zeros = 0;
for (long long power5 = 5; power5 <= N; power5 *= 5)
zeros += N / power5;
return zeros;
}
#include<iostream>
int main()
{
int size,i;
std::cin >> size;
int*fact;
fact = new int[size];
for (i = 0; i < size; i++)
{
std::cin >> fact[size];
}
for (i = 0; i < size; i++)
{
int con = 5;
int multiple = 0;
do
{
multiple = multiple+(fact[size] / con);
con = con * 5;
} while (con < fact[size]);
std::cout << multiple <<'\n';
}
return 0;
}
this code works perfectly for a single input..bt for multiple inputs it prints the o/p for the last entered number...what is wrong..i jst cant think off it

Finding a brute force algorithm for the following cryptarithm / alphametic puzzle

I'm trying to write a program in C that will solve the following cryptarithm:
one + one = two
seven is prime
nine is a perfect square
Namely, I need to find the numerical values for the words one, two, seven and nine where each letter (o, n, e, t, w, s, v, i) is assigned a numerical value and the complete number also meets all of the above conditions.
I was thinking along the lines of creating an int array for each of the words and then 1) checking if each word meets the condition (e.g is a prime for "seven") and then 2) checking if each integer in the array is consistant with the value of the other words, where the other words also are found to meet their respective conditions.
I can't really see this working though as I would have to continuously convert the int array to a single int throughout every iteration and then I'm not sure how I can simultaneously match each element in the array with the other words.
Perhaps knowing the MIN and MAX numerical range that must be true for each of the words would be useful?
Any ideas?
For a brute-force (ish) method, I'd start with the prime seven, and use the Sieve of Eratosthenes to get all the prime numbers up to 99999. You could discard all answers where the 2nd and 4th digit aren't the same. After that you could move on to the square nine, because three of the digits are determined by the prime seven. That should narrow down the possibilities nicely, and then you can just use the answer of #pmg to finish it off :-).
Update: The following C# program seems to do it
bool[] poss_for_seven = new bool[100000]; // this will hold the possibilities for `seven`
for (int seven = 0; seven < poss_for_seven.Length; seven++)
poss_for_seven[seven] = (seven > 9999); // `seven` must have 5 digits
// Sieve of Eratosthenes to make `seven` prime
for (int seven = 2; seven < poss_for_seven.Length; seven++) {
for (int j = 2 * seven; j < poss_for_seven.Length; j += seven) {
poss_for_seven[j] = false;
}
}
// look through the array poss_for_seven[], considering each possibility in turn
for (int seven = 10000; seven < poss_for_seven.Length; seven++) {
if (poss_for_seven[seven]) {
int second_digit = ((seven / 10) % 10);
int fourth_digit = ((seven / 1000) % 10);
if (second_digit == fourth_digit) {
int e = second_digit;
int n = (seven % 10); // NB: `n` can't be zero because otherwise `seven` wouldn't be prime
for (int i = 0; i < 10; i++) {
int nine = n * 1000 + i * 100 + n * 10 + e;
int poss_sqrt = (int)Math.Floor(Math.Sqrt(nine) + 0.1); // 0.1 in case of of rounding error
if (poss_sqrt * poss_sqrt == nine) {
int o = ((2 * e) % 10); // since 2 * `one` = `two`, we now know `o`
int one = o * 100 + n * 10 + e;
int two = 2 * one;
int t = ((two / 100) % 10);
int w = ((two / 10) % 10);
// turns out that `one`=236, `two`=472, `nine` = 3136.
// look for solutions where `s` != `v` with `s` and `v' different from `o`, `n`, `e`,`t`, `w` and `i`
int s = ((seven / 10000) % 10);
int v = ((seven / 100) % 10);
if (s != v && s != o && s != n && s != e && s != t && s != w && s != i && v != o && v != n && v != e && v != t && v != w && v != i) {
System.Diagnostics.Trace.WriteLine(seven + "," + nine + "," + one + "," + two);
}
}
}
}
}
}
It seems that nine is always equal to 3136, so that one = 236 and two = 472. However, there are 21 possibiliites for seven. If one adds the constraint that no two digits can take the same value (which is what the C# code above does), then it reduces to just one possibility (although a bug in my code meant this answer originally had 3 possibilities):
seven,nine,one,two
56963,3136,236,472
I just found the time to build a c program to solve your cryptarithm.
I think that tackling the problem mathematicaly, prior to starting the brute force programming, will heavily increase the speed of the output.
Some math (number theory):
Since ONE + ONE = TWO, O cant be larget than 4, because ONE + ONE would result 4 digits. Also O cant be 0. TWO end with O and is an even number, because it is 2 * ONE.
Applying these 3 filters to O, the possible values remain O= {2,4}
Hence E can be {1,2,6,7} because (E+E) modulus 10 must be = O. More specificaly, O=2 implicates E={1,6} and O=4 implicates E={2,7}
Now lets filter N. Given that SEVEN is prime, N must be an odd number. Also N cant be 5, because all that ends with 5 is divisible by 5. Hence N={1,3,7,9}
Now that we have reduced the possibilites for the most ocurring characters (O,E,N), we are ready to hit this cryptarith with all of our brutality, having iterations drastically reduced.
Heres the C code:
#include <stdio.h>
#include <math.h>
#define O 0
#define N 1
#define E 2
#define T 3
#define W 4
#define S 5
#define V 6
#define I 7
bool isPerfectSquare(int number);
bool isPrime(int number);
void printSolutions(int countSolutions);
int filterNoRepeat(int unfilteredCount);
int solutions[1000][8]; // solution holder
int possibilitiesO[2] = {2,4};
int possibilitiesN[4] = {1,3,7,9};
int possibilitiesE[4] = {1,6,2,7};
void main() {
int countSolutions = 0;
int numberOne;
// iterate to fill up the solutions array by: one + one = two
for(int o=0;o<2;o++) {
for(int n=0;n<4;n++) {
for(int e=2*o;e<2*o+2;e++) { // following code is iterated 2*4*2 = 16 times
numberOne = 100*possibilitiesO[o] + 10*possibilitiesN[n] + possibilitiesE[e];
int w = ((2*numberOne)/10)%10;
int t = ((2*numberOne)/100)%10;
// check if NINE is a perfect square
for(int i=0;i<=9;i++) { // i can be anything ----- 10 iterations
int numberNine = 1000*possibilitiesN[n] + 100*i + 10*possibilitiesN[n] + possibilitiesE[e];
if(isPerfectSquare(numberNine)) {
// check if SEVEN is prime
for(int s=1;s<=9;s++) { // s cant be 0 ------ 9 iterations
for(int v=0;v<=9;v++) { // v can be anything other than s ------- 10 iterations
if(v==s) continue;
int numberSeven = 10000*s + 1000*possibilitiesE[e] + 100*v + 10*possibilitiesE[e] + possibilitiesN[n];
if(isPrime(numberSeven)) { // store solution
solutions[countSolutions][O] = possibilitiesO[o];
solutions[countSolutions][N] = possibilitiesN[n];
solutions[countSolutions][E] = possibilitiesE[e];
solutions[countSolutions][T] = t;
solutions[countSolutions][W] = w;
solutions[countSolutions][S] = s;
solutions[countSolutions][V] = v;
solutions[countSolutions][I] = i;
countSolutions++;
}
}
}
}
}
}
}
}
// 16 * 9 * 10 * 10 = 14400 iterations in the WORST scenario, conditions introduced reduce MOST of these iterations to 1 if() line
// iterations consumed by isPrime() function are not taken in count in the aproximation above.
// filter solutions so that no two letter have the same digit
countSolutions = filterNoRepeat(countSolutions);
printSolutions(countSolutions); // voila!
}
bool isPerfectSquare(int number) { // check if given number is a perfect square
double root = sqrt((double)number);
if(root==floor(root)) return true;
else return false;
}
bool isPrime(int number) { // simple algoritm to determine if given number is prime, check interval from sqrt(number) to number/2 with a step of +2
int startValue = sqrt((double)number);
if(startValue%2==0) startValue--; // make it odd
for(int k=startValue;k<number/2;k+=2) {
if(number%k==0) return false;
}
return true;
}
void printSolutions(int countSolutions) {
for(int k=0;k<countSolutions;k++) {
int one = 100*solutions[k][O] + 10*solutions[k][N] + solutions[k][E];
int two = 100*solutions[k][T] + 10*solutions[k][W] + solutions[k][O];
int seven = 10000*solutions[k][S] + 1000*solutions[k][E] + 100*solutions[k][V] + 10*solutions[k][E] + solutions[k][N];
int nine = 1000*solutions[k][N] + 100*solutions[k][I] + 10*solutions[k][N] + solutions[k][E];
printf("ONE: %d, TWO: %d, SEVEN: %d, NINE %d\n",one,two,seven,nine);
}
}
int filterNoRepeat(int unfilteredCount) {
int nrSol = 0;
for(int k=0;k<unfilteredCount;k++) {
bool isValid = true;
for(int i=0;i<7;i++) { // if two letters match, solution is not valid
for(int j=i+1;j<8;j++) {
if(solutions[k][i]==solutions[k][j]) {
isValid = false;
break;
}
}
if(!isValid) break;
}
if(isValid) { // store solution
for(int i=0;i<8;i++) {
solutions[nrSol][i] = solutions[k][i];
}
nrSol++;
}
}
return nrSol;
}
You can try the code yourself if you are still interested in this :P. The result is one single solution: ONE: 236, TWO: 472, SEVEN: 56963, NINE: 3136
This solution is the same as Stochastically's solutions, confirming the correctness of both algorithms i think :).
Thanks for providing this nice cryptarithm and have a nice day!
Brute force FTW!
#define ONE ((o*100) + (n*10) + e)
#define TWO ((t*100) + (w*10) + o)
#define SEVEN ((s*10000) + (e*1010) + (v*100) + n)
#define NINE ((n*1010) + (i*100) + e)
for (o = 1; o < 10; o++) { /* 1st digit cannot be zero (one) */
for (n = 1; n < 10; n++) { /* 1st digit cannot be zero (nine) */
if (n == o) continue;
for (e = 0; n < 10; n++) {
if (e == n) continue;
if (e == o) continue;
/* ... */
if (ONE + ONE == TWO) /* whatever */;
/* ... */
}
}
}

Resources