--- /dev/null
+checker
+push_swap
+*.o
--- /dev/null
+[submodule "Libft"]
+ path = Libft
+ url = git://ljiriste.work/Libft
--- /dev/null
+Subproject commit a4212a0f1de2cf7553f3cde8931c90fe006f3cd4
--- /dev/null
+CC := gcc
+#CFLAGS = -std=c99 -Wall -Wextra -Werror -Wpedantic
+CFLAGS = -Wall -Wextra -Werror -Wpedantic
+
+RM := rm -f
+
+SUBPROJECTS := Libft
+
+INCDIR := src_checker
+SUBINCDIR := $(addsuffix /inc, $(SUBPROJECTS));
+INCLUDE := $(addprefix -I, $(INCDIR) $(SUBINCDIR))
+
+CHECKSRCDIR := src_checker
+
+CHECKSOURCES := checker.c \
+ actions.c \
+ stack_manipulation.c \
+
+CHECKSOURCES := $(addprefix $(CHECKSRCDIR)/, $(CHECKSOURCES))
+
+CHECKOBJECTS := $(CHECKSOURCES:.c=.o)
+
+PUSHSRCDIR = src_push
+
+PUSHSOURCES := push.c \
+
+PUSHSOURCES := $(addprefix $(PUSHSRCDIR)/, $(PUSHSOURCES))
+
+PUSHOBJECTS := $(PUSHSOURCES:.c=.o)
+
+OBJECTS := $(PUSHOBJECTS) $(CHECKOBJECTS)
+
+NAME := push_swap checker
+
+all : $(NAME)
+
+debug : CFLAGS += -g
+debug : $(NAME)
+
+push_swap : $(PUSHOBJECTS) Libft/libft.a
+ $(CC) $(CFLAGS) -o $@ $^
+
+checker : $(CHECKOBJECTS) Libft/libft.a
+ $(CC) $(CFLAGS) -o $@ $^
+
+# Libft is not dependant on all subprojects (only itself)
+# but this shouldn't be a problem, as the project needs to download all anyway
+Libft/libft.a : | $(SUBINCDIR)
+ifneq (,$(findstring debug, $(MAKECMDGOALS)))
+ $(MAKE) -C Libft debug
+else
+ $(MAKE) -C Libft
+endif
+
+%.o : %.c
+ $(CC) $(CFLAGS) -o $@ -c $< $(INCLUDE)
+
+%/inc :
+ git submodule update --init $($@%/inc=%)
+
+clean :
+ $(RM) $(OBJECTS)
+ $(foreach proj, $(SUBPROJECTS), $(MAKE) -C $(proj) clean)
+
+fclean :
+ $(RM) $(OBJECTS)
+ $(RM) $(NAME)
+ $(foreach proj, $(SUBPROJECTS), $(MAKE) -C $(proj) fclean)
+
+re : fclean
+ $(MAKE) all
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* actions.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/24 11:46:02 by ljiriste #+# #+# */
+/* Updated: 2024/01/24 13:49:25 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "checker.h"
+
+void action_rotate(t_stacks *s, t_target target)
+{
+ if (target == a || target == both)
+ stack_rotate(&s->a, 1);
+ if (target == b || target == both)
+ stack_rotate(&s->b, 1);
+ return ;
+}
+
+void action_reverse_rotate(t_stacks *s, t_target target)
+{
+ if (target == a || target == both)
+ stack_rotate(&s->a, -1);
+ if (target == b || target == both)
+ stack_rotate(&s->b, -1);
+ return ;
+}
+
+void action_swap(t_stacks *s, t_target target)
+{
+ if (target == a || target == both)
+ stack_swap(&s->a);
+ if (target == b || target == both)
+ stack_swap(&s->b);
+ return ;
+}
+
+void action_push(t_stacks *s, t_target target)
+{
+ if ((target == a || target == both) && s->b.stack.size != 0)
+ {
+ stack_push(&s->a, stack_top(&s->b));
+ stack_pop(&s->b);
+ }
+ if ((target == b || target == both) && s->a.stack.size != 0)
+ {
+ stack_push(&s->b, stack_top(&s->a));
+ stack_pop(&s->a);
+ }
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* checker.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/24 10:31:06 by ljiriste #+# #+# */
+/* Updated: 2024/01/24 14:41:00 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "checker.h"
+#include "libft.h"
+#include <stdlib.h>
+
+#define COMMANDS_NUM 11
+
+static int command_parse(const char *input, t_command *command)
+{
+ const size_t len = ft_strlen(input);
+ const char *com_str[COMMANDS_NUM] = {"sa", "sb", "ss", "pa", "pb", "ra", "rb", "rr", "rra", "rrb", "rrr"};
+ size_t i;
+
+ i = 0;
+ while (1)
+ {
+ if (!ft_strcmp(input, com_str[i++]))
+ break ;
+ if (i == COMMANDS_NUM)
+ return (1);
+ }
+ if (len == 3)
+ command->action = action_reverse_rotate;
+ else if (input[0] == 's')
+ command->action = action_swap;
+ else if (input[0] == 'p')
+ command->action = action_push;
+ else if (input[0] == 'r')
+ command->action = action_rotate;
+ if (input[len - 1] == 'a')
+ command->target = a;
+ else if (input[len - 1] == 'b')
+ command->target = b;
+ else
+ command->target = both;
+ return (0);
+}
+
+static void execute(t_command command, t_stacks *s)
+{
+ command.action(s, command.target);
+ return ;
+}
+
+static int interpret(t_stacks *s)
+{
+ char *input;
+ t_command command;
+
+ input = get_next_line(0);
+ while (input)
+ {
+ input[ft_strlen(input) - 1] = '\0';
+ if (command_parse(input, &command))
+ {
+ free(input);
+ return (1);
+ }
+ execute(command, s);
+ free(input);
+ input = get_next_line(0);
+ }
+ return (0);
+}
+
+void init_stack(t_stack *s)
+{
+ ft_vec_init(&s->stack, sizeof(int));
+ s->ind = 0;
+ return ;
+}
+
+void free_stack(t_stack *s)
+{
+ ft_vec_free(&s->stack, NULL);
+ s->ind = 0;
+ return ;
+}
+
+int is_sorted(t_stack *s)
+{
+ const size_t start_ind = s->ind;
+ int prev;
+ int cur;
+
+ prev = stack_top(s);
+ stack_rotate(s, 1);
+ while (s->ind != start_ind)
+ {
+ cur = stack_top(s);
+ if (cur <= prev)
+ return (0);
+ prev = cur;
+ stack_rotate(s, 1);
+ }
+ return (1);
+}
+
+int is_int(const char *str)
+{
+ char *test;
+
+ test = ft_itoa(ft_atoi(str));
+ if (ft_strcmp(str, test))
+ {
+ free(test);
+ return (0);
+ }
+ free(test);
+ return (1);
+}
+
+int contains(int new, t_stack *s)
+{
+ const size_t start_ind = s->ind;
+ int cur;
+
+ if (s->stack.size == 0)
+ return (0);
+ cur = stack_top(s);
+ if (cur == new)
+ return (1);
+ stack_rotate(s, 1);
+ while (s->ind != start_ind)
+ {
+ cur = stack_top(s);
+ if (cur == new)
+ return (1);
+ stack_rotate(s, 1);
+ }
+ return (0);
+}
+
+int parse(int argc, char **argv, t_stack *s)
+{
+ size_t i;
+ int new;
+
+ if (argc == 1)
+ return (1);
+ i = 1;
+ while (i < (size_t)argc)
+ {
+ if (!is_int(argv[i]))
+ return (1);
+ new = ft_atoi(argv[i]);
+ if (contains(new, s))
+ return (1);
+ stack_push(s, new);
+ stack_rotate(s, 1);
+ ++i;
+ }
+ return (0);
+}
+
+void clean_up(t_stacks *s)
+{
+ free_stack(&s->a);
+ free_stack(&s->b);
+ return ;
+}
+
+int main(int argc, char **argv)
+{
+ t_stacks s;
+
+ init_stack(&s.a);
+ init_stack(&s.b);
+ if (parse(argc, argv, &s.a))
+ {
+ clean_up(&s);
+ ft_printf("Error.\n");
+ return (1);
+ }
+ if (interpret(&s))
+ {
+ clean_up(&s);
+ ft_printf("Error.\n");
+ return (1);
+ }
+ if (is_sorted(&s.a) && s.b.stack.size == 0)
+ ft_printf("OK\n");
+ else
+ ft_printf("KO\n");
+ clean_up(&s);
+ return (0);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* checker.h :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/24 12:13:51 by ljiriste #+# #+# */
+/* Updated: 2024/01/24 12:21:55 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#ifndef CHECKER_H
+# define CHECKER_H
+
+# include "libft.h"
+
+typedef struct s_stack
+{
+ t_vec stack;
+ size_t ind;
+} t_stack;
+
+typedef struct s_stacks
+{
+ t_stack a;
+ t_stack b;
+} t_stacks;
+
+typedef enum e_target
+{
+ a,
+ b,
+ both,
+} t_target;
+
+typedef void(t_action(t_stacks *s, t_target target));
+
+typedef struct s_command
+{
+ t_action *action;
+ t_target target;
+} t_command;
+
+t_action action_push;
+t_action action_swap;
+t_action action_rotate;
+t_action action_reverse_rotate;
+
+void stack_push(t_stack *s, int el);
+void stack_swap(t_stack *s);
+void stack_rotate(t_stack *s, int amount);
+void stack_pop(t_stack *s);
+int stack_top(t_stack *s);
+
+#endif //CHECKER_H
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* stack_manipulation.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/24 11:48:47 by ljiriste #+# #+# */
+/* Updated: 2024/01/24 13:59:25 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "checker.h"
+#include "libft.h"
+
+// conversions are meh
+// maybe it would be better to have size_t amount and third arg for direction
+void stack_rotate(t_stack *s, int amount)
+{
+ if (s->stack.size == 0)
+ return ;
+ while (amount < 0)
+ amount += s->stack.size;
+ if (s->ind > SIZE_MAX - (size_t)amount)
+ s->ind -= s->stack.size;
+ s->ind = (s->ind + amount) % s->stack.size;
+ return ;
+}
+
+// Not great, because one does not know whether
+// result of zero is error
+int stack_top(t_stack *s)
+{
+ if (s->stack.size == 0)
+ return (0);
+ return (*(int *)ft_vec_access(&s->stack, s->ind));
+}
+
+void stack_pop(t_stack *s)
+{
+ if (s->stack.size == 0)
+ return ;
+ ft_vec_forget(&s->stack, s->ind);
+ if (s->stack.size > 0)
+ s->ind %= s->stack.size;
+ return ;
+}
+
+void stack_push(t_stack *s, int el)
+{
+ ft_vec_insert(&s->stack, &el, s->ind);
+ return ;
+}
+
+void stack_swap(t_stack *s)
+{
+ int tmp;
+
+ if (s->stack.size <= 1)
+ return ;
+ tmp = stack_top(s);
+ stack_pop(s);
+ stack_rotate(s, 1);
+ stack_push(s, tmp);
+ stack_rotate(s, -1);
+ return ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* push.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/01/24 13:17:32 by ljiriste #+# #+# */
+/* Updated: 2024/01/24 13:18:17 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "libft.h"
+
+int main(void)
+{
+ ft_printf("TODO: Implement push_swap.\n");
+ return (0);
+}