]> www.ljiriste.work Git - SO_Challenges/15.git/commitdiff
Implement a solution to the challenge trunk
authorLukáš Jiřiště <redacted>
Sun, 25 Jan 2026 17:58:57 +0000 (18:58 +0100)
committerLukáš Jiřiště <redacted>
Sun, 25 Jan 2026 18:00:31 +0000 (19:00 +0100)
.gitmodules [new file with mode: 0644]
Libft [new submodule]
Makefile [new file with mode: 0644]
main.c [new file with mode: 0644]

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..626d139
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "Libft"]
+       path = Libft
+       url = git://ljiriste.work/Libft
diff --git a/Libft b/Libft
new file mode 160000 (submodule)
index 0000000..30f8df1
--- /dev/null
+++ b/Libft
@@ -0,0 +1 @@
+Subproject commit 30f8df1bfda39333988817e9f5312e71905dbc34
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..75d2376
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,72 @@
+MAKEFLAGS += --no-builtin-rules
+
+CC := gcc
+CFLAGS := -std=c99 -Wall -Wextra -Werror -Wpedantic
+LDFLAGS := -L Libft -lft
+
+ifneq ("$(wildcard .debug)","")
+       CFLAGS += -g
+endif
+
+RM := rm -f
+
+SUBPROJECTS := Libft
+
+INCDIR := inc
+INCDIR += $(addsuffix /inc, $(SUBPROJECTS));
+INCLUDE := $(addprefix -I, $(INCDIR))
+
+SRCDIR := .
+
+SOURCES :=     main.c                  \
+
+SOURCES := $(addprefix $(SRCDIR)/, $(SOURCES))
+
+OBJECTS := $(SOURCES:.c=.o)
+
+NAME := sort_alphabet
+
+all : $(NAME)
+
+debug : .debug
+       $(MAKE) -C Libft debug
+       $(MAKE) all
+
+nodebug :
+       $(MAKE) -C Libft nodebug
+       $(RM) .debug
+       $(MAKE) shallow_re
+
+.% :
+       $(MAKE) shallow_fclean
+       touch $@
+
+FORCE : ;
+
+Libft/libft.a : FORCE | Libft/Makefile
+       $(MAKE) -C Libft
+
+$(NAME) : $(OBJECTS) Libft/libft.a
+       $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
+
+%.o : %.c | Libft/Makefile
+       $(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)
+
+%/Makefile :
+       git submodule update --init $($@%/Makefile=%)
+
+clean :
+       $(RM) $(OBJECTS)
+
+fclean : clean
+       $(MAKE) -C Libft fclean
+       $(RM) $(NAME)
+
+re : fclean
+       $(MAKE) all
+
+shallow_fclean : clean
+       $(RM) $(NAME)
+
+shallow_re : shallow_fclean
+       $(MAKE) all
diff --git a/main.c b/main.c
new file mode 100644 (file)
index 0000000..cbab04c
--- /dev/null
+++ b/main.c
@@ -0,0 +1,283 @@
+#include "libft.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+typedef struct
+{
+       unsigned char   bytes[4];
+}                                      t_symbol;
+
+typedef struct
+{
+       t_symbol        preceding;
+       t_symbol        subsequent;
+}                              t_relation;
+
+size_t get_utf8_size(char c)
+{
+       if (~c & 0x80)
+       {
+               return (1);
+       }
+       if ((c & 0xF0) == 0xF0)
+       {
+               return (4);
+       }
+       if ((c & 0xF0) == 0xE0)
+       {
+               return (3);
+       }
+       if ((c & 0xF0) == 0xC0)
+       {
+               return (2);
+       }
+       return (0);
+}
+
+size_t get_symbol_size(t_symbol symbol)
+{
+       return (get_utf8_size(symbol.bytes[0]));
+}
+
+int    is_symbol_null(t_symbol symbol)
+{
+       return (symbol.bytes[0] == '\0');
+}
+
+void   copy_symbol(const char *string, t_symbol *symbol)
+{
+       ft_bzero(&symbol->bytes, sizeof(symbol->bytes));
+       ft_memcpy(&symbol->bytes, string, get_utf8_size(*string));
+       return ;
+}
+
+t_symbol       *decode_utf8(const char *string)
+{
+       t_symbol        *result;
+       size_t          i;
+
+       result = malloc((ft_strlen(string) + 1) * sizeof(t_symbol));
+       if (!result)
+       {
+               return (NULL);
+       }
+       i = 0;
+       while (*string)
+       {
+               copy_symbol(string, result + i);
+               string += get_symbol_size(result[i]);
+               ++i;
+       }
+       copy_symbol(string, result + i);
+       return (result);
+}
+
+int    is_same_symbol(t_symbol a, t_symbol b)
+{
+       int             ret;
+       size_t  i;
+
+       ret = 1;
+       i = 0;
+       while (i < sizeof(a.bytes) / sizeof(a.bytes[0]))
+       {
+               ret = ret && (a.bytes[i] == b.bytes[i]);
+               ++i;
+       }
+       return (ret);
+}
+
+int    get_relation(const char *first, const char *second, t_relation *relation)
+{
+       size_t          i;
+       t_symbol        *decoded_first;
+       t_symbol        *decoded_second;
+
+       decoded_first = decode_utf8(first);
+       decoded_second = decode_utf8(second);
+       if (!decoded_first || !decoded_first)
+       {
+               free(decoded_first);
+               free(decoded_second);
+               return (1);
+       }
+       i = 0;
+       while (is_same_symbol(decoded_first[i], decoded_second[i]))
+       {
+               ++i;
+       }
+       relation->preceding = decoded_first[i];
+       relation->subsequent = decoded_second[i];
+       free(decoded_first);
+       free(decoded_second);
+       return (0);
+}
+
+void   remove_invalid_relations(t_vec *relations)
+{
+       size_t                          i;
+       const t_relation        *relation;
+
+       i = relations->size;
+       while (i > 0)
+       {
+               --i;
+               relation = ft_vec_caccess(relations, i);
+               if (is_symbol_null(relation->subsequent)
+                               || is_symbol_null(relation->preceding))
+               {
+                       ft_vec_erase(relations, i, NULL);
+               }
+       }
+       return ;
+}
+
+int    create_relation_list(t_vec *relations, int fd)
+{
+       t_relation      relation;
+       char            *prev_word;
+       char            *word;
+
+       prev_word = get_next_line(fd);
+       word = get_next_line(fd);
+       while (word)
+       {
+               if (get_relation(prev_word, word, &relation)
+                               || ft_vec_append(relations, &relation))
+               {
+                       free(prev_word);
+                       free(word);
+                       return (1);
+               }
+               free(prev_word);
+               prev_word = word;
+               word = get_next_line(fd);
+       }
+       free(prev_word);
+       remove_invalid_relations(relations);
+       return (0);
+}
+
+t_symbol       find_symbol_that_only_precedes(const t_vec *relations)
+{
+       size_t                          i;
+       const t_relation        *relation;
+       t_symbol                        symbol;
+
+       relation = ft_vec_caccess(relations, 0);
+       symbol = relation->preceding;
+       i = 1;
+       while (i < relations->size)
+       {
+               relation = ft_vec_caccess(relations, i);
+               if (is_same_symbol(symbol, relation->subsequent))
+               {
+                       symbol = relation->preceding;
+                       i = 0;
+               }
+               ++i;
+       }
+       return (symbol);
+}
+
+void   remove_symbol_relations(t_vec *relations, t_symbol symbol)
+{
+       size_t                          i;
+       const t_relation        *relation;
+
+       i = relations->size;
+       while (i > 0)
+       {
+               --i;
+               relation = ft_vec_caccess(relations, i);
+               if (is_same_symbol(symbol, relation->preceding))
+               {
+                       ft_vec_erase(relations, i, NULL);
+               }
+       }
+       return ;
+}
+
+int    sort_alphabet(t_vec *relations, t_vec *alphabet)
+{
+       t_symbol                        symbol;
+       const t_relation        *relation;
+
+       while (relations->size > 1)
+       {
+               symbol = find_symbol_that_only_precedes(relations);
+               remove_symbol_relations(relations, symbol);
+               if (ft_vec_append(alphabet, &symbol))
+               {
+                       return (1);
+               }
+       }
+       relation = ft_vec_caccess(relations, 0);
+       if (ft_vec_append(alphabet, &relation->preceding)
+                       || ft_vec_append(alphabet, &relation->subsequent))
+       {
+               return (1);
+       }
+       return (0);
+}
+
+void   print_symbol(t_symbol symbol)
+{
+       write(STDOUT_FILENO, symbol.bytes, get_symbol_size(symbol));
+       return ;
+}
+
+void   print_alphabet(const t_vec *alphabet)
+{
+       size_t  i;
+
+       i = 0;
+       while (i < alphabet->size)
+       {
+               print_symbol(*(const t_symbol *)ft_vec_caccess(alphabet, i));
+               ++i;
+       }
+       write(STDOUT_FILENO, "\n", 1);
+       return ;
+}
+
+int main(int argc, char **argv)
+{
+       int             ret;
+       int             input_fd;
+       t_vec   relations;
+       t_vec   alphabet;
+
+       if (argc == 1)
+       {
+               input_fd = STDIN_FILENO;
+       }
+       else
+       {
+               input_fd = open(argv[1], O_RDONLY);
+               if (input_fd < 0)
+               {
+                       return (1);
+               }
+       }
+       ft_vec_init(&relations, sizeof(t_relation));
+       ft_vec_init(&alphabet, sizeof(t_symbol));
+       if (create_relation_list(&relations, input_fd) == 0
+                       && sort_alphabet(&relations, &alphabet) == 0)
+       {
+               print_alphabet(&alphabet);
+               ret = 0;
+       }
+       else
+       {
+               ret = 2;
+       }
+       ft_vec_free(&relations, NULL);
+       ft_vec_free(&alphabet, NULL);
+       if (input_fd != STDIN_FILENO)
+       {
+               close(input_fd);
+       }
+       return (ret);
+}