From: Lukáš Jiřiště Date: Sun, 25 Jan 2026 17:58:57 +0000 (+0100) Subject: Implement a solution to the challenge X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=refs%2Fheads%2Ftrunk;p=SO_Challenges%2F15.git Implement a solution to the challenge --- ef23748de00e4d62c4d41d89fb2bfb264dedd727 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..626d139 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Libft"] + path = Libft + url = git://ljiriste.work/Libft diff --git a/Libft b/Libft new file mode 160000 index 0000000..30f8df1 --- /dev/null +++ b/Libft @@ -0,0 +1 @@ +Subproject commit 30f8df1bfda39333988817e9f5312e71905dbc34 diff --git a/Makefile b/Makefile new file mode 100644 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 index 0000000..cbab04c --- /dev/null +++ b/main.c @@ -0,0 +1,283 @@ +#include "libft.h" +#include +#include +#include + +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); +}