Euler Project 4: Finding the largest palindrome product - arrays

So, I've wrote several function prototypes for finding the largest palindrome products. The idea is that put the original number into an array in reverse order then convert the array into a number as reverse number. Then compare the reverse number with original number to see if these two numbers are equal or not. However, I am stuck at implementing these functions prototypes in main method. If yes, then it is a palindrome product/ Any suggestions? Please, have mercy I am new to C
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
// Taking a number and reverse it. Put it in reverse order into an array. Then, convert all elements in the array into an array again
//Ex: Original number = 6542
//Input: "6542" -> arr[4] = {2,4,5,6} -> Output: "2456"
//Original Number = 6542; Reverse Number = 2456
//Original Number != Reverse Number -> The number is not palindrome. Palindrome Number Example: 456654, 1, 2332.
int convert_reverse_num (int original_num, int digits_count){
int arr_size = digits_count;
int x = original_num;
int final_reverse_num = 0;
int *arr;
arr = (int*)malloc (arr_size * sizeof(int));
//convert the number into arr array by placing the first index with the last trailing digit on the right
for (int i = 0; i < arr_size; i++){
arr[i] = x % 10;
x /= 10;
}
//Adding all values in the array into a number
//starting from the first index of the array which has the value of the last digit of the number
for (int i = 0; i < arr_size; i++){
final_reverse_num *= 10;
final_reverse_num += arr[i];
}
free(arr);
return final_reverse_num;
}
//Check the number is palindrome or not by comparing the original num and reverse num
bool is_palindrome(int original_num, int reverse_num){
int x = original_num;
int y = reverse_num;
if(x == y)
return 1;
else
return 0;
}
//Count number of digits in a number in order to declare the buffer size
int count_digit_num(int product_digits){
int y = product_digits;
int digits_count = 0;
while(y!=0){
y /= 10;
++digits_count;
}return digits_count;
}
//Find all possible products from two ndigits(2 digits, 3 digits, 4 digits) number
// Examples: 1 digits: 1*2. 2 digits: 12*13. 3 digits: 100 * 999
int find_largest_palindrome(int ndigits){
int min = 1;
int max;
int smallest_num;
int largest_num = 0;
int product = 0;
//Finding the minima. 1 digit = 1; 2 digits = 10; 3 digits = 100
smallest_num = min * pow(10, ndigits-1);
//Finding the maxima. 1 digits = 9; 2 digits = 99; 3 digits = 999
for (int i = 0; i < ndigits; i++){
max = 9 * pow(10, i);
largest_num += max;
}
//All possible products from minima and maxima
for (int x = largest_num; x >= smallest_num; x--){
for (int y = largest_num; y >= smallest_num; y--){
product = x * y;
}
}
return product;
}
int main(){
return 0;
}

Related

How to convert each number in a num String to an int in C

I've been trying to do this problem on Project Euler
This is what I've done so far -
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
char nums[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
int64_t sum = 1, new_sum = 0;
int num;
for(int i = 0; i < 988; i+= 13){
sum = 1
for(int j = 0; j < 13; ++j){
//Converting nums[i] to int and storing it to num here
sum *= num;
}
if(sum > new_sum){
new_sum = sum;
}
}
printf("%lld", new_sum);
}
I don't know how to convert each charNum in the String to an integer, I've tried atoi and sscanf and both of them ask for a char pointer.
I get these errors respectively
passing argument to parameter here
int atoi(const char *); //sum *= atoi(nums[i])
format specifies type 'int *' but the argument has type 'int' [-Wformat]
sscanf(nums[i], "%d", num);
Any help is appreciated.
Just converting a character representing a digit to the digit itself is simply done by
int digit = nums[position] - '0';
C language guarantees for any character set that the digits 0-9 are succeeding one another in exactly that order (which is not necessarily the case for alphabetic characters, see e.g. (in-?) famous EBCDIC).
As I read the problem the maximum can be at any location, not only multiples of 13. For this speaks as well that the maximum of four subsequent digits is found at a location where the number of digits preceding is not a multiple of four.
Apart from, unless the number if digits is a multiple of 13, your loops would exceed array bounds of nums, so undefined behaviour (if not a multiple of 13, then for last iteration of i there are less than 13 digits left, but j still tries to iterate over all 13 digits).
Fixing both:
size_t sequenceLength = 13; // could be a function parameter
size_t len = strlen(nums); // sizeof would include the terminating 0 character!
if(len < sequenceLength)
{
return 0; // if within a function, else whatever appropriate error handling
}
uint64_t max = 1; // can't have negative values anyway...
for(size_t i = 0; i < sequenceLength; ++i)
{
max *= nums[i] - '0'; // see above
}
// now we found first possible maximum: the product of first 13 digits
uint64_t num = max;
for(size_t i = sequenceLength; i < len; ++i)
{
// for next product, we have already included the first 12 digits
// within the previous product!
// but there is one surplus digit contained we need to eliminate:
num /= nums[i - sequenceLength] - '0';
// now we can include the yet missing one:
num *= nums[i] - '0';
// or as a one-liner:
num = num / (nums[i - sequenceLength] - '0') * (nums[i] - '0');
// TODO: update maximum, if need be, just as in your code
}
Would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#define N 13
int main() {
char nums[] = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int64_t prod = 1, max_prod = 0;
int num;
int pos;
for (int i = 0; i < sizeof nums; i += N) {
prod = 1;
for (int j = 0; j < N; j++){
// Converting nums[i] to int and storing it to num here
num = nums[i + j] - '0';
prod *= num;
}
if (prod > max_prod) {
max_prod = prod;
pos = i;
}
}
printf("max product = %ld at %.*s\n", max_prod, N, nums + pos);
}
Output:
max product = 6270566400 at 4355766896648
BTW as the variable name sum is misleading, I've changed it to prod for product.
I assume that you want a nuber for each digit (i.e., range 0 to 9)
If yes, the below code should be not too far from what you need:
char nums[] = "73167176531330624919225119674426574742355349194934969835203... (so long)...";
char *p;
long lTheTotalCount, lTheNumber;
lTheTotalCount = 0;
for (p=nums ; *p ; p++) {
lTheNumber = (long)(*p - '0');
lTheTotalCount += lTheNumber;
};

Counting and deleting repeated digits of array elements

I need to write a program that allows user to enter an array of integers, finds the digit that appears most often in all entered numbers, and removes it from the elements of the array. If several digits appear the same number of times, the smallest of them should be deleted. If all digits of the element of the array are deleted, that element should become zero. In the end, such a modified array is printed.
Example of input and output:
Enter number of elements of the array: 5
Enter the array: 3833 8818 23 33 1288
After deleting, the array is: 8 8818 2 0 1288
Explanation: The numbers 3 and 8 appear the same number of times (6 times each), but 3 is less, so it was removed it from all members of the array. Element 33 consists exclusively of the digits 3, so that it becomes 0.
#include <stdio.h>
int main() {
int i,n,arr[100]; n;
printf("Enter number of elements of the array: ");
scanf("%d", &n);
printf("Enter the array: ");
for(i=0;i<n;i++) {
scanf("%d", &arr[i]);
}
return 0;
}
EDIT: I'm beginner to programming, and this task should be done using only knowledge learned so far in my course which is conditionals, loops, and arrays. This shouldn't be done with strings.
Divide the problem into separate tasks.
Write the code
In the code below I do not treat 0 as having digit 0. It is because it is not possible to remove 0 from 0. You can easily change this behaviour by changing while(){} loop to do{}while()
int removeDigit(int val, int digit)
{
int result = 0;
unsigned mul = 1;
int sign = val < 0 ? -1 : 1;
digit %= 10;
while(val)
{
int dg = abs(val % 10);
if(dg != digit)
{
result += dg * mul;
mul *= 10;
}
val /= 10;
}
return sign * result;
}
void countDigits(int val, size_t *freq)
{
while(val)
{
freq[abs(val % 10)]++;
val /= 10;
}
}
int findMostFrequent(const size_t *freq)
{
size_t max = 0;
for(size_t i = 1; i < 10; i++)
{
if(freq[i] > freq[max]) max = i;
}
return (int)max;
}
int main(void)
{
int table[20];
size_t freq[10] = {0,};
int mostfreq = 0;
srand(time(NULL));
for(size_t i = 0; i < 20; i++)
{
table[i] = rand();
printf("Table[%zu] = %d\n", i, table[i]);
countDigits(table[i], freq);
}
mostfreq = findMostFrequent(freq);
printf("Most frequent digit: %d\n", mostfreq);
for(size_t i = 0; i < 20; i++)
{
table[i] = removeDigit(table[i], mostfreq);
printf("Table[%zu] = %d\n", i, table[i]);
}
}
https://godbolt.org/z/PPj9s341b

for loop unexpectedly jumping down in value

Goldbach's conjecture states that every even integer over 4 is the sum of two primes, I am writing a program in C to find these pairs. To do this it first finds all the primes less than a user given number. I have a for loop to iterate from 4 to the user given number and find the pairs within the loop body. When that loop gets to about around 40, suddenly jumps back down by about 30 and then continues to iterate up (with user input 50 it jumped from 38 to 9, with input 60 it jumped from 42 to 7). I can't figure out why this is happening. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>
struct pair{
int a;
int b;
}pair_t;
int main(){
int N;
int numPrimes = 1;
int *primes = malloc(100*sizeof(int));
int isPrime = 1;
primes[0] = 2;
int timesRealloc = 0;
int availableSlots = 100;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
struct pair pairs[N/2 + 4];
int j = 0;
int i;
for (i = 3; i <= N; i+=2){
j = 0;
isPrime = 1;
while (primes[j] <= sqrt(i)) {
if (i%primes[j] == 0) {
isPrime = 0;
break;
}
j++;
}
if (isPrime == 1){
primes[numPrimes] = i;
numPrimes++;
}
if (availableSlots == numPrimes){
timesRealloc++;
availableSlots += 100;
primes = realloc(primes, availableSlots*sizeof(int));
}
}
printf("The largest prime I found was %d\n", primes[(numPrimes-1)]);
int k;
for (i=4; i<=N; i+=2){
printf("i is %d, N is %d\n", i, N);
if (i > N){ break; }
for (j=0; j<numPrimes; j++){
for (k=0; k<numPrimes; k++){
int sum = primes[j] + primes[k];
if(sum == i){
pairs[i].a = primes[j];
pairs[i].b = primes[k];
}
}
}
}
for (i=4; i<=N; i+=2){
printf("%d is the sum of %d and %d\n", i, pairs[i].a, pairs[i].b);
}
return 0;
}
You attempt to be space efficient by compressing the pairs array to just hold every other (even) number and start from 4 instead of zero. However, you miscalculate its size and then when you go to use it, you treat it like it hasn't been compressed and that there's a slot for every natural number.
The code suffers from having the prime array calculation in main() along with the other code, this is best separated out. And when it looks for pairs, it doesn't quit when it finds one, nor when it starts getting sums greater than the target. My rework below attempts to address all of these issues:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define INITIAL_SLOTS (100)
struct pair {
int a;
int b;
} pair_t;
int compute_primes(int limit, unsigned **primes, int size) {
int numPrimes = 0;
(*primes)[numPrimes++] = 2;
for (int i = 3; i <= limit; i += 2) {
bool isPrime = true;
for (int j = 0; (*primes)[j] <= i / (*primes)[j]; j++) {
if (i % (*primes)[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
(*primes)[numPrimes++] = i;
}
if (numPrimes == size) {
size *= 2;
*primes = realloc(*primes, size * sizeof(unsigned));
}
}
return numPrimes;
}
int main() {
int N;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
unsigned *primes = calloc(INITIAL_SLOTS, sizeof(unsigned));
int numPrimes = compute_primes(N, &primes, INITIAL_SLOTS);
printf("The largest prime I found was %d\n", primes[numPrimes - 1]);
struct pair pairs[(N - 4) / 2 + 1]; // compressed data structure
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
bool found = false;
for (int j = 0; ! found && j < numPrimes; j++) {
for (int k = 0; ! found && k < numPrimes; k++) {
int sum = primes[j] + primes[k];
if (sum == i) {
pairs[offset].a = primes[j];
pairs[offset].b = primes[k];
found = true;
} else if (sum > i) {
break;
}
}
}
}
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
printf("%d is the sum of %d and %d\n", i, pairs[offset].a, pairs[offset].b);
}
free(primes);
return 0;
}
OUTPUT
> ./a.out
Please enter the largest even number you want to find the Goldbach pair for:
10000
The largest prime I found was 9973
4 is the sum of 2 and 2
6 is the sum of 3 and 3
8 is the sum of 3 and 5
10 is the sum of 3 and 7
12 is the sum of 5 and 7
14 is the sum of 3 and 11
...
9990 is the sum of 17 and 9973
9992 is the sum of 19 and 9973
9994 is the sum of 53 and 9941
9996 is the sum of 23 and 9973
9998 is the sum of 31 and 9967
10000 is the sum of 59 and 9941
>

is this program correct to calculate the sum of 5 digits

Program to calculate the sum of five digits
This program is showing error in the compiler even though I think its factually correct
#include<stdio.h>
int main()
{
int i,a,num=32765,n;
int sum=0;
a=num%10;
n=num/10;
sum=sum+a;
for(i=0;i>4;i++)
{
a=n%10;
n=n/10;
sum=sum+a;
}
printf("the sum of five digits is %d", sum);
}
The loop in your code is never entered because i=0 and then you check if i>=3 which is never true.
You could use something like this:
int digit_sum(int num){
int sum=0;
while (num !=0){
sum += num%10;
num = num/10;
}
return sum;
}
int main()
{
int num = 12346;
/*
if (num <0) // add this block if negative number is posible
num = -num; // and its ok to change num or use some temp instead
*/
int sum = digit_sum(num);
printf("the sum of five digits is %d",sum);
return 0;
}
Or use recursion:
int digit_sum(int num){
if (num)
return num%10 + digit_sum(num/10);
}
Your loop is never entered because i=0 and cant be greater then 3!!! so the solution is:
int number=12345;
int total=0;
int remainder=0;
while(number>0){
remainder=number%10;
total=total+remainder;
number=number/10;
}
Your code is almost correct, just needed correct loop condition. Added comments so that you can see what is going on:
#include <stdio.h>
int main()
{
int i, a, num = 32765, n;
int sum = 0;
// extract 1st digit
a = num % 10; // a is 5 (% returns the remainder of the division)
n = num / 10; // n is 3276 (should be 3276.5, but int eats 0.5)
sum = sum + a; // sum is 5 which is (0 + 5)
// extract the remaining 4 digits
for (i = 0; i < 4; i++) // i is 0, 1, 2, 3
{
a = n % 10; // a is 6, 7, 2, 3
n = n / 10; // n is 327, 32, 3, 0
sum = sum + a; // sum is 11, 18, 20, 23
}
printf("the sum of five digits is %d", sum);
return 0;
}
https://ideone.com/EI9tgM

How to improve execution time when calculating prime factors

I have to make a program to find the largest way to show a n! number (excluding the 1).
for example: 4! = 1x2x3x4 = 1x2x3x2x2. so you can use the product of 5 numbers to show the 4!.
so the imput is 4 and the output is 5.
5 is the max amount of numbers with which you can express the 4!.
In simple words is factorize a factorial number in prime factors, count how many they are and show it.
What I did was a 'for' cycle where I count all the prime factors of 1 to 'n' and amount of them.
But I have a problem with big numbers like when 'n' is 100000, it takes 8 seconds to complete. I need to improve the speed.
I think the problem is in the factorization function.
int factors( int fact )
{
int i,cont,product=1, control;
cont=0;
control=fact;
for (i= 2;control != product;)
{
if ((fact%i == 0))
{
cont++;
fact/=i;
product*=i;}
else
i++;
}
return cont;
}
I need to improve it to get a best execution time. Or maybe the method that i'm using to get the prime factors from a factorial number isn't a good option?
NOTE: I do not calculate the value of 100000!. I just factorize all the numbers from 1 to 10000 and count them.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int *prime;
int prime_n;
void make_prime_table(int n){
prime = malloc(sizeof(int) * n / 2);
prime_n =0;
prime[prime_n++] = 2;
prime[prime_n++] = 3;
int i, j;
for(i = 5; i <= n; i +=2){
bool is_prime = true;
for(j = 1; j < prime_n ; ++j){
int t = prime[j];
if(t * t > i)
break;
if(i % t == 0){
is_prime = false;
break;
}
}
if(is_prime)
prime[prime_n++] = i;
}
}
int factors(int fact_n ){
int i, c, p, sum=0;
for(i = 0; i < prime_n ; ++i){
c = fact_n;//number of prime in N : (x1 = N / P) + (x2 = x1 / P) + ...
while(c = c / prime[i]){
sum += c;
}
}
return sum;
}
int main(void){
int n = 100000;
make_prime_table(n);
int ans = factors(n);
printf("ans = %d\n", ans);
free(prime);
return 0;
}
number of prime P in N! :
case of 2 in 10!
1 2 3 4 5 6 7 8 9 10
* * * * * # There are 5 number that is divided by 2. 5 = 10 / 2
* * # Number that can be divided further part of the mark of `*`(5/2).
* # The number of total is the number of `*`.
*search "theorem of Legendre"

Resources