--- /dev/null
+#include <stdio.h>
+#include <ctype.h>
+#include <stdbool.h>
+
+#include <uthash.h>
+
+struct conn {
+ char key[10];
+ struct node *node;
+ UT_hash_handle hh;
+};
+struct node {
+ char key[10];
+ struct conn *connections;
+ UT_hash_handle hh;
+};
+
+struct node *get_or_create(struct node **graph, char name[])
+{
+ struct node *n;
+ HASH_FIND_STR(*graph, name, n);
+ if (n) {
+ return n;
+ } else {
+ n = malloc(sizeof(struct node));
+ strcpy(n->key, name);
+ n->connections = NULL;
+ HASH_ADD_STR(*graph, key, n);
+ }
+ return n;
+}
+
+void add_connection(struct node *from, struct node *to)
+{
+ //to
+ struct conn *c = malloc(sizeof(struct conn));
+ strcpy(c->key, to->key);
+ c->node = to;
+ HASH_ADD_STR(from->connections, key, c);
+ //fro
+ c = malloc(sizeof(struct conn));
+ strcpy(c->key, from->key);
+ c->node = from;
+ HASH_ADD_STR(to->connections, key, c);
+}
+
+char **copy_visited(char **visited, int nvisited)
+{
+ char **r = malloc(sizeof(char *)*nvisited);
+ memcpy(r, visited, sizeof(char *)*nvisited);
+ return r;
+}
+
+int find_end(struct node *node, char **visited, int nvisited, bool twice)
+{
+ if (strcmp(node->key, "end") == 0)
+ return 1;
+ if (islower(node->key[0])) {
+ for (int i = 0; i<nvisited; i++)
+ if (strcmp(node->key, visited[i]) == 0)
+ return 0;
+ visited = realloc(visited, sizeof(char *)*(nvisited+1));
+ visited[nvisited++] = node->key;
+ }
+ int r = 0;
+ for (struct conn *c = node->connections; c != NULL; c = c->hh.next) {
+ if (twice && strcmp(node->key, "start") != 0 && islower(node->key[0]))
+ r += find_end(c->node, copy_visited(visited, nvisited-1), nvisited-1, false);
+ r += find_end(c->node, copy_visited(visited, nvisited), nvisited, twice);
+ }
+ free(visited);
+ return r;
+}
+
+int main()
+{
+ struct node *graph = NULL;
+ char *buf = NULL;
+ size_t len = 0;
+ while (getline(&buf, &len, stdin) != -1) {
+ char *toname = strchr(buf, '-');
+ *(toname++)= '\0';
+ if (toname[strlen(toname)-1] == '\n')
+ toname[strlen(toname)-1] = '\0';
+ add_connection(get_or_create(&graph, buf),
+ get_or_create(&graph, toname));
+ }
+
+ printf("%d\n", find_end(get_or_create(&graph, "start"), NULL, 0, true));
+}