Four is the number of letters in the ...: Difference between revisions

Content added Content deleted
(C - reduce memory usage)
(C - use GLib)
Line 51: Line 51:


=={{header|C}}==
=={{header|C}}==
{{libheader|GLib}}
<lang c>#include <ctype.h>
<lang c>#include <ctype.h>
#include <locale.h>
#include <locale.h>
Line 56: Line 57:
#include <stdio.h>
#include <stdio.h>
#include <stdint.h>
#include <stdint.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>


typedef uint64_t integer;
typedef uint64_t integer;
Line 115: Line 115:
}
}
return &named_numbers[names_len - 1];
return &named_numbers[names_len - 1];
}

void fatal(const char* message) {
fprintf(stderr, "%s\n", message);
exit(1);
}

void* xmalloc(size_t n) {
void* ptr = malloc(n);
if (ptr == NULL)
fatal("Out of memory");
return ptr;
}

void* xrealloc(void* p, size_t n) {
void* ptr = realloc(p, n);
if (ptr == NULL)
fatal("Out of memory");
return ptr;
}

typedef struct string_buffer_tag {
size_t size;
size_t capacity;
char* string;
} string_buffer;

void string_buffer_create(string_buffer* buffer, size_t capacity) {
buffer->size = 0;
buffer->capacity = capacity;
buffer->string = xmalloc(capacity);
}

void string_buffer_destroy(string_buffer* buffer) {
free(buffer->string);
buffer->string = NULL;
buffer->size = 0;
buffer->capacity = 0;
}

void string_buffer_clear(string_buffer* buffer) {
buffer->size = 0;
}

void string_buffer_append(string_buffer* buffer, const char* str, size_t len) {
size_t min_capacity = buffer->size + len + 1;
if (buffer->capacity < min_capacity) {
size_t new_capacity = 5*buffer->capacity/4;
if (new_capacity < min_capacity)
new_capacity = min_capacity;
buffer->string = xrealloc(buffer->string, new_capacity);
buffer->capacity = new_capacity;
}
memcpy(buffer->string + buffer->size, str, len + 1);
buffer->size += len;
}
}


Line 175: Line 120:
size_t offset;
size_t offset;
size_t length;
size_t length;
} word;
} word_t;


typedef struct word_list_tag {
typedef struct word_list_tag {
size_t size;
GArray* words;
size_t capacity;
GString* str;
word* words;
string_buffer str;
} word_list;
} word_list;


void word_list_create(word_list* words, size_t capacity) {
void word_list_create(word_list* words) {
words->size = 0;
words->words = g_array_new(FALSE, FALSE, sizeof(word_t));
words->capacity = capacity;
words->str = g_string_new(NULL);
words->words = xmalloc(capacity * sizeof(word));
string_buffer_create(&words->str, capacity*8);
}
}


void word_list_destroy(word_list* words) {
void word_list_destroy(word_list* words) {
string_buffer_destroy(&words->str);
g_string_free(words->str, TRUE);
free(words->words);
g_array_free(words->words, TRUE);
words->words = NULL;
words->size = 0;
words->capacity = 0;
}
}


void word_list_clear(word_list* words) {
void word_list_clear(word_list* words) {
string_buffer_clear(&words->str);
g_string_truncate(words->str, 0);
words->size = 0;
g_array_set_size(words->words, 0);
}
}


void word_list_append(word_list* words, const char* str) {
void word_list_append(word_list* words, const char* str) {
size_t offset = words->str.size;
size_t offset = words->str->len;
size_t len = strlen(str);
size_t len = strlen(str);
string_buffer_append(&words->str, str, len);
g_string_append_len(words->str, str, len);
word_t word;
size_t min_capacity = words->size + 1;
word.offset = offset;
if (words->capacity < min_capacity) {
word.length = len;
size_t new_capacity = (words->capacity * 5)/4;
g_array_append_val(words->words, word);
if (new_capacity < min_capacity)
}
new_capacity = min_capacity;

words->words = xrealloc(words->words, new_capacity * sizeof(word));
word_t* word_list_get(word_list* words, size_t index) {
words->capacity = new_capacity;
return &g_array_index(words->words, word_t, index);
}
word* w = &words->words[words->size++];
w->offset = offset;
w->length = len;
}
}


void word_list_extend(word_list* words, const char* str) {
void word_list_extend(word_list* words, const char* str) {
word* w = &words->words[words->size - 1];
word_t* word = word_list_get(words, words->words->len - 1);
size_t len = strlen(str);
size_t len = strlen(str);
w->length += len;
word->length += len;
string_buffer_append(&words->str, str, len);
g_string_append_len(words->str, str, len);
}
}


Line 258: Line 193:
}
}


size_t count_letters(const word_list* words, size_t index) {
size_t count_letters(word_list* words, size_t index) {
const word* w = &words->words[index];
const word_t* word = word_list_get(words, index);
size_t letters = 0;
size_t letters = 0;
const char* s = words->str.string + w->offset;
const char* s = words->str->str + word->offset;
for (size_t i = 0, n = w->length; i < n; ++i) {
for (size_t i = 0, n = word->length; i < n; ++i) {
if (isalpha((unsigned char)s[i]))
if (isalpha((unsigned char)s[i]))
++letters;
++letters;
Line 290: Line 225:


size_t sentence_length(const word_list* words) {
size_t sentence_length(const word_list* words) {
size_t n = words->size;
size_t n = words->words->len;
if (n == 0)
if (n == 0)
return 0;
return 0;
return words->str.size + n - 1;
return words->str->len + n - 1;
}
}


Line 300: Line 235:
size_t n = 201;
size_t n = 201;
word_list result = { 0 };
word_list result = { 0 };
word_list_create(&result, 1024);
word_list_create(&result);
sentence(&result, n);
sentence(&result, n);
printf("Number of letters in first %'lu words in the sequence:\n", n);
printf("Number of letters in first %'lu words in the sequence:\n", n);
Line 311: Line 246:
for (n = 1000; n <= 10000000; n *= 10) {
for (n = 1000; n <= 10000000; n *= 10) {
sentence(&result, n);
sentence(&result, n);
const word* w = &result.words[n - 1];
const word_t* word = word_list_get(&result, n - 1);
const char* s = result.str.string + w->offset;
const char* s = result.str->str + word->offset;
printf("The %'luth word is '%.*s' and has %lu letters. ", n, (int)w->length, s,
printf("The %'luth word is '%.*s' and has %lu letters. ", n,
count_letters(&result, n - 1));
(int)word->length, s, count_letters(&result, n - 1));
printf("Sentence length: %'lu\n" , sentence_length(&result));
printf("Sentence length: %'lu\n" , sentence_length(&result));
}
}