/*
-Anagramarama - A word game. Like anagrams? You'll love anagramarama!
-Copyright (C) 2003 Colm Gallagher
+ Anagramarama - A word game. Like anagrams? You'll love anagramarama!
+ Copyright (C) 2003 Colm Gallagher
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-Contact Details: colm@coralquest.com
- 12 Weston Terrace, West Kilbride, KA23 9JX. Scotland.
+ Contact Details: colm@coralquest.com
+ 12 Weston Terrace, West Kilbride, KA23 9JX. Scotland.
*/
#include <stdlib.h>
#include <string.h>
#include "linked.h"
-/***********************************************************/
-int Length(struct node* head){
+/*
+ * Count the length of the linked list.
+ */
+
+int
+Length(struct node *head)
+{
+ struct node *current = head;
+ int count = 0;
+ for ( ; current; current = current->next) {
+ ++count;
+ }
+ return count;
+}
-struct node* current = head;
-int count = 0;
+/*
+ * swap the data content of two linked list nodes without changing
+ * the position of the node within the list
+ */
+
+void
+swap(struct node **from, struct node **to)
+{
+ char *word = (*from)->anagram;
+ int len = (*from)->length;
+
+ (*from)->anagram = (*to)->anagram;
+ (*from)->length = (*to)->length;
+ (*to)->anagram = word;
+ (*to)->length = len;
+}
- while (current != NULL){
- //printf("%s\n", current->anagram);
- count++;
- current = current->next;
+/*
+ * sort the list first alphabetically and then by increasing word length
+ */
+
+void
+sort(struct node **headRef)
+{
+ struct node* left, *right;
+ int completed = 0;
+
+ while (!completed) {
+ left = *headRef;
+ right = left->next;
+ completed = 1;
+ for (; left && right; left = left->next, right = right->next) {
+ if (strcmp(left->anagram, right->anagram) > 0) {
+ swap(&left, &right);
+ completed = 0;
+ }
}
+ }
+
+ completed = 0;
+ while (!completed) {
+ left = *headRef;
+ right = left->next;
+ completed = 1;
+ for (; left && right; left = left->next, right = right->next) {
+ if (left->length > right->length) {
+ swap(&left, &right);
+ completed = 0;
+ }
+ }
+ }
+}
- return count;
+/*
+ * Free the list and the allocated data in each node
+ */
+
+void
+destroyAnswers(struct node** headRef)
+{
+ struct node* current = *headRef;
+ struct node* previous = *headRef;
+
+ while (current != NULL){
+ free(current->anagram);
+ previous = current;
+ current = current->next;
+ free(previous);
+ previous = NULL;
+ }
+
+ *headRef = NULL;
}
-/***********************************************************/
-void swap(struct node** from, struct node** to){
-// swaps the contents of 2 linked list nodes
-// doesn't disturb the pointers
-char* swap;
-
- swap = malloc(sizeof((*from)->anagram));
- strcpy(swap, (*from)->anagram);
- (*from)->anagram = (*to)->anagram;
- (*from)->length = (*to)->length;
- (*to)->anagram = swap;
- (*to)->length = strlen(swap);
-
-}
/***********************************************************/
-void sort(struct node** headRef){
-// sort the linked list alpha/num of chars
-struct node* current = *headRef;
-struct node* next = malloc(sizeof(struct node));
-int done = 0;
-int swaps = 0;
-
- // walk the list
- while (!done){
- while (current !=NULL){
- next = current->next;
- if (next != NULL){
- //printf("%s, %s - %i\n", next->anagram, current->anagram, strcmp(next->anagram, current->anagram));
- if (strcmp(next->anagram, current->anagram)<0){
- swap(&next, ¤t);
- swaps++;
- }
- }
- current = current->next;
- }
- if (!swaps){
- done = 1;
- }
- else{
- swaps = 0;
- current = *headRef;
- }
- }
-
- done = 0;
- current = *headRef;
- swaps = 0;
-
- // walk the list
- while (!done){
- while (current !=NULL){
- next = current->next;
- if (next != NULL){
- //printf("%s, %s \n", next->anagram, current->anagram);
- if (strlen(next->anagram) < strlen(current->anagram)){
- swap(&next, ¤t);
- swaps++;
- }
- }
- current = current->next;
- }
- if (!swaps){
- done = 1;
- }
- else{
- swaps = 0;
- current = *headRef;
- }
- }
-
- free(next);
+void
+push(struct node **headRef, const char *anagram)
+{
+ struct node * current = *headRef;
+ int len;
+ int duplicate = 0;
+
+ /* walk the list first, so we can ignore duplicates...
+ * this is probably slower than clearing duplicates at the end
+ * but simpler to write in the first instance
+ */
+ while (current != NULL) {
+ if (!strcmp(anagram, current->anagram)){
+ duplicate = 1;
+ break;
+ }
+ current = current->next;
+ }
+
+ if (!duplicate) {
+ struct node *newNode = malloc(sizeof(struct node));
+ len = strlen(anagram);
+ newNode->anagram = strdup(anagram);
+ newNode->length = len;
+ newNode->found = 0;
+ newNode->guessed = 0;
+ newNode->next = *headRef;
+
+ *headRef = newNode;
+ }
}
-/***********************************************************/
-void destroyAnswers(struct node** headRef){
-// destroy the whole answers list
-
-struct node* current = *headRef;
-struct node* previous = *headRef;
-
- while (current != NULL){
- free(current->anagram);
- previous = current;
- current = current->next;
- free(previous);
- previous = NULL;
- }
-
- *headRef = NULL;
+#ifdef UNIT_TEST
+#include "unittest.h"
+
+static int test_list_creation()
+{
+ struct node *head = NULL, *node = NULL;
+ const char *words[] = {"one", "two", "three", "four", "five" };
+ const char *ordrd[] = {"one", "two", "five", "four", "three" };
+ size_t n, word_count = sizeof(words)/sizeof(words[0]);
+
+ for (n = 0; n < word_count;++n) {
+ push(&head, (char *)words[n]);
+ }
+ test_equals_int("check list length", 5, Length(head));
+
+ for (node = head, n = word_count; node; --n, node = node->next) {
+ if (strcmp(words[n-1], node->anagram) != 0)
+ test_fail("incorrect node value");
+ if (strlen(words[n-1]) != node->length)
+ test_fail("incorrect node value length");
+ }
+
+ node = head->next;
+ swap(&head, &node);
+ test_equals_str("check swapped nodes", words[3], head->anagram);
+ test_equals_str("check swapped nodes", words[4], head->next->anagram);
+
+ sort(&head);
+
+ for (node = head, n = 0; node; ++n, node = node->next) {
+ if (strcmp(ordrd[n], node->anagram) != 0)
+ test_fail("incorrect node value");
+ }
+
+ destroyAnswers(&head);
+ test_equals_ptr("check list destroyed", head, NULL);
+ return 0;
}
+struct unit_test_t unit_tests[] = {
+ { NULL, test_list_creation, NULL}
+};
-
-/***********************************************************/
-void push(struct node** headRef, char* anagram){
-
-struct node* newNode = malloc(sizeof(struct node));
-int len;
-struct node* current = *headRef;
-int duplicate = 0;
-
- // walk the list first, so we can ignore duplicates...
- // this is probably slower than clearing duplicates at the end
- // but simpler to write in the first instance
- while (current != NULL){
- if (!strcmp(anagram, current->anagram)){
- duplicate = 1;
- break;
- }
- current = current->next;
- }
-
- if (!duplicate){
- len = strlen(anagram+1);
- newNode->anagram = malloc(sizeof(char)*(len + 1));
- strcpy(newNode->anagram, anagram);
- newNode->length = len + 1;
- newNode->found = 0;
- newNode->guessed = 0;
- newNode->next = *headRef; // dereference back the the real head pointer
-
- *headRef = newNode; // ditto when replacing it with the new one
- }
+int
+main(void)
+{
+ run_tests(unit_tests);
+ return 0;
}
+#endif /* UNIT_TEST */
+
+/*
+ * Local variables:
+ * mode: c
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
#include <stdint.h>
#endif
+#ifdef __GNUC__
+#define NOWARN __attribute__((unused))
+#else
+#define NOWARN
+#endif
+static void test_equals_int(const char *what, const int a, const int b) NOWARN;
+static void test_equals_wide(const char *what, const uint64_t a, const uint64_t b) NOWARN;
+static void test_equals_ptr(const char *what, const void *a, const void *b) NOWARN;
+static void test_equals_str(const char *what, const char *a, const char *b) NOWARN;
+static void test_equals_strn(const char *what, const char *a, const char *b, size_t n) NOWARN;
+static void test_non_null_ptr(const char *what, const void *a) NOWARN;
+
typedef void * (unit_test_setup_t)();
typedef int (unit_test_run_t)(void *);
typedef void (unit_test_teardown_t)(void *);
#define RUN(what) printf("\t%s\n", what); test_count++;
-static test_fail(const char *what)
+static void test_fail(const char *what)
{
printf("\tFAIL: %s\n", what);
fflush(stdout);
RUN(what);
if (a != b) test_fail(what);
}
-static void test_equals_str(const char *what, const uint8_t *a, const uint8_t *b)
+static void test_equals_str(const char *what, const char *a, const char *b)
{
RUN(what);
- if (strcmp((const char *)a,(const char *)b)) test_fail(what);
+ if (strcmp(a,b)) test_fail(what);
}
-static void test_equals_strn(const char *what, const uint8_t *a, const uint8_t *b, size_t n)
+static void test_equals_strn(const char *what, const char *a, const char *b, size_t n)
{
RUN(what);
- if (strncmp((const char *)a,(const char *)b,n)) test_fail(what);
+ if (strncmp(a,b,n)) test_fail(what);
}
static void test_non_null_ptr(const char *what, const void *a)
{
}
static int
-run_tests(const struct unit_test_t *testPtr)
+run_test(const struct unit_test_t *testPtr)
{
int r = 0;
void *clientData = NULL;
testPtr->tearDown(clientData);
return r;
}
+
+#define run_tests(tests) do { \
+ size_t n; \
+ for (n = 0; n < sizeof(tests)/sizeof(tests[0]); ++n) { \
+ run_test(&tests[n]); \
+ } \
+ test_print_results(); \
+ } while(0);