mirror of
https://github.moeyy.xyz/https://github.com/TheAlgorithms/C.git
synced 2023-10-11 15:56:24 +08:00
Merge branch 'project_euler/master2'
* project_euler/master2: (26 commits) solution using arbitrary number of digits took 11ms algorithm by Dijkstra updating DIRECTORY.md move time computation inside loop + comments faster parallleization time computation inside the loop & print loop info added comments sol1 optimized by storing abundant numbers in a condensed array brute-force - compute abundant numbers every time added source text file updating DIRECTORY.md sort using both lazy sort and shell-sort add stats for algo 2 and use milliseconds create a duplicate array added new shell-sort algorithm updating DIRECTORY.md speed optimized solution + optional OpenMP added computational time added additional summary updating DIRECTORY.md ...
This commit is contained in:
commit
22bb478c07
11
DIRECTORY.md
11
DIRECTORY.md
@ -243,6 +243,17 @@
|
|||||||
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2015/sol1.c)
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2015/sol1.c)
|
||||||
* Problem 16
|
* Problem 16
|
||||||
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2016/sol1.c)
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2016/sol1.c)
|
||||||
|
* Problem 20
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2020/sol1.c)
|
||||||
|
* Problem 19
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2019/sol1.c)
|
||||||
|
* Problem 21
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2021/sol1.c)
|
||||||
|
* Problem 22
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2022/sol1.c)
|
||||||
|
* Problem 23
|
||||||
|
* [Sol1](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2023/sol1.c)
|
||||||
|
* [Sol2](https://github.com/TheAlgorithms/C/blob/master/project_euler/Problem%2023/sol2.c)
|
||||||
|
|
||||||
## Searching
|
## Searching
|
||||||
* [Binary Search](https://github.com/TheAlgorithms/C/blob/master/searching/Binary_Search.c)
|
* [Binary Search](https://github.com/TheAlgorithms/C/blob/master/searching/Binary_Search.c)
|
||||||
|
120
project_euler/Problem 19/sol1.c
Normal file
120
project_euler/Problem 19/sol1.c
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns number of days in a month.
|
||||||
|
* Month is identified by an integer -
|
||||||
|
* 0 = Jan and 11 = December
|
||||||
|
* For February, adjust for leap year outside the function.
|
||||||
|
**/
|
||||||
|
char get_month_days(short month)
|
||||||
|
{
|
||||||
|
if (month == 1) /* February has 28 days. Adjust leap year in the loop */
|
||||||
|
return 28;
|
||||||
|
else if (month <= 6) /* odd months till July have 30 days - Jan = 0 (even)*/
|
||||||
|
{
|
||||||
|
if (month & 0x01)
|
||||||
|
return 30;
|
||||||
|
else
|
||||||
|
return 31;
|
||||||
|
} else if (month >= 7) /* odd months after July have 31 days*/
|
||||||
|
{
|
||||||
|
if (month & 0x01)
|
||||||
|
return 31;
|
||||||
|
else
|
||||||
|
return 30;
|
||||||
|
}
|
||||||
|
/* should never reach here! */
|
||||||
|
perror("Should never have reached this point!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return 1 if input year is a leap year
|
||||||
|
* otherwise, return 0
|
||||||
|
**/
|
||||||
|
char is_leap_year(short year)
|
||||||
|
{
|
||||||
|
if ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
const char* day_string(int day)
|
||||||
|
{
|
||||||
|
switch(day)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return "Sunday";
|
||||||
|
case 1:
|
||||||
|
return "Monday";
|
||||||
|
case 2:
|
||||||
|
return "Tuesday";
|
||||||
|
case 3:
|
||||||
|
return "Wednesday";
|
||||||
|
case 4:
|
||||||
|
return "Thursday";
|
||||||
|
case 5:
|
||||||
|
return "Friday";
|
||||||
|
case 6:
|
||||||
|
return "Saturday";
|
||||||
|
default:
|
||||||
|
return "Shouldnt see this!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int count_sundays = 0;
|
||||||
|
const short start_year = 1901;
|
||||||
|
const short end_year = 2000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let us identify days i.e., Sunday thru Saturday with integers - 0 thru 6 respectively
|
||||||
|
* Jan 1 1901 was a Tuesday
|
||||||
|
**/
|
||||||
|
char start_day = 2;
|
||||||
|
|
||||||
|
for (int year = start_year; year <= end_year; year++)
|
||||||
|
{
|
||||||
|
char is_leap = is_leap_year(year);
|
||||||
|
for (char month = 0; month < 12; month ++)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* These two for-loops count the start of day for the next month. Hence,
|
||||||
|
* we have to skip the last December count */
|
||||||
|
if (year == end_year && month == 11)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int days = get_month_days(month);
|
||||||
|
|
||||||
|
if (is_leap && month == 1) /* for a leap year february, add a day */
|
||||||
|
days ++;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (year == end_year)
|
||||||
|
{
|
||||||
|
printf("Year: %d\t Month: %d\t Days: %d\t First of day: %s\n", year, month, days, day_string(start_day));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Main Algorithm:
|
||||||
|
* every week has 7 days hence, the start of next day would be modulo 7
|
||||||
|
* add to this, the current start date and ensure the result is still
|
||||||
|
* modulo 7!
|
||||||
|
**/
|
||||||
|
start_day = ((days % 7) + start_day) % 7;
|
||||||
|
|
||||||
|
/* If start-day is a Sunday, increment counter */
|
||||||
|
if (start_day == 0)
|
||||||
|
count_sundays ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Total number of Sundays that happened on the 1st of a month in the last century: %d\n", count_sundays);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
170
project_euler/Problem 20/sol1.c
Normal file
170
project_euler/Problem 20/sol1.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* store arbitratily large integer values
|
||||||
|
* as a linked list of digits.
|
||||||
|
**/
|
||||||
|
typedef struct _big_int
|
||||||
|
{
|
||||||
|
char value; /** tens place (single digit) */
|
||||||
|
struct _big_int *next_digit; /** hundreds place */
|
||||||
|
struct _big_int *prev_digit; /** units place */
|
||||||
|
} big_int;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void print_digit(const big_int *my_int)
|
||||||
|
{
|
||||||
|
printf("\tValue : %d\n\tNext : %p\n\tPrev : %p\n", my_int->value, my_int->next_digit, my_int->prev_digit);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that allocates memory to add another
|
||||||
|
* digit at the MSB
|
||||||
|
**/
|
||||||
|
big_int *add_digit(big_int *digit, char value)
|
||||||
|
{
|
||||||
|
if (digit == NULL)
|
||||||
|
{
|
||||||
|
digit = (big_int *)malloc(sizeof(big_int));
|
||||||
|
if (!digit)
|
||||||
|
{
|
||||||
|
perror("Unable to allocate memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
digit->value = value;
|
||||||
|
digit->next_digit = NULL;
|
||||||
|
digit->prev_digit = NULL;
|
||||||
|
|
||||||
|
return digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digit->next_digit)
|
||||||
|
{
|
||||||
|
digit->next_digit->value = value;
|
||||||
|
return digit->next_digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit->next_digit = (big_int *)malloc(sizeof(big_int));
|
||||||
|
if (digit->next_digit == NULL)
|
||||||
|
{
|
||||||
|
perror("Unable to allocate memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
digit->next_digit->value = value;
|
||||||
|
digit->next_digit->next_digit = NULL;
|
||||||
|
digit->next_digit->prev_digit = digit;
|
||||||
|
return digit->next_digit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to remove digits preceeding the
|
||||||
|
* current digit.
|
||||||
|
**/
|
||||||
|
char remove_digits(big_int *digit, int N)
|
||||||
|
{
|
||||||
|
if (digit == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (digit->next_digit == NULL)
|
||||||
|
{
|
||||||
|
free(digit);
|
||||||
|
digit = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (N > 0)
|
||||||
|
return remove_digits(digit->next_digit, N - 1);
|
||||||
|
|
||||||
|
return remove_digits(digit->next_digit, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned int N = 5;
|
||||||
|
big_int *ptr = add_digit(NULL, 1); /* start with 1 */
|
||||||
|
const big_int *ptr0 = ptr; /* save the first location */
|
||||||
|
unsigned long sum_digits = 0;
|
||||||
|
unsigned long num_digits = 0;
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
N = atoi(argv[1]);
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i <= N; i++)
|
||||||
|
{
|
||||||
|
int carry = 0;
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("%3d: ", i);
|
||||||
|
#endif
|
||||||
|
ptr = (big_int *)ptr0; /* multiply every digit with i */
|
||||||
|
while (ptr)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("%p\t", ptr);
|
||||||
|
#endif
|
||||||
|
unsigned int tmp = ptr->value * i + carry;
|
||||||
|
if (tmp >= 10)
|
||||||
|
{
|
||||||
|
div_t tmp2 = div(tmp, 10);
|
||||||
|
carry = tmp2.quot;
|
||||||
|
tmp = tmp2.rem;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
carry = 0;
|
||||||
|
|
||||||
|
if (carry > 0 && ptr->next_digit == NULL)
|
||||||
|
add_digit(ptr, 0);
|
||||||
|
|
||||||
|
ptr->value = tmp;
|
||||||
|
|
||||||
|
if (i == N)
|
||||||
|
/**
|
||||||
|
* sum digits on the last iteration
|
||||||
|
* this avoid having another loop over all digits
|
||||||
|
**/
|
||||||
|
sum_digits += tmp;
|
||||||
|
|
||||||
|
if (ptr->next_digit)
|
||||||
|
/* more digits available */
|
||||||
|
ptr = ptr->next_digit;
|
||||||
|
else
|
||||||
|
/* no more digits left - reached MSB */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t end_time = clock();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("ptr = %p\n", ptr);
|
||||||
|
printf("%d! = ", N);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Notice that in the loop above, we make sure that at the end of the loop,
|
||||||
|
* ptr is pointing to the last digit. Thus we can avoid using another loop.
|
||||||
|
**/
|
||||||
|
// ptr = &my_int;
|
||||||
|
// /* move ptr to the MSB digit */
|
||||||
|
// while (ptr->next_digit)
|
||||||
|
// ptr = ptr->next_digit;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
putchar(ptr->value + 0x30); /* convert digit to ASCII char */
|
||||||
|
ptr = ptr->prev_digit;
|
||||||
|
num_digits++;
|
||||||
|
} while (ptr); /* after coming to units place, there will be no valid ptr */
|
||||||
|
|
||||||
|
printf("\nTime taken: %.4g millisecond\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Digit Sum = %lu\tNumber of digits = %lu\tStorage space = %.3gkb\t \n",
|
||||||
|
sum_digits, num_digits, num_digits * sizeof(big_int) / 1024.0);
|
||||||
|
|
||||||
|
remove_digits((big_int *)ptr0, -1);
|
||||||
|
return 0;
|
||||||
|
}
|
98
project_euler/Problem 21/sol1.c
Normal file
98
project_euler/Problem 21/sol1.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function to return the sum of proper divisors of N
|
||||||
|
**/
|
||||||
|
unsigned int sum_of_divisors(unsigned int N)
|
||||||
|
{
|
||||||
|
unsigned int sum = 1; /* 1 is always a divisor */
|
||||||
|
|
||||||
|
/* divisors are symmertically distributed about the square-root */
|
||||||
|
for (unsigned int i = 2; (i * i) <= N; i++)
|
||||||
|
{
|
||||||
|
if (N % i != 0)
|
||||||
|
/* i is not a proper divisor */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// #ifdef DEBUG
|
||||||
|
// printf("%4d, %4d,", i, N / i);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
sum += i;
|
||||||
|
|
||||||
|
if (i * i == N)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sum += N / i;
|
||||||
|
}
|
||||||
|
// #ifdef DEBUG
|
||||||
|
// printf("\nSum of divisors of %4d: %4d\n", N, sum);
|
||||||
|
// #endif
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned long sum = 0;
|
||||||
|
unsigned int MAX_N = 500;
|
||||||
|
if (argc == 2)
|
||||||
|
MAX_N = atoi(argv[1]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We use an array of flags to check if a number at the index was:
|
||||||
|
* not-processed = 0
|
||||||
|
* is amicable = 1
|
||||||
|
* not amicable = -1
|
||||||
|
**/
|
||||||
|
char *flags = (char *)calloc(MAX_N, sizeof(char));
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for schedule(runtime)
|
||||||
|
#endif
|
||||||
|
/* there are no such numbers till 10. Lets search from there on */
|
||||||
|
for (unsigned int i = 10; i < MAX_N; i++)
|
||||||
|
{
|
||||||
|
if (flags[i] != 0)
|
||||||
|
/* already processed, skip */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned int b = sum_of_divisors(i);
|
||||||
|
if (b >= MAX_N)
|
||||||
|
flags[i] = -1;
|
||||||
|
else if (flags[b] == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
unsigned int c = sum_of_divisors(b);
|
||||||
|
if (c == i && b != i)
|
||||||
|
{
|
||||||
|
/* found amicable */
|
||||||
|
flags[b] = 1;
|
||||||
|
flags[i] = 1;
|
||||||
|
sum += b + i;
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("Amicable: %4d : %4d\n", i, b);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
flags[i] = -1;
|
||||||
|
if (b < MAX_N)
|
||||||
|
flags[b] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t end_time = clock();
|
||||||
|
|
||||||
|
printf("\nTime taken: %.4g millisecond\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("Sum of all numbers = %lu\n", sum);
|
||||||
|
|
||||||
|
free(flags);
|
||||||
|
return 0;
|
||||||
|
}
|
1
project_euler/Problem 22/names.txt
Normal file
1
project_euler/Problem 22/names.txt
Normal file
File diff suppressed because one or more lines are too long
138
project_euler/Problem 22/sol1.c
Normal file
138
project_euler/Problem 22/sol1.c
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_NAMES 6000 /* Maximum number of names to store */
|
||||||
|
#define MAX_NAME_LEN 20 /* Maximum length of each name */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alphabetical sorting using 'shell sort' algorithm
|
||||||
|
**/
|
||||||
|
void shell_sort(char data[][MAX_NAME_LEN], int LEN)
|
||||||
|
{
|
||||||
|
const int gaps[] = {701, 301, 132, 57, 23, 10, 4, 1};
|
||||||
|
const int gap_len = 8;
|
||||||
|
int i, j, g;
|
||||||
|
|
||||||
|
for (g = 0; g < gap_len; g++)
|
||||||
|
{
|
||||||
|
int gap = gaps[g];
|
||||||
|
for (i = gap; i < LEN; i++)
|
||||||
|
{
|
||||||
|
char tmp_buffer[MAX_NAME_LEN];
|
||||||
|
strcpy(tmp_buffer, data[i]);
|
||||||
|
|
||||||
|
for (j = i; j >= gap && strcmp(data[j - gap], tmp_buffer) > 0; j -= gap)
|
||||||
|
strcpy(data[j], data[j - gap]);
|
||||||
|
strcpy(data[j], tmp_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (i = 0; i < LEN; i++)
|
||||||
|
printf("%s\t", data[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alphabetical sorting using 'lazy sort' algorithm
|
||||||
|
**/
|
||||||
|
void lazy_sort(char data[][MAX_NAME_LEN], int LEN)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < LEN; i++)
|
||||||
|
{
|
||||||
|
for (j = i + 1; j < LEN; j++)
|
||||||
|
{
|
||||||
|
if (strcmp(data[i], data[j]) > 0)
|
||||||
|
{
|
||||||
|
char tmp_buffer[MAX_NAME_LEN];
|
||||||
|
strcpy(tmp_buffer, data[i]);
|
||||||
|
strcpy(data[i], data[j]);
|
||||||
|
strcpy(data[j], tmp_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (i = 0; i < LEN; i++)
|
||||||
|
printf("%s\t", data[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned long COUNT = 0;
|
||||||
|
char *fname = "names.txt";
|
||||||
|
char names[MAX_NAMES][MAX_NAME_LEN];
|
||||||
|
short method = 0; /* sorting algorithm to use. 0 = lazy, 1 = shell-sort */
|
||||||
|
|
||||||
|
if (argc == 2)
|
||||||
|
method = atoi(argv[1]);
|
||||||
|
|
||||||
|
FILE *fp = fopen(fname, "rt");
|
||||||
|
if (!fp)
|
||||||
|
{
|
||||||
|
perror("Unable to open file");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loops to get total number of rows and columns in the file
|
||||||
|
**/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int ret = fscanf(fp, "\"%[^\",]\",", names[COUNT++]);
|
||||||
|
if (ret <= 0)
|
||||||
|
continue;
|
||||||
|
// printf("%s\t", names[COUNT - 1]);
|
||||||
|
} while (!feof(fp));
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
printf("\nTotal number of names: %lu\n", COUNT);
|
||||||
|
|
||||||
|
if (method == 0)
|
||||||
|
{
|
||||||
|
clock_t start_time = clock();
|
||||||
|
shell_sort(names, COUNT);
|
||||||
|
clock_t end_time = clock();
|
||||||
|
printf("\nShell sort: %.4g millisecond\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
}
|
||||||
|
else if (method == 1)
|
||||||
|
{
|
||||||
|
clock_t start_time = clock();
|
||||||
|
lazy_sort(names, COUNT);
|
||||||
|
clock_t end_time = clock();
|
||||||
|
printf("\nLazy sort: %.4g millisecond\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
long sum_score = 0;
|
||||||
|
clock_t start_time = clock();
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for schedule(runtime) reduction(+ \
|
||||||
|
: sum_score)
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (unsigned int i = 935; i < 940; i++)
|
||||||
|
#else
|
||||||
|
for (unsigned int i = 0; i < COUNT; i++)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
unsigned int score = 0;
|
||||||
|
/* score the alphabets in i^th name */
|
||||||
|
for (int j = 0; names[i][j] != '\0'; j++)
|
||||||
|
score += names[i][j] - 'A' + 1; /* convert ASCII character to integer score */
|
||||||
|
sum_score += score * (i + 1);
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("Name: %s\tScore: %u x %u = %lu\n", names[i], score, i + 1, (unsigned long)score * (i + 1));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
clock_t end_time = clock();
|
||||||
|
printf("Scoring time: %.4g millisecond\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
|
||||||
|
printf("Total Score = %lu\n", sum_score);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
116
project_euler/Problem 23/sol1.c
Normal file
116
project_euler/Problem 23/sol1.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned long MAX_N = 28123;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns:
|
||||||
|
* -1 if N is deficient
|
||||||
|
* 1 if N is abundant
|
||||||
|
* 0 if N is perfect
|
||||||
|
**/
|
||||||
|
char get_perfect_number(unsigned long N)
|
||||||
|
{
|
||||||
|
unsigned long sum = 1;
|
||||||
|
char ret = 0;
|
||||||
|
|
||||||
|
for (unsigned long i = 2; i * i <= N; i++)
|
||||||
|
{
|
||||||
|
if (N % i == 0)
|
||||||
|
{
|
||||||
|
sum += i;
|
||||||
|
unsigned long tmp = N / i;
|
||||||
|
if (tmp != i)
|
||||||
|
sum += tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sum == N ? 0 : (sum > N ? 1 : -1);
|
||||||
|
// #ifdef DEBUG
|
||||||
|
// printf("%5lu: %5lu : %d\n", N, sum, ret);
|
||||||
|
// #endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the given number an abundant number (1) or not (0)
|
||||||
|
**/
|
||||||
|
unsigned long is_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
return get_perfect_number(N) == 1 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the next abundant number after N and not including N
|
||||||
|
**/
|
||||||
|
unsigned long get_next_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
for (i = N + 1; !is_abundant(i); i++)
|
||||||
|
;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a given number can be represented as a sum
|
||||||
|
* of two abundant numbers.
|
||||||
|
* 1 - if yes
|
||||||
|
* 0 - if not
|
||||||
|
**/
|
||||||
|
char is_sum_of_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
/** optimized logic:
|
||||||
|
* i + j = N where both i and j should be abundant
|
||||||
|
* hence we can simply check for j = N - i as we loop through i
|
||||||
|
**/
|
||||||
|
for (unsigned long i = get_next_abundant(1); i <= (N >> 1); i = get_next_abundant(i))
|
||||||
|
if (is_abundant(N - i))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("\t%4lu + %4lu = %4lu\n", i, N - i, N);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned long sum = 0;
|
||||||
|
if (argc == 2)
|
||||||
|
MAX_N = strtoul(argv[1], NULL, 10);
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
printf("Using OpenMP parallleization with %d threads\n", omp_get_max_threads());
|
||||||
|
#else
|
||||||
|
printf("Not using parallleization!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clock_t dt = 0;
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for reduction(+ \
|
||||||
|
: sum) schedule(runtime)
|
||||||
|
#endif
|
||||||
|
for (unsigned long i = 1; i <= MAX_N; i++)
|
||||||
|
{
|
||||||
|
clock_t start_time = clock();
|
||||||
|
if (!is_sum_of_abundant(i))
|
||||||
|
sum += i;
|
||||||
|
clock_t end_time = clock();
|
||||||
|
dt += end_time - start_time;
|
||||||
|
|
||||||
|
printf("... %5lu: %8lu\r", i, sum);
|
||||||
|
if (i % 100 == 0)
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Time taken: %.4g ms\n", 1e3 * dt / CLOCKS_PER_SEC);
|
||||||
|
printf("Sum of numbers that cannot be represented as sum of two abundant numbers : %lu\n", sum);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
180
project_euler/Problem 23/sol2.c
Normal file
180
project_euler/Problem 23/sol2.c
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#include <omp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimization 1 - compute & store abundant numbers once
|
||||||
|
* into a look-up array
|
||||||
|
**/
|
||||||
|
|
||||||
|
unsigned long MAX_N = 28123;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the global array to be used to store a flag to identify
|
||||||
|
* if a particular number is abundant (1) or not (0).
|
||||||
|
* Using a whole byte to store a binary info would be redundant.
|
||||||
|
* We will use each byte to represent 8 numbers by relying on bits.
|
||||||
|
* This saves memory required by 1/8
|
||||||
|
**/
|
||||||
|
char *abundant_flags = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns:
|
||||||
|
* -1 if N is deficient
|
||||||
|
* 1 if N is abundant
|
||||||
|
* 0 if N is perfect
|
||||||
|
**/
|
||||||
|
char get_perfect_number(unsigned long N)
|
||||||
|
{
|
||||||
|
unsigned long sum = 1;
|
||||||
|
char ret = 0;
|
||||||
|
|
||||||
|
for (unsigned long i = 2; i * i <= N; i++)
|
||||||
|
{
|
||||||
|
if (N % i == 0)
|
||||||
|
{
|
||||||
|
sum += i;
|
||||||
|
unsigned long tmp = N / i;
|
||||||
|
if (tmp != i)
|
||||||
|
sum += tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sum == N ? 0 : (sum > N ? 1 : -1);
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("%5lu: %5lu : %d\n", N, sum, ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the given number an abundant number (1) or not (0)
|
||||||
|
**/
|
||||||
|
char is_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
// return abundant_flags[N >> 3] & (1 << N % 8) ? 1 : 0;
|
||||||
|
return abundant_flags[N >> 3] & (1 << (N & 7)) ? 1 : 0; /* optimized modulo operation */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the next abundant number after N and not including N
|
||||||
|
**/
|
||||||
|
unsigned long get_next_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
/* keep checking successive numbers till an abundant number is found */
|
||||||
|
for (i = N + 1; !is_abundant(i); ++i)
|
||||||
|
;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if a given number can be represented as a sum
|
||||||
|
* of two abundant numbers.
|
||||||
|
* 1 - if yes
|
||||||
|
* 0 - if not
|
||||||
|
**/
|
||||||
|
char is_sum_of_abundant(unsigned long N)
|
||||||
|
{
|
||||||
|
/** optimized logic:
|
||||||
|
* i + j = N where both i and j should be abundant
|
||||||
|
* hence we can simply check for j = N - i as we loop through i
|
||||||
|
**/
|
||||||
|
for (unsigned long i = get_next_abundant(1); i <= (N >> 1); i = get_next_abundant(i))
|
||||||
|
if (is_abundant(N - i))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("\t%4lu + %4lu = %4lu\n", i, N - i, N);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
unsigned long sum = 0;
|
||||||
|
if (argc == 2)
|
||||||
|
MAX_N = strtoul(argv[1], NULL, 10);
|
||||||
|
|
||||||
|
/** byte array to store flags to identify abundant numbers
|
||||||
|
* the flags are identified by bits
|
||||||
|
**/
|
||||||
|
abundant_flags = (char *)calloc(MAX_N >> 3, 1);
|
||||||
|
if (!abundant_flags)
|
||||||
|
{
|
||||||
|
perror("Unable to allocate memoey!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
printf("Using OpenMP parallleization with %d threads\n", omp_get_max_threads());
|
||||||
|
#else
|
||||||
|
printf("Not using parallleization!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
|
||||||
|
/* Loop to set abundant flags */
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for schedule(runtime)
|
||||||
|
#endif
|
||||||
|
for (unsigned long N = 1; N <= MAX_N; N++)
|
||||||
|
{
|
||||||
|
char ret = get_perfect_number(N);
|
||||||
|
if (ret == 1)
|
||||||
|
{
|
||||||
|
// int byte_offset = N % 8, index = N >> 3;
|
||||||
|
int byte_offset = N & 7, index = N >> 3;
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp critical
|
||||||
|
#endif
|
||||||
|
abundant_flags[index] |= ret << byte_offset;
|
||||||
|
}
|
||||||
|
// if (i % 100 == 0)
|
||||||
|
// printf("... %5lu: %8lu\r", i, sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_t end_time = clock();
|
||||||
|
double t1 = 1e3 * (end_time - start_time) / CLOCKS_PER_SEC;
|
||||||
|
printf("Time taken to get abundant numbers: %.4g ms\n", t1);
|
||||||
|
|
||||||
|
clock_t t2 = 0;
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp for schedule(runtime) private(start_time, end_time)
|
||||||
|
#endif
|
||||||
|
for (unsigned long i = 1; i < MAX_N; i++)
|
||||||
|
{
|
||||||
|
start_time = clock();
|
||||||
|
if (!is_sum_of_abundant(i))
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp critical
|
||||||
|
#endif
|
||||||
|
sum += i;
|
||||||
|
end_time = clock();
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp critical
|
||||||
|
#endif
|
||||||
|
t2 += end_time - start_time;
|
||||||
|
|
||||||
|
printf("... %5lu: %8lu\r", i, sum);
|
||||||
|
if (i % 100 == 0)
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
putchar('\n');
|
||||||
|
#endif
|
||||||
|
double t22 = 1e3 * t2 / CLOCKS_PER_SEC;
|
||||||
|
printf("Time taken for final sum: %.4g ms\nTotal Time taken: %.4g ms\n", t22, t1 + t22);
|
||||||
|
printf("Memory used: %lu bytes\n", MAX_N >> 3);
|
||||||
|
printf("Sum of numbers that cannot be represented as sum of two abundant numbers : %lu\n", sum);
|
||||||
|
|
||||||
|
free(abundant_flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
project_euler/Problem 24/sol1
Executable file
BIN
project_euler/Problem 24/sol1
Executable file
Binary file not shown.
109
project_euler/Problem 25/sol1.c
Normal file
109
project_euler/Problem 25/sol1.c
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define MAX_DIGITS 1000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to add arbitraty length decimal integers stored in an array.
|
||||||
|
* a + b = c = new b
|
||||||
|
**/
|
||||||
|
unsigned int add_numbers(uint8_t *a, uint8_t *b, uint8_t *c, int N)
|
||||||
|
{
|
||||||
|
uint8_t carry = 0;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
// printf("\t%d + %d + %d ", a[i], b[i], carry);
|
||||||
|
c[i] = carry + a[i] + b[i];
|
||||||
|
if (c[i] > 9) /* check for carry */
|
||||||
|
{
|
||||||
|
carry = 1;
|
||||||
|
c[i] -= 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
carry = 0;
|
||||||
|
// printf("= %d, %d\n", carry, c[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (carry != 0)
|
||||||
|
{
|
||||||
|
// printf("\t\t...adding new digit\n");
|
||||||
|
// printf("\t0 + %d + %d ", b[i], carry);
|
||||||
|
c[i] = carry + c[i];
|
||||||
|
if (c[i] > 9)
|
||||||
|
{
|
||||||
|
carry = 1;
|
||||||
|
c[i] -= 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
carry = 0;
|
||||||
|
// printf("= %d, %d\n", carry, c[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_number(uint8_t *number, int N)
|
||||||
|
{
|
||||||
|
int start_pos = N - 1;
|
||||||
|
|
||||||
|
/* skip all initial zeros */
|
||||||
|
while (number[start_pos] == 0)
|
||||||
|
start_pos--;
|
||||||
|
|
||||||
|
for (int i = start_pos; i >= 0; i--)
|
||||||
|
putchar(number[i] + 0x30);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int get_digits(uint8_t *number)
|
||||||
|
{
|
||||||
|
unsigned int digits = MAX_DIGITS;
|
||||||
|
while (number[digits] == 0)
|
||||||
|
digits--;
|
||||||
|
return digits;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
uint8_t fn[MAX_DIGITS + 1]; /* array to store digits of a large number */
|
||||||
|
uint8_t fn1[MAX_DIGITS + 1];
|
||||||
|
uint8_t sum[MAX_DIGITS + 1];
|
||||||
|
|
||||||
|
memset(fn, 0, MAX_DIGITS);
|
||||||
|
memset(fn1, 0, MAX_DIGITS);
|
||||||
|
memset(sum, 0, MAX_DIGITS);
|
||||||
|
|
||||||
|
fn[0] = 1;
|
||||||
|
fn1[1] = 1;
|
||||||
|
|
||||||
|
unsigned int index = 1, digit_count = 1;
|
||||||
|
|
||||||
|
clock_t start_time = clock();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
digit_count = add_numbers(fn, fn1, sum, digit_count);
|
||||||
|
// digit_count = get_digits(sum);
|
||||||
|
|
||||||
|
// printf("%5u (%u) (%u) ", index, digit_count, get_digits(sum));
|
||||||
|
// print_number(sum, digit_count);
|
||||||
|
// putchar('\n');
|
||||||
|
|
||||||
|
if (digit_count == MAX_DIGITS)
|
||||||
|
break;
|
||||||
|
memcpy(fn, fn1, MAX_DIGITS);
|
||||||
|
memcpy(fn1, sum, MAX_DIGITS);
|
||||||
|
index++;
|
||||||
|
} while (digit_count < MAX_DIGITS);
|
||||||
|
clock_t end_time = clock();
|
||||||
|
|
||||||
|
printf("Time taken: %.4g ms\n", 1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
||||||
|
printf("The nth term for %d digits: %u \n", MAX_DIGITS, index--);
|
||||||
|
print_number(sum, digit_count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#define ELEMENT_NR 20
|
#define ELEMENT_NR 20000
|
||||||
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
|
#define ARRAY_LEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
const char *notation = "Shell Sort Big O Notation:\
|
const char *notation = "Shell Sort Big O Notation:\
|
||||||
\n--> Best Case: O(n log(n)) \
|
\n--> Best Case: O(n log(n)) \
|
||||||
@ -37,10 +37,38 @@ void shellSort(int array[], int len)
|
|||||||
swap(&array[j], &array[j + gap]);
|
swap(&array[j], &array[j + gap]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimized algorithm - takes half the time as other
|
||||||
|
**/
|
||||||
|
void shell_sort2(int array[], int LEN)
|
||||||
|
{
|
||||||
|
const int gaps[] = {701, 301, 132, 57, 23, 10, 4, 1};
|
||||||
|
const int gap_len = 8;
|
||||||
|
int i, j, g;
|
||||||
|
|
||||||
|
for (g = 0; g < gap_len; g++)
|
||||||
|
{
|
||||||
|
int gap = gaps[g];
|
||||||
|
for (i = gap; i < LEN; i++)
|
||||||
|
{
|
||||||
|
int tmp = array[i];
|
||||||
|
|
||||||
|
for (j = i; j >= gap && (array[j - gap] - tmp) > 0; j -= gap)
|
||||||
|
array[j] = array[j - gap];
|
||||||
|
array[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
for (i = 0; i < LEN; i++)
|
||||||
|
printf("%s\t", data[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int array[ELEMENT_NR];
|
int array[ELEMENT_NR];
|
||||||
|
int array2[ELEMENT_NR];
|
||||||
int range = 500;
|
int range = 500;
|
||||||
int size;
|
int size;
|
||||||
clock_t start, end;
|
clock_t start, end;
|
||||||
@ -48,7 +76,10 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
for (i = 0; i < ELEMENT_NR; i++)
|
for (i = 0; i < ELEMENT_NR; i++)
|
||||||
|
{
|
||||||
array[i] = rand() % range + 1;
|
array[i] = rand() % range + 1;
|
||||||
|
array2[i] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
size = ARRAY_LEN(array);
|
size = ARRAY_LEN(array);
|
||||||
|
|
||||||
@ -62,7 +93,19 @@ int main(int argc, char *argv[])
|
|||||||
show_data(array, size);
|
show_data(array, size);
|
||||||
|
|
||||||
printf("%s\n", notation);
|
printf("%s\n", notation);
|
||||||
printf("Time spent sorting: %f\n", time_spent);
|
printf("Time spent sorting: %.4g ms\n", time_spent * 1e3);
|
||||||
|
|
||||||
|
printf("--------------------------\n");
|
||||||
|
start = clock();
|
||||||
|
shell_sort2(array2, size);
|
||||||
|
end = clock();
|
||||||
|
time_spent = (double)(end - start) / CLOCKS_PER_SEC;
|
||||||
|
|
||||||
|
printf("Data Sorted\n");
|
||||||
|
show_data(array2, size);
|
||||||
|
|
||||||
|
printf("%s\n", notation);
|
||||||
|
printf("Time spent sorting: %.4g ms\n", time_spent * 1e3);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user