Improve solution for problem 43
This commit is contained in:
parent
80719a58f8
commit
a82d270691
104
C/p043.c
104
C/p043.c
@ -1,22 +1,62 @@
|
|||||||
|
/* The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a
|
||||||
|
* rather interesting sub-string divisibility property.
|
||||||
|
*
|
||||||
|
* Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note the following:
|
||||||
|
*
|
||||||
|
* d2d3d4=406 is divisible by 2
|
||||||
|
* d3d4d5=063 is divisible by 3
|
||||||
|
* d4d5d6=635 is divisible by 5
|
||||||
|
* d5d6d7=357 is divisible by 7
|
||||||
|
* d6d7d8=572 is divisible by 11
|
||||||
|
* d7d8d9=728 is divisible by 13
|
||||||
|
* d8d9d10=289 is divisible by 17
|
||||||
|
*
|
||||||
|
* Find the sum of all 0 to 9 pandigital numbers with this property.*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "projecteuler.h"
|
||||||
|
|
||||||
void permute(int *v, int i, int n);
|
int compare(void *a, void *b);
|
||||||
void swap(int *a, int *b);
|
int has_property(int **n);
|
||||||
int has_property(int *v);
|
|
||||||
|
|
||||||
long int sum = 0;
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int n[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
int i;
|
||||||
|
int **n;
|
||||||
|
long int sum = 0;
|
||||||
double elapsed;
|
double elapsed;
|
||||||
struct timespec start, end;
|
struct timespec start, end;
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
|
|
||||||
permute(n, 0, 9);
|
if((n = (int **)malloc(10*sizeof(int *))) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error while allocating memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
if((n[i] = (int *)malloc(sizeof(int))) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error while allocating memory\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*n[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the next permutation and check if it has the required property.
|
||||||
|
* Repeat until all the permutations have been found.*/
|
||||||
|
while(next_permutation((void **)n, 10, compare) != -1)
|
||||||
|
{
|
||||||
|
if(has_property(n))
|
||||||
|
{
|
||||||
|
sum += *n[0] * 1e9 + *n[1] * 1e8 + *n[2] * 1e7 + *n[3] * 1e6 + *n[4] * 1e5 +
|
||||||
|
*n[5] * 1e4 + *n[6] * 1e3 + *n[7] * 1e2 + *n[8] * 1e1 + *n[9];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &end);
|
clock_gettime(CLOCK_MONOTONIC, &end);
|
||||||
|
|
||||||
@ -30,84 +70,64 @@ int main(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void permute(int *v, int i, int n)
|
int compare(void *a, void *b)
|
||||||
{
|
{
|
||||||
int j;
|
int *n1, *n2;
|
||||||
|
|
||||||
if(i == n)
|
n1 = (int *)a;
|
||||||
{
|
n2 = (int *)b;
|
||||||
if(has_property(v))
|
|
||||||
{
|
return *n1 - *n2;
|
||||||
sum += v[0] * 1e9 + v[1] * 1e8 + v[2] * 1e7 + v[3] * 1e6 + v[4] * 1e5 + v[5] * 1e4 + v[6] * 1e3 + v[7] * 1e2 + v[8] * 1e1 + v[9];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(j = i; j <= n; j++)
|
|
||||||
{
|
|
||||||
swap((v+i), (v+j));
|
|
||||||
permute(v, i+1, n);
|
|
||||||
swap((v+i), (v+j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void swap(int *a, int *b)
|
/* Function to check if the value has the desired property.*/
|
||||||
{
|
int has_property(int **n)
|
||||||
int tmp;
|
|
||||||
|
|
||||||
tmp = *a;
|
|
||||||
*a = *b;
|
|
||||||
*b = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int has_property(int *v)
|
|
||||||
{
|
{
|
||||||
long int value;
|
long int value;
|
||||||
|
|
||||||
value = v[1] * 100 + v[2] * 10 + v[3];
|
value = *n[1] * 100 + *n[2] * 10 + *n[3];
|
||||||
|
|
||||||
if(value % 2 != 0)
|
if(value % 2 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[2] * 100 + v[3] * 10 + v[4];
|
value = *n[2] * 100 + *n[3] * 10 + *n[4];
|
||||||
|
|
||||||
if(value % 3 != 0)
|
if(value % 3 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[3] * 100 + v[4] * 10 + v[5];
|
value = *n[3] * 100 + *n[4] * 10 + *n[5];
|
||||||
|
|
||||||
if(value % 5 != 0)
|
if(value % 5 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[4] * 100 + v[5] * 10 + v[6];
|
value = *n[4] * 100 + *n[5] * 10 + *n[6];
|
||||||
|
|
||||||
if(value % 7 != 0)
|
if(value % 7 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[5] * 100 + v[6] * 10 + v[7];
|
value = *n[5] * 100 + *n[6] * 10 + *n[7];
|
||||||
|
|
||||||
if(value % 11 != 0)
|
if(value % 11 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[6] * 100 + v[7] * 10 + v[8];
|
value = *n[6] * 100 + *n[7] * 10 + *n[8];
|
||||||
|
|
||||||
if(value %13 != 0)
|
if(value %13 != 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = v[7] * 100 + v[8] * 10 + v[9];
|
value = *n[7] * 100 + *n[8] * 10 + *n[9];
|
||||||
|
|
||||||
if(value % 17 != 0)
|
if(value % 17 != 0)
|
||||||
{
|
{
|
||||||
|
@ -266,6 +266,15 @@ int sum_of_divisors(int n)
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void swap(void **array, int i, int j)
|
||||||
|
{
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
tmp = array[i];
|
||||||
|
array[i] = array[j];
|
||||||
|
array[j] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv))
|
void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv))
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
@ -276,9 +285,7 @@ void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv))
|
|||||||
{
|
{
|
||||||
if(cmp(array[i], array[i-1]) < 0)
|
if(cmp(array[i], array[i-1]) < 0)
|
||||||
{
|
{
|
||||||
tmp = array[i];
|
swap(array, i, i-1);
|
||||||
array[i] = array[i-1];
|
|
||||||
array[i-1] = tmp;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,17 +336,13 @@ int partition(void **array, int l, int r, int (*cmp)(void *lv, void *rv))
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If j>i, swap array[i] and array[j].*/
|
/* If j>i, swap array[i] and array[j].*/
|
||||||
tmp = array[i];
|
swap(array, i, j);
|
||||||
array[i] = array[j];
|
|
||||||
array[j] = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap array[i] with pivot. All elements on the left of pivot are smaller, all
|
/* Swap array[i] with pivot. All elements on the left of pivot are smaller, all
|
||||||
* the elements on the right are bigger, so pivot is in the correct position
|
* the elements on the right are bigger, so pivot is in the correct position
|
||||||
* in the sorted array.*/
|
* in the sorted array.*/
|
||||||
tmp = array[i];
|
swap(array, i, r);
|
||||||
array[i] = array[r];
|
|
||||||
array[r] = tmp;
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -361,6 +364,43 @@ void quick_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv))
|
|||||||
quick_sort(array, i+1, r, cmp);
|
quick_sort(array, i+1, r, cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implements SEPA (Simple, Efficient Permutation Algorithm)
|
||||||
|
* to find the next permutation.*/
|
||||||
|
int next_permutation(void **perm, int n, int (*cmp)(void *a, void *b))
|
||||||
|
{
|
||||||
|
int i, key;
|
||||||
|
|
||||||
|
/* Starting from the right of the array, for each pair of values
|
||||||
|
* if the left one is smaller than the right, that value is the key.*/
|
||||||
|
for(i = n - 2; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(cmp(perm[i], perm[i+1]) < 0)
|
||||||
|
{
|
||||||
|
key = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If no left value is smaller than its right value, the
|
||||||
|
* array is in reverse order, i.e. it's the last permutation.*/
|
||||||
|
if(i == -1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the smallest value on the right of the key which is bigger than the key itself,
|
||||||
|
* considering that the values at the right of the key are in reverse order.*/
|
||||||
|
for(i = key + 1; i < n && cmp(perm[i], perm[key]) > 0; i++);
|
||||||
|
|
||||||
|
/* Swap the value found and the key.*/
|
||||||
|
swap(perm, key, i-1);
|
||||||
|
/* Sort the values at the right of the key. This is
|
||||||
|
* the next permutation.*/
|
||||||
|
insertion_sort(perm, key+1, n-1, cmp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int is_pandigital(int value, int n)
|
int is_pandigital(int value, int n)
|
||||||
{
|
{
|
||||||
int *digits;
|
int *digits;
|
||||||
@ -413,6 +453,8 @@ int is_pentagonal(long int n)
|
|||||||
{
|
{
|
||||||
double i;
|
double i;
|
||||||
|
|
||||||
|
/* A number n is pentagonal if p=(sqrt(24n+1)+1)/6 is an integer.
|
||||||
|
* In this case, n is the pth pentagonal number.*/
|
||||||
i = (sqrt(24*n+1) + 1) / 6;
|
i = (sqrt(24*n+1) + 1) / 6;
|
||||||
|
|
||||||
if(i == (int)i)
|
if(i == (int)i)
|
||||||
|
@ -13,8 +13,10 @@ int *sieve(int n);
|
|||||||
int count_divisors(int n);
|
int count_divisors(int n);
|
||||||
int find_max_path(int **triang, int n);
|
int find_max_path(int **triang, int n);
|
||||||
int sum_of_divisors(int n);
|
int sum_of_divisors(int n);
|
||||||
|
void swap(void **vet, int i, int j);
|
||||||
void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv));
|
void insertion_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv));
|
||||||
void quick_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv));
|
void quick_sort(void **array, int l, int r, int (*cmp)(void *lv, void *rv));
|
||||||
|
int next_permutation(void **perm, int n, int (*cmp)(void *a, void *b));
|
||||||
int is_pandigital(int value, int n);
|
int is_pandigital(int value, int n);
|
||||||
int is_pentagonal(long int n);
|
int is_pentagonal(long int n);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user