2020-06-05 20:53:38 +03:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
* \brief [Problem 22](https://projecteuler.net/problem=22) solution
|
2020-06-06 21:51:49 +03:00
|
|
|
* \author [Krishna Vedala](https://github.com/kvedala)
|
2020-06-05 20:53:38 +03:00
|
|
|
*/
|
2020-04-02 06:29:54 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
|
|
|
#ifdef _OPENMP
|
|
|
|
#include <omp.h>
|
|
|
|
#endif
|
|
|
|
|
2020-06-05 20:53:38 +03:00
|
|
|
#define MAX_NAMES 6000 /**< Maximum number of names to store */
|
|
|
|
#define MAX_NAME_LEN 20 /**< Maximum length of each name */
|
2020-04-02 06:29:54 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Alphabetical sorting using 'shell sort' algorithm
|
2020-06-28 22:18:52 +03:00
|
|
|
*/
|
2020-04-02 06:29:54 +03:00
|
|
|
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]);
|
|
|
|
|
2020-05-29 23:23:24 +03:00
|
|
|
for (j = i; j >= gap && strcmp(data[j - gap], tmp_buffer) > 0;
|
|
|
|
j -= gap)
|
2020-04-02 06:29:54 +03:00
|
|
|
strcpy(data[j], data[j - gap]);
|
|
|
|
strcpy(data[j], tmp_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef DEBUG
|
2020-06-28 18:25:37 +03:00
|
|
|
for (i = 0; i < LEN; i++) printf("%s\t", data[i]);
|
2020-04-02 06:29:54 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Alphabetical sorting using 'lazy sort' algorithm
|
2020-06-28 22:18:52 +03:00
|
|
|
*/
|
2020-04-02 06:29:54 +03:00
|
|
|
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
|
2020-06-28 18:25:37 +03:00
|
|
|
for (i = 0; i < LEN; i++) printf("%s\t", data[i]);
|
2020-04-02 06:29:54 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-06-05 20:53:38 +03:00
|
|
|
/** Main function */
|
2020-04-02 06:29:54 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-06-05 20:53:38 +03:00
|
|
|
/*
|
2020-04-02 06:29:54 +03:00
|
|
|
* Loops to get total number of rows and columns in the file
|
2020-06-05 20:53:38 +03:00
|
|
|
*/
|
2020-04-02 06:29:54 +03:00
|
|
|
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();
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("\nShell sort: %.4g millisecond\n",
|
|
|
|
1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
2020-04-02 06:29:54 +03:00
|
|
|
}
|
|
|
|
else if (method == 1)
|
|
|
|
{
|
|
|
|
clock_t start_time = clock();
|
|
|
|
lazy_sort(names, COUNT);
|
|
|
|
clock_t end_time = clock();
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("\nLazy sort: %.4g millisecond\n",
|
|
|
|
1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
2020-04-02 06:29:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
long sum_score = 0;
|
|
|
|
clock_t start_time = clock();
|
2020-04-24 03:59:02 +03:00
|
|
|
int i;
|
2020-04-24 03:17:32 +03:00
|
|
|
|
2020-04-02 06:29:54 +03:00
|
|
|
#ifdef _OPENMP
|
2020-05-29 23:23:24 +03:00
|
|
|
#pragma omp parallel for schedule(runtime) reduction(+ : sum_score)
|
2020-04-02 06:29:54 +03:00
|
|
|
#endif
|
|
|
|
#ifdef DEBUG
|
2020-04-24 03:17:32 +03:00
|
|
|
for (i = 935; i < 940; i++)
|
2020-04-02 06:29:54 +03:00
|
|
|
#else
|
2020-04-24 03:17:32 +03:00
|
|
|
for (i = 0; i < COUNT; i++)
|
2020-04-02 06:29:54 +03:00
|
|
|
#endif
|
|
|
|
{
|
2020-07-02 03:21:56 +03:00
|
|
|
long score = 0;
|
2020-04-02 06:29:54 +03:00
|
|
|
/* score the alphabets in i^th name */
|
|
|
|
for (int j = 0; names[i][j] != '\0'; j++)
|
2020-05-29 23:23:24 +03:00
|
|
|
score += names[i][j] - 'A' +
|
|
|
|
1; /* convert ASCII character to integer score */
|
2020-04-02 06:29:54 +03:00
|
|
|
sum_score += score * (i + 1);
|
|
|
|
#ifdef DEBUG
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("Name: %s\tScore: %u x %u = %lu\n", names[i], score, i + 1,
|
|
|
|
(unsigned long)score * (i + 1));
|
2020-04-02 06:29:54 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
clock_t end_time = clock();
|
2020-05-29 23:23:24 +03:00
|
|
|
printf("Scoring time: %.4g millisecond\n",
|
|
|
|
1e3 * (end_time - start_time) / CLOCKS_PER_SEC);
|
2020-04-02 06:29:54 +03:00
|
|
|
|
|
|
|
printf("Total Score = %lu\n", sum_score);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|