Improve solution for problem 43

This commit is contained in:
daniele 2019-09-26 10:23:01 +02:00
parent 80719a58f8
commit a82d270691
Signed by: fuxino
GPG Key ID: 6FE25B4A3EE16FDA
3 changed files with 115 additions and 51 deletions

104
C/p043.c
View File

@ -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)
{ {

View File

@ -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)

View File

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