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.
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))
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
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;
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 */
/* */
/* ************************************************************************** */
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
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* is_sorted.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2024/02/22 14:22:08 by ljiriste #+# #+# */
+/* Updated: 2024/02/22 14:37:15 by ljiriste ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "checker.h"
+#include <stddef.h>
+
+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);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* prepare.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 <stddef.h>
+
+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 ;
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* prints.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* 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 ;
+}
/* By: ljiriste <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <limits.h>
+
+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);
}