Project Euler, Πρόβλημα #22 έγραψε:Using
names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.
For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.
What is the total of all the name scores in the file?
Η λύση μου σε C...
- Κώδικας: Επιλογή όλων
#include <stdio.h>
#include <string.h> // for strncmp
#include <stdlib.h> // for calloc(), free()
#define MAX_WLEN 100
#define LETTVAL(c) ((c)-'A'+1)
typedef enum { FALSE=0, TRUE } Bool;
typedef struct node {
char word[ MAX_WLEN ]; // the word
struct node *next; // pointer to next node
} Node;
typedef struct {
Node *head, *tail; // pointers to 1st & last nodes
long int len; // UNUSED
} List;
// ------------------------------------------------------------------------------------
char *s_ncopy( char *dst, const char *src, int n )
{
char *ret = dst;
while ( (dst-ret) < n-1 && (*dst=*src) != '\0' )
dst++, src++;
if ( *dst )
*dst = 0;
return ret;
}
// ------------------------------------------------------------------------------------
Bool list_putascend( List *list, char *data )
{
Node *curr = NULL, *prev = NULL;
Node *new = calloc( 1, sizeof(struct node) );
if ( !new || !data ) // calloc failed or invalid data
return FALSE;
s_ncopy(new->word, data, MAX_WLEN); // initialize newly created node
new->next = NULL; // ...
if ( list->head == NULL) { // list was empty, direct insertion
list->head = list->tail = new;
(list->len)++;
return TRUE;
}
// direct append
if ( strncmp(data, list->tail->word, MAX_WLEN ) >= 0 ) {
list->tail->next = new;
list->tail = new;
(list->len)++;
return TRUE;
}
curr = prev = list->head; // general case (traversing)
// find spot for the insertion
while ( curr && strncmp(curr->word, data, MAX_WLEN) <= 0 )
{ // use <= data, to allow duplicates
prev = curr; // save previous node
curr = curr->next;
}
// insert BEFORE 1st node
if ( list->head == curr /* && curr->data != data */ ) {
list->head = new;
new->next = curr;
(list->len)++;
return TRUE;
}
// insert AFTER 1st node
if ( !curr || strncmp(curr->word, data, MAX_WLEN) != 0 ) {
prev->next = new;
new->next = curr;
}
(list->len)++;
return TRUE;
}
// ------------------------------------------------------------------------------------
void list_destroy( List *list )
{
if ( list->head == NULL )
return;
Node *dummy = NULL;
while ( list->head ) {
dummy = list->head->next;
free( list->head );
list->head = dummy;
}
return;
}
// ------------------------------------------------------------------------------------
Bool get_fcontents( const char *fname, const char *delims, List *list )
{
FILE *fp = fopen(fname, "r");
char s[ MAX_WLEN ] = {0}; // important! filling up with 0s
if ( !fp || !list) // fopen error or invalid list
return FALSE;
while ( !feof(fp) )
{
fscanf (fp, delims, s); // read next clean word
if ( !list_putascend( list, s) ) { // if insertion to list fails
fclose( fp ); // cleanup & return error
return FALSE;
}
}
fclose( fp );
return TRUE;
}
// ------------------------------------------------------------------------------------
int main( void )
{
List list = {.head=NULL, .tail=NULL, .len=0L}; // linked list for sorted words
Node *pnode = NULL; // for traversing the list
long int i, score = 0; // node counter & total score
// read file contents into list, in ascending order
get_fcontents( "names.txt", "\"%[a-zA-Z]\",", &list );
// calc the total score
for (i=0, pnode = list.head; pnode; i++ )
{
int wscore = 0; // individual word score
char *cp = pnode->word; // for traversing a word
while ( *cp ) // calc individual score
wscore += LETTVAL( *cp++ );
score += (i+1) * wscore;
pnode = pnode->next;
}
printf("%ld\n", score ); // print the total score
list_destroy( &list ); // free mem reserved for list
exit( EXIT_SUCCESS );
}
Βασικά, με τη συνάρτηση get_fcontents() διαβάζει τις λέξεις από το αρχείο (χρησιμοποιώντας ως διαχωριστικούς χαρακτήρες τα δυο " και το ,) και τις αποθηκεύει ταξινομημένες σε μια απλά συνδεδεμένη λίστα. Κατόπιν πιάνει τη λίστα από την αρχή και υπολογίζει τη βαθμολογία της κάθε λέξης, καθώς και το τελικό σκορ.
Θα πάω σπίτι να δω μήπως μπορώ να σινιάρω καθόλου τον κώδικα και να τον ανεβάσω και στο ideone.com.
ΥΓ. Είδα λύση σε Python σε 3 γραμμές !!!!!!!! (χρησιμοποιούσε lamdas) και κόντεψα να βάλω τα κλάμματα
