diff --git a/du5/program.c b/du5/program.c new file mode 100644 index 0000000..52531c1 --- /dev/null +++ b/du5/program.c @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include + +typedef struct Node { + int is_answer; + char *text; + struct Node *yes; + struct Node *no; +} Node; + +// portable strdup replacement +static char *my_strdup(const char *s) { + if (!s) return NULL; + size_t l = strlen(s) + 1; + char *p = malloc(l); + if (!p) return NULL; + memcpy(p, s, l); + return p; +} + +// getline prototype (POSIX); declaring to avoid implicit declaration warnings +ssize_t getline(char **__lineptr, size_t *__n, FILE *__stream); + +static char *trim_newline(char *s) { + if (!s) return s; + size_t len = strlen(s); + while (len > 0 && (s[len-1] == '\n' || s[len-1] == '\r')) { + s[--len] = '\0'; + } + return s; +} + +static char *ltrim(char *s) { + while (*s && isspace((unsigned char)*s)) s++; + return s; +} + +Node *parse_node(char **lines, int n, int *idx, int *err) { + if (*idx >= n) { *err = 1; return NULL; } + char *line = lines[*idx]; + (*idx)++; + if (line[0] == '*') { + // answer node + char *txt = line + 1; + txt = ltrim(txt); + Node *node = malloc(sizeof(Node)); + if (!node) { *err = 1; return NULL; } + node->is_answer = 1; + node->text = my_strdup(txt); + node->yes = node->no = NULL; + return node; + } else { + // question node + Node *node = malloc(sizeof(Node)); + if (!node) { *err = 1; return NULL; } + node->is_answer = 0; + node->text = my_strdup(line); + node->yes = parse_node(lines, n, idx, err); + if (*err) { free(node->text); free(node); return NULL; } + node->no = parse_node(lines, n, idx, err); + if (*err) { // free subtree? skip deep frees for brevity + free(node->text); free(node); return NULL; + } + return node; + } +} + +int count_answers(Node *root) { + if (!root) return 0; + if (root->is_answer) return 1; + return count_answers(root->yes) + count_answers(root->no); +} + +void free_tree(Node *root) { + if (!root) return; + free_tree(root->yes); + free_tree(root->no); + free(root->text); + free(root); +} + +int main(void) { + // Read lines until an empty line (or EOF) + char *line = NULL; + size_t cap = 0; + ssize_t len; + char **lines = NULL; + int lines_count = 0; + + while ((len = getline(&line, &cap, stdin)) != -1) { + trim_newline(line); + // stop at blank line + if (line[0] == '\0') break; + // store a copy + char *copy = my_strdup(line); + if (!copy) { fprintf(stderr, "Chyba pri alokácii pamäte\n"); return 1; } + lines = realloc(lines, sizeof(char*) * (lines_count + 1)); + if (!lines) { fprintf(stderr, "Chyba pri alokácii pamäte\n"); return 1; } + lines[lines_count++] = copy; + } + free(line); + + if (lines_count == 0) { + printf("Chyba pri načítaní bázy pravidiel\n"); + return 0; + } + + int idx = 0; + int err = 0; + Node *root = parse_node(lines, lines_count, &idx, &err); + if (err || root == NULL || idx != lines_count) { + printf("Chyba pri načítaní bázy pravidiel\n"); + for (int i = 0; i < lines_count; ++i) free(lines[i]); + free(lines); + if (root) free_tree(root); + return 0; + } + + int leaves = count_answers(root); + // print number of goods (answers) + printf("%d\n", leaves); + + // interactive session: use 'a' for áno (yes) and 'n' for nie (no) + Node *cur = root; + char buf[128]; + while (cur) { + if (cur->is_answer) { + // print answer and exit + printf("Odpoveď: %s\n", cur->text); + break; + } + // question + printf("%s\n", cur->text); + if (!fgets(buf, sizeof(buf), stdin)) { + // EOF or error + printf("Nesprávny vstup\n"); + break; + } + // skip whitespace and take first non-space char + char *p = buf; + while (*p && isspace((unsigned char)*p)) p++; + char c = *p; + if (c == 'a' || c == 'A') { + cur = cur->yes; + } else if (c == 'n' || c == 'N') { + cur = cur->no; + } else { + printf("Nesprávny vstup\n"); + break; + } + } + + free_tree(root); + for (int i = 0; i < lines_count; ++i) free(lines[i]); + free(lines); + return 0; +} \ No newline at end of file