From d8334be1865982cf07f436c5dbb75f3b479b3c1e Mon Sep 17 00:00:00 2001 From: Robert Bright Date: Sat, 17 Oct 2020 02:06:31 +0100 Subject: [PATCH 1/2] add 2 libft function --- libft/ft_strchr.c | 29 +++++++++++++++++++++++++++++ libft/ft_strequ.c | 26 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 libft/ft_strchr.c create mode 100644 libft/ft_strequ.c diff --git a/libft/ft_strchr.c b/libft/ft_strchr.c new file mode 100644 index 0000000..7c4a5e5 --- /dev/null +++ b/libft/ft_strchr.c @@ -0,0 +1,29 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strchr.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fokrober +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/04/12 23:06:57 by fokrober #+# #+# */ +/* Updated: 2019/04/23 19:50:24 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +char *ft_strchr(const char *s, int c) +{ + int i; + + i = 0; + while (s[i]) + { + if (s[i] == (char)c) + return (((char*)s + i)); + i++; + } + if (s[i] == (char)c) + return ((char*)s + i); + return (NULL); +} diff --git a/libft/ft_strequ.c b/libft/ft_strequ.c new file mode 100644 index 0000000..ccf8b58 --- /dev/null +++ b/libft/ft_strequ.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ft_strequ.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fokrober +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2019/04/11 05:19:54 by fokrober #+# #+# */ +/* Updated: 2020/10/17 01:59:01 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +int ft_strequ(char const *s1, char const *s2) +{ + if (!s1 || !s2) + return (0); + if (*s1 && *s2) + { + if (*s1 != *s2) + return (0); + (void)(s1++ && s2++); + } + return (*s1 == *s2); +} From 2f6b00ee35e7684ea60457ec5e29b7487aacc93c Mon Sep 17 00:00:00 2001 From: Robert Bright Date: Sat, 17 Oct 2020 02:50:25 +0100 Subject: [PATCH 2/2] first release of the parser --- Makefile | 5 +- include/lem_in.h | 13 +++-- include/libft.h | 4 +- libft/Makefile | 9 ++-- src/get_data.c | 63 ++++++++++++++++++++++- src/hashmap.c | 117 ++++++++++++++++++++++++++++++++++++++++++ src/lem_in.c | 98 ++++++++++++++++++++++++++++++++--- src/parser.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++ src/sort_list.c | 82 ++++++++++++++++++++++++++++++ src/tools.c | 87 +++++++++++++++++++++++++++++++ 10 files changed, 588 insertions(+), 20 deletions(-) create mode 100644 src/hashmap.c create mode 100644 src/parser.c create mode 100644 src/sort_list.c create mode 100644 src/tools.c diff --git a/Makefile b/Makefile index 46d917f..9339372 100644 --- a/Makefile +++ b/Makefile @@ -6,12 +6,13 @@ # By: bob +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/04/15 15:46:07 by bob #+# #+# # -# Updated: 2020/10/16 05:18:33 by fokrober ### ########.fr # +# Updated: 2020/10/17 02:35:31 by fokrober ### ########.fr # # # # **************************************************************************** # NAME = lem-in -SRC = $(addprefix src/, lem_in.c get_data.c) +SRC = $(addprefix src/, lem_in.c get_data.c hashmap.c parser.c \ + sort_list.c tools.c) HEADER = $(addprefix include/, lem_in.h) OBJ = $(SRC:.c=.o) LFTDIR = ./libft diff --git a/include/lem_in.h b/include/lem_in.h index bd124f4..ef70538 100644 --- a/include/lem_in.h +++ b/include/lem_in.h @@ -6,7 +6,7 @@ /* By: bob +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/22 12:49:48 by bob #+# #+# */ -/* Updated: 2020/10/16 05:28:17 by fokrober ### ########.fr */ +/* Updated: 2020/10/17 02:36:55 by fokrober ### ########.fr */ /* */ /* ************************************************************************** */ @@ -30,9 +30,10 @@ # define MAX_LLONG 18446744073709551615 # define SPACE " \t" # include -# include +# include "libft.h" # include # include +# include typedef struct s_hash t_hash; typedef struct s_edge t_edge; @@ -42,7 +43,7 @@ typedef struct s_env t_env; struct s_edge { - t_node *child; + t_node *to; int flow; t_edge *next; }; @@ -93,8 +94,12 @@ struct s_env t_env *farmdata(void); int parser(t_env *env); t_hash *create_hash(size_t size); -int save_node(t_env *env, char *name); t_node *get_node(t_env *env, char *name); +int save_node(t_env *env, char *name); int save_link(t_env *env, char *link); int get_data(t_env *env, char *line, int type); +void sort_edges(t_edge **head, t_env *env); +int x_isalpha(char *s, char *end); +int isnumber(char *s, char *end); +int add_edge(t_node *node, t_node *to); #endif diff --git a/include/libft.h b/include/libft.h index b82338f..0ecc997 100644 --- a/include/libft.h +++ b/include/libft.h @@ -6,7 +6,7 @@ /* By: mzaboub +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/03/29 23:32:55 by mzaboub #+# #+# */ -/* Updated: 2020/10/16 05:29:07 by fokrober ### ########.fr */ +/* Updated: 2020/10/17 02:36:10 by fokrober ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,8 @@ void ft_putstr(char const *str); void ft_putnbr(int n); void ft_putendl_fd(char *s, int fd); int ft_strnequ(char const *s1, char const *s2, size_t n); +int ft_strequ(char const *s1, char const *s2); +char *ft_strchr(char const *s1, int c); int ft_atoi(const char *str); void *ft_memalloc(size_t size); void *ft_memcpy(void *dst, const void *src, size_t n); diff --git a/libft/Makefile b/libft/Makefile index 2326633..d993a0b 100644 --- a/libft/Makefile +++ b/libft/Makefile @@ -6,13 +6,14 @@ # By: bob +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2020/04/15 22:00:03 by bob #+# #+# # -# Updated: 2020/10/16 03:50:00 by fokrober ### ########.fr # +# Updated: 2020/10/17 02:12:27 by fokrober ### ########.fr # # # # **************************************************************************** # NAME = libft.a SRC = ft_putstr.c ft_putnbr.c ft_putendl_fd.c ft_strnequ.c ft_strsub.c \ - ft_memcpy.c ft_memalloc.c ft_memdel.c ft_atoi.c ft_bzero.c + ft_memcpy.c ft_memalloc.c ft_memdel.c ft_atoi.c ft_bzero.c ft_strchr.c \ + ft_strequ.c HEADER = libft.h OBJ = $(SRC:.c=.o) ARFLAGS = rcsu @@ -31,12 +32,12 @@ $(NAME): prompt $(OBJ) $(HEADER) @echo "\n\n$(GREEN) > $(NAME) built !\n$(RESET)" prompt: - @echo -n " > $(NAME) building" + @printf " > $(NAME) building" %.o: %.c $(HEADER) @$(CC) $(CFLAGS) $< -o $@ @ar $(ARFLAGS) $(NAME) $@ - @echo ".\c" + @printf "." clean: @$(RM) $(OBJ) diff --git a/src/get_data.c b/src/get_data.c index e78ead0..383bea0 100644 --- a/src/get_data.c +++ b/src/get_data.c @@ -6,12 +6,73 @@ /* By: bob +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2020/04/26 16:49:07 by bob #+# #+# */ -/* Updated: 2020/10/16 05:29:49 by fokrober ### ########.fr */ +/* Updated: 2020/10/17 02:37:24 by fokrober ### ########.fr */ /* */ /* ************************************************************************** */ #include "lem_in.h" +static int save_rooms(t_env *env, char *line, int type) +{ + int i; + char *tmp; + + i = 0; + while (line[i] && line[i] != ' ') + i++; + if (!(tmp = ft_strsub(line, 0, i))) + return (SYS_ERROR); + type == START ? (env->start = tmp) : 0; + type == END ? (env->end = tmp) : 0; + return (save_node(env, tmp)); +} + +static int check_rooms(char *s) +{ + int res[3]; + int pos; + int i; + + pos = 0; + i = -1; + ft_bzero(res, 3 * sizeof(int)); + while (s[++i] && pos < 5) + { + if (!pos && s[0] != 'L') + res[pos] = x_isalpha(s, SPACE); + if (pos && pos % 2 == 0) + res[pos / 2] = isnumber(&s[i], SPACE); + if (!pos || !(pos % 2)) + { + if (!res[pos ? pos / 2 : pos]) + return (FALSE); + i += res[pos ? pos / 2 : pos]; + pos += 1; + } + if ((pos && pos % 2) && (s[i] == ' ' || s[i] == '\t')) + pos += (s[i + 1] != ' ' && s[i + 1] != '\t'); + } + return (res[0] && (res[1] && res[2])); +} + +int get_data(t_env *env, char *line, int type) +{ + static int prev; + int ret; + + if (!env->hash && !(env->hash = create_hash(HASH_SIZE))) + return (SYS_ERROR); + if (!prev) + { + if (check_rooms(line)) + return (save_rooms(env, line, type)); + ret = save_link(env, line); + prev = !ret; + return (!prev ? INVALID_LINE : ret); + } + return (save_link(env, line)); +} + static int pushdata(t_env *env, char *farm, int ret) { char *tmp; diff --git a/src/hashmap.c b/src/hashmap.c new file mode 100644 index 0000000..3a416de --- /dev/null +++ b/src/hashmap.c @@ -0,0 +1,117 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* hashmap.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: bob +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/25 23:35:28 by bob #+# #+# */ +/* Updated: 2020/10/17 02:31:07 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "lem_in.h" + +t_hash *create_hash(size_t size) +{ + t_hash *hash; + size_t i; + + hash = (t_hash*)malloc(sizeof(t_hash)); + if (hash) + hash->tab = (t_node**)malloc(sizeof(t_node*) * size); + if (!hash || !hash->tab) + return (NULL); + hash->size = size; + i = -1; + while (++i < size) + hash->tab[i] = NULL; + return (hash); +} + +static int hash_calc(t_hash *hash, char *key) +{ + size_t result; + size_t tmp; + int prev; + + if (!key) + return (-1); + result = 0; + prev = 1; + while (*key) + { + tmp = ((*key * 0x80200802ULL) & 0x0884422110ULL); + result += ((tmp * (key[1] + prev)) % hash->size); + prev += *key; + key++; + } + result = result >= hash->size ? result % hash->size : result; + return (result); +} + +t_node *get_node(t_env *env, char *name) +{ + int pos; + t_node *tmp; + + pos = hash_calc(env->hash, name); + if (pos < 0) + return (NULL); + tmp = env->hash->tab[pos]; + while (tmp) + { + if (ft_strequ(tmp->name, name)) + return (tmp); + tmp = tmp->next; + } + return (NULL); +} + +int save_node(t_env *env, char *name) +{ + int pos; + t_node *tmp; + t_node *prev; + + if ((pos = hash_calc(env->hash, name)) < 0) + return (pos); + prev = env->hash->tab[pos]; + tmp = prev; + while (tmp) + { + if (ft_strequ(tmp->name, name)) + return (OK); + tmp = tmp->next; + } + if (!(tmp = (t_node*)malloc(sizeof(t_node)))) + return (SYS_ERROR); + tmp->id = 0; + tmp->name = name; + tmp->links = NULL; + tmp->lck = 0; + tmp->next = prev; + env->hash->tab[pos] = tmp; + env->size += 1; + return (OK); +} + +int save_link(t_env *env, char *link) +{ + t_node *node1; + t_node *node2; + char *room2; + int ret; + + if (!(room2 = ft_strchr(link, '-'))) + return (INVALID_LINE); + *room2 = '\0'; + node1 = get_node(env, link); + node2 = get_node(env, room2 + 1); + if (!node1 || !node2) + return (INVALID_LINE); + ret = OK; + ret = add_edge(node1, node2); + ret == OK ? (ret = add_edge(node2, node1)) : ret; + return (ret); +} diff --git a/src/lem_in.c b/src/lem_in.c index bf40ba1..786d127 100644 --- a/src/lem_in.c +++ b/src/lem_in.c @@ -3,20 +3,102 @@ /* ::: :::::::: */ /* lem_in.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: fokrober +#+ +:+ +#+ */ +/* By: bob +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2020/10/16 05:19:43 by fokrober #+# #+# */ -/* Updated: 2020/10/16 05:40:29 by fokrober ### ########.fr */ +/* Created: 2020/04/22 12:40:55 by bob #+# #+# */ +/* Updated: 2020/10/17 02:43:47 by fokrober ### ########.fr */ /* */ /* ************************************************************************** */ #include "lem_in.h" -int main(void) +static t_node **chrooms_to_nodes(t_env *env) { - t_env *env; + t_node **nodes; + t_node *node; + int at; + size_t i; - env = farmdata(); - ft_putendl_fd(env->farm, 2); - return (0); + if (!(nodes = (t_node**)malloc(env->size * sizeof(t_node*)))) + return (NULL); + nodes[START] = get_node(env, env->start); + nodes[END] = get_node(env, env->end); + i = -1; + at = END; + while (++i < env->hash->size) + { + node = env->hash->tab[i]; + while (node) + { + if (node != nodes[END] && node != nodes[START]) + { + nodes[++at] = node; + node->id = at; + } + node = node->next; + } + } + return (nodes); +} + +static void begin_with_end(t_node **nodes, t_env *env) +{ + t_edge *tmp; + + env->sort = 1; + tmp = nodes[END]->links; + while (tmp) + { + sort_edges(&tmp->to->links, env); + tmp = tmp->next; + } +} + +static t_node **init(t_node **nodes, t_env *env) +{ + int i; + + nodes = chrooms_to_nodes(env); + ft_memdel((void**)&env->hash->tab); + ft_memdel((void**)&env->hash); + if (!env || !nodes) + exit(EXIT_FAILURE); + env->next = (int *)malloc(env->size * sizeof(int)); + env->check = (int *)malloc(env->size * sizeof(int)); + env->dist = (int*)malloc(env->size * sizeof(int)); + env->prev = (int*)malloc(env->size * sizeof(int)); + if (!env->next || !env->prev || !env->dist || !env->check) + exit(EXIT_FAILURE); + i = -1; + nodes[END]->id = END; + env->q = ft_memalloc(sizeof(t_queue)); + while (++i < env->size) + { + env->dist[i] = i == 1 ? 0 : INT_MAX; + env->next[i] = FALSE; + env->check[i] = FALSE; + env->prev[i] = -1; + } + begin_with_end(nodes, env); + return (nodes); +} + +int main(void) +{ + t_node **nodes; + t_env *env; + int ret; + + env = farmdata(); + if ((ret = parser(env))) + { + (ret == INVALID_DATA) ? write(STDOUT, "ERROR", 5) : + write(STDOUT, env->farm, env->len); + write(STDOUT, "\n", 1); + return (ret); + } + if (!env->start || !env->end) + return (write(STDOUT, "ERROR\n", 6)); + nodes = init(NULL, env); + return (ret); } diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 0000000..7891c44 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,130 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* parser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: bob +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/04/22 12:44:44 by bob #+# #+# */ +/* Updated: 2020/10/17 02:37:50 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "lem_in.h" + +int x_isalpha(char *s, char *end) +{ + int i; + int j; + + i = 0; + if (s == NULL) + return (FALSE); + while (s[i]) + { + j = -1; + while (end[++j]) + { + if (end[j] == s[i]) + return (i); + } + if (s[i] > 32 && s[i] < 127) + i++; + else + return (FALSE); + } + return (i); +} + +int isnumber(char *s, char *end) +{ + int i; + int j; + + i = 0; + if (s == NULL) + return (FALSE); + i = (s[i] == '+' || s[i] == '-'); + while (s[i] && i < 20) + { + j = -1; + while (end[++j]) + { + if (end[j] == s[i]) + return (i); + } + if (!(s[i] >= '0' && s[i] <= '9')) + return (FALSE); + i++; + } + if (i == 20 && s[0] != '1') + return (FALSE); + return (i); +} + +int check_ants(t_env *env, char *line) +{ + if (isnumber(line, SPACE)) + env->ants = ft_atoi(line); + else + return (INVALID_DATA); + if (!env->ants) + return (INVALID_SIZE); + if (env->ants < 0) + return (INVALID_DATA); + return (FALSE); +} + +int farmline(t_env *env, char **line, int *type) +{ + static int pos; + static int jump; + int start; + int len; + + pos = jump; + start = pos; + if (env->farm[start] == '\0') + return (FALSE); + while (env->farm[pos] && env->farm[pos] != '\n') + pos += 1; + jump = pos + 1; + len = pos - start; + if (len && ft_strnequ("##start", &env->farm[start], len)) + (void)((*type < 0 ? (*type = START) : 0) + || farmline(env, line, type)); + else if (len && ft_strnequ("##end", &env->farm[start], len)) + (void)((*type < 0 ? (*type = END) : 1) + && farmline(env, line, type)); + else if (env->farm[start] == '#') + farmline(env, line, type); + else if (!(*line = ft_strsub(env->farm, start, len))) + return (-1); + return (pos); +} + +int parser(t_env *env) +{ + char *line; + int ret; + int type; + int pos; + + ret = env ? OK : SYS_ERROR; + type = -1; + line = NULL; + while ((!ret && (pos = farmline(env, &line, &type)) > 0) && line) + { + if (env->ants && (ret = get_data(env, line, type))) + { + env->len = (ret == INVALID_LINE) ? pos : 0; + break ; + } + if (!env->ants && (ret = check_ants(env, line)) + > INVALID_SIZE) + break ; + type = -1; + ft_memdel((void**)&line); + } + return (pos < 0 ? pos : ret); +} diff --git a/src/sort_list.c b/src/sort_list.c new file mode 100644 index 0000000..c8483e2 --- /dev/null +++ b/src/sort_list.c @@ -0,0 +1,82 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* sort_list.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: bob +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/07/06 09:36:15 by bob #+# #+# */ +/* Updated: 2020/10/17 01:56:11 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "lem_in.h" + +static t_edge *get_tail(t_edge *head) +{ + t_edge *tmp; + + tmp = head; + while (head) + { + tmp = head; + head = head->next; + } + return (tmp); +} + +static t_edge *pivot(t_env *env, t_edge *head, t_edge *end, t_edge **tail) +{ + t_edge **tmp; + t_edge *cur; + + tmp = &head; + cur = head; + *tail = end; + while (cur != end) + { + if (env->dist[cur->to->id] > env->dist[end->to->id]) + { + *tmp = cur->next; + (*tail)->next = cur; + *tail = cur; + (*tail)->next = NULL; + cur = *tmp; + continue ; + } + tmp = &cur->next; + cur = cur->next; + } + return (head); +} + +static t_edge *sort_recur(t_edge *head, t_edge *end, t_env *env) +{ + t_edge *tail; + t_edge *tmp; + + if (!head || head == end) + return (head); + head = pivot(env, head, end, &tail); + if (head == end) + head->next = sort_recur(head->next, tail, env); + else + { + tmp = head; + while (tmp->next != end) + tmp = tmp->next; + tmp->next = NULL; + head = sort_recur(head, tmp, env); + end->next = sort_recur(end->next, tail, env); + tmp = get_tail(head); + tmp->next = end; + } + return (head); +} + +void sort_edges(t_edge **head, t_env *env) +{ + if (!head || !*head) + return ; + *head = sort_recur(*head, get_tail(*head), env); +} diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..51511e1 --- /dev/null +++ b/src/tools.c @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* queue_tools.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: bob +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2020/08/05 17:12:40 by bob #+# #+# */ +/* Updated: 2020/10/17 02:26:53 by fokrober ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "lem_in.h" + +int enqueue_node(t_queue *q, t_node *elem) +{ + t_node *prev; + + if (!q->start) + { + q->start = elem; + q->back = elem; + q->front = elem; + } + else if (q->back) + { + prev = (t_node *)q->back; + prev->next = elem; + q->back = elem; + if (!q->front) + q->front = q->back; + } + return (TRUE); +} + +t_node *dequeue_node(t_queue *q) +{ + t_node *node; + + node = q->front; + if (q->front == q->back) + q->front = NULL; + else if (node) + q->front = node->next; + return (node); +} + +int set_flow(t_node **nodes, int from, int to, int val) +{ + t_edge *edge; + + edge = nodes[from]->links; + while (edge) + { + if (edge->to->id == to) + { + edge->flow = val; + break ; + } + edge = edge->next; + } + return (TRUE); +} + +int add_edge(t_node *node, t_node *to) +{ + t_edge *edge; + t_edge **prev; + + edge = node->links; + prev = &node->links; + while (edge) + { + if (edge->to == to) + return (OK); + prev = &edge->next; + edge = edge->next; + } + edge = (t_edge*)malloc(sizeof(t_edge)); + if (!edge) + return (SYS_ERROR); + edge->to = to; + edge->flow = 0; + edge->next = NULL; + *prev = edge; + return (OK); +}