From: Lukas Jiriste Date: Fri, 23 Feb 2024 09:36:57 +0000 (+0100) Subject: Implement a sorting algorithm X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=564690168c990f37598a89a51d4263661eb036bf;p=42%2Fpush_swap.git Implement a sorting algorithm The idea is to push everything except for 3 elements from a to b. Stack a can then be trivially sorted after which we can insert (the cheapest) elements from b to the correct place in a. The implementation needs to be refined as it does not actually sort. --- diff --git a/Makefile b/Makefile index 80d1055..3044f30 100644 --- a/Makefile +++ b/Makefile @@ -19,12 +19,20 @@ CHECKSOURCES := checker.c \ stack_manipulation.c \ arg_parsing.c \ stacks_mem.c \ + is_sorted.c \ CHECKSOURCES := $(addprefix $(CHECKSRCDIR)/, $(CHECKSOURCES)) CHECKOBJECTS := $(CHECKSOURCES:.c=.o) PUSHSOURCES := push.c \ + arg_parsing.c \ + stack_manipulation.c \ + stacks_mem.c \ + actions.c \ + prints.c \ + is_sorted.c \ + prepare.c \ PUSHSOURCES := $(addprefix $(PUSHSRCDIR)/, $(PUSHSOURCES)) diff --git a/src/checker.c b/src/checker.c index 77b6152..7e429ef 100644 --- a/src/checker.c +++ b/src/checker.c @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/01/24 10:31:06 by ljiriste #+# #+# */ -/* Updated: 2024/02/06 14:21:13 by ljiriste ### ########.fr */ +/* Updated: 2024/02/22 14:27:20 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -83,25 +83,6 @@ static int interpret(t_stacks *s) return (0); } -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 main(int argc, char **argv) { t_stacks s; diff --git a/src/checker.h b/src/checker.h index e03b18f..2b7f3d7 100644 --- a/src/checker.h +++ b/src/checker.h @@ -6,7 +6,7 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/01/24 12:13:51 by ljiriste #+# #+# */ -/* Updated: 2024/02/06 14:22:08 by ljiriste ### ########.fr */ +/* Updated: 2024/02/23 09:48:21 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ @@ -56,11 +56,20 @@ void action_swap(t_stacks *s, t_target target); void action_rotate(t_stacks *s, t_target target); void action_reverse_rotate(t_stacks *s, t_target target); +void print_push(t_stacks *s, t_target target); +void print_swap(t_stacks *s, t_target target); +void print_rotate(t_stacks *s, t_target target); +void print_reverse_rotate(t_stacks *s, t_target target); + 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); +int is_sorted(t_stack *s); int parse(int argc, char **argv, t_stack *s); + +void prepare_stacks(t_stacks *s, size_t ind_a, size_t ind_b); +size_t cost(t_stacks *s, const size_t b_plus, const size_t a_plus); #endif //CHECKER_H diff --git a/src/is_sorted.c b/src/is_sorted.c new file mode 100644 index 0000000..3029920 --- /dev/null +++ b/src/is_sorted.c @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* is_sorted.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/22 14:22:08 by ljiriste #+# #+# */ +/* Updated: 2024/02/22 14:37:15 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "checker.h" +#include + +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); +} diff --git a/src/prepare.c b/src/prepare.c new file mode 100644 index 0000000..51e4c1f --- /dev/null +++ b/src/prepare.c @@ -0,0 +1,126 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prepare.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/23 09:35:45 by ljiriste #+# #+# */ +/* Updated: 2024/02/23 09:54:39 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "checker.h" +#include "libft.h" +#include + +static void prepare_plus_together(t_stacks *s, size_t rot_a, size_t rot_b) +{ + size_t i; + + i = 0; + while (i < ft_mins(rot_a, rot_b)) + { + print_rotate(s, both); + ++i; + } + if (rot_a > rot_b) + { + while (i < rot_a) + { + print_rotate(s, a); + ++i; + } + } + else + { + while (i < rot_b) + { + print_rotate(s, b); + ++i; + } + } + return ; +} + +static void prepare_minus_together(t_stacks *s, size_t rot_a, size_t rot_b) +{ + size_t i; + + i = 0; + while (i < ft_mins(rot_a, rot_b)) + { + print_reverse_rotate(s, both); + ++i; + } + if (rot_a > rot_b) + { + while (i < rot_a) + { + print_reverse_rotate(s, a); + ++i; + } + } + else + { + while (i < rot_b) + { + print_reverse_rotate(s, b); + ++i; + } + } + return ; +} + +static void prepare_a_plus_against(t_stacks *s, size_t rot_a, size_t rot_b) +{ + size_t i; + + i = 0; + while (i < rot_a) + { + print_rotate(s, a); + ++i; + } + i = 0; + while (i < rot_b) + { + print_reverse_rotate(s, b); + ++i; + } + return ; +} + +static void prepare_a_minus_against(t_stacks *s, size_t rot_a, size_t rot_b) +{ + size_t i; + + i = 0; + while (i < rot_a) + { + print_reverse_rotate(s, a); + ++i; + } + i = 0; + while (i < rot_b) + { + print_rotate(s, b); + ++i; + } + return ; +} + +void prepare_stacks(t_stacks *s, size_t ind_a, size_t ind_b) +{ + const size_t c = cost(s, ind_b, ind_a); + + if (c == ft_maxs(ind_a, ind_b)) + prepare_plus_together(s, ind_a, ind_b); + else if (c == ft_maxs(s->a.stack.size - ind_a, s->b.stack.size - ind_b)) + prepare_minus_together(s, s->a.stack.size - ind_a, s->b.stack.size - ind_b); + else if (c == ind_a + (s->b.stack.size - ind_b)) + prepare_a_plus_against(s, ind_a, s->b.stack.size - ind_b); + else + prepare_a_minus_against(s, s->a.stack.size - ind_a, ind_b); + return ; +} diff --git a/src/prints.c b/src/prints.c new file mode 100644 index 0000000..9fe9b5a --- /dev/null +++ b/src/prints.c @@ -0,0 +1,50 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* prints.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ljiriste +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/02/15 14:42:01 by ljiriste #+# #+# */ +/* Updated: 2024/02/15 14:50:40 by ljiriste ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "checker.h" + +char target_to_char(t_target target, char both) +{ + if (target == a) + return ('a'); + if (target == b) + return ('b'); + return (both); +} + +void print_push(t_stacks *s, t_target target) +{ + ft_printf("p%c ", target_to_char(target, 'p')); + action_push(s, target); + return ; +} + +void print_rotate(t_stacks *s, t_target target) +{ + ft_printf("r%c ", target_to_char(target, 'r')); + action_rotate(s, target); + return ; +} + +void print_reverse_rotate(t_stacks *s, t_target target) +{ + ft_printf("rr%c ", target_to_char(target, 'r')); + action_reverse_rotate(s, target); + return ; +} + +void print_swap(t_stacks *s, t_target target) +{ + ft_printf("s%c ", target_to_char(target, 's')); + action_swap(s, target); + return ; +} diff --git a/src/push.c b/src/push.c index 5184574..fcb1e93 100644 --- a/src/push.c +++ b/src/push.c @@ -6,14 +6,186 @@ /* By: ljiriste +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/01/24 13:17:32 by ljiriste #+# #+# */ -/* Updated: 2024/01/24 13:18:17 by ljiriste ### ########.fr */ +/* Updated: 2024/02/23 10:15:20 by ljiriste ### ########.fr */ /* */ /* ************************************************************************** */ +// This program works with t_stack +// It uses "print" functions for stack manipulations +// One may only use "non-print" stack manipulation in a case where +// the stacks return to their state, so as not to skew the output + +#include "checker.h" #include "libft.h" +#include + +void a_sort_three_or_less(t_stacks *s) +{ + int last; + int max; + size_t steps_to_smaller; + size_t i; + + i = 0; + last = stack_top(&s->a); + max = INT_MIN; + steps_to_smaller = 0; + while (i < s->a.stack.size) + { + stack_rotate(&s->a, 1); + steps_to_smaller += (stack_top(&s->a) < last); + last = stack_top(&s->a); + if (max < stack_top(&s->a)) + max = stack_top(&s->a); + ++i; + } + if (steps_to_smaller == 2) + print_swap(s, a); + if (max == stack_top(&s->a) && !is_sorted(&s->a)) + print_rotate(s, a); + else if (!is_sorted(&s->a)) + print_reverse_rotate(s, a); + return ; +} + +size_t find_target_ind(t_stack *stack, int val) +{ + size_t cur_step; + const size_t initial_ind = stack->ind; + size_t res; + + cur_step = stack->stack.size / 2; + stack_rotate(stack, cur_step); + while (cur_step > 1) + { + cur_step /= 2; + if (stack_top(stack) < val) + stack_rotate(stack, cur_step); + else + stack_rotate(stack, -cur_step); + } + if (stack->ind > initial_ind) + res = (stack->ind - initial_ind); + else + res = stack->stack.size + stack->ind - initial_ind; + stack->ind = initial_ind; + return (res); +} + +// Let's split the stacks by the index of the current value +// +// a b +// | | +// | a+ | +// | | +// | | b+ +// --- | +// | | +// | | +// | | +// | a- --- +// | | +// | | b- +// | | +// +// Either we have to stack_rotate both in the same direction +// in which case the cost is the higher of those +// - max(a+, b+) or max(a-, b-) +// Or we have to stack_rotate them in the opposite direction +// in which case we have to add the moves +// - a+ + b- or a- + b+ +// +// The minimum cost is the lowest of these four values +size_t cost(t_stacks *s, const size_t b_plus, const size_t a_plus) +{ + size_t res; + const size_t a_minus = s->a.stack.size - a_plus; + const size_t b_minus = s->b.stack.size - b_plus; + + res = ft_maxs(a_plus, b_plus); + res = ft_mins(res, ft_maxs(a_minus, b_minus)); + res = ft_mins(res, a_plus + b_minus); + res = ft_mins(res, a_minus + b_plus); + return (res); +} -int main(void) +size_t find_best(t_stacks *s, t_vec *target_a_indeces) { - ft_printf("TODO: Implement push_swap.\n"); + size_t res_ind; + size_t cur; + size_t best; + size_t i; + + best = SIZE_MAX; + i = 0; + while (i < s->b.stack.size) + { + cur = cost(s, i, *(size_t *)ft_vec_access(target_a_indeces, i)); + if (cur < best) + { + res_ind = i; + best = cur; + } + ++i; + } + return (res_ind); +} + +void get_push_indeces(t_stacks *s, int *ind_a, int *ind_b) +{ + t_vec target_a_indeces; + size_t target; + size_t i; + + ft_vec_init(&target_a_indeces, sizeof(size_t)); + i = 0; + while (i < s->b.stack.size) + { + target = find_target_ind(&s->a, stack_top(&s->b)); + ft_vec_append(&target_a_indeces, &target); + stack_rotate(&s->b, 1); + ++i; + } + *ind_b = find_best(s, &target_a_indeces); + stack_rotate(&s->b, *ind_b); + *ind_a = find_target_ind(&s->a, stack_top(&s->b)); + stack_rotate(&s->b, -*ind_b); + ft_vec_free(&target_a_indeces, NULL); + return ; +} + +void sort(t_stacks *s) +{ + int ind_a; + int ind_b; + + while (s->a.stack.size > 3) + { + print_push(s, b); + } + a_sort_three_or_less(s); + while (s->b.stack.size > 0) + { + get_push_indeces(s, &ind_a, &ind_b); + prepare_stacks(s, ind_a, ind_b); + print_push(s, a); + } + 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); + } + sort(&s); + clean_up(&s); return (0); }