Implement a sorting algorithm
authorLukas Jiriste <ljiriste@student.42prague.com>
Fri, 23 Feb 2024 09:36:57 +0000 (10:36 +0100)
committerLukas Jiriste <ljiriste@student.42prague.com>
Fri, 23 Feb 2024 09:36:57 +0000 (10:36 +0100)
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.

Makefile
src/checker.c
src/checker.h
src/is_sorted.c [new file with mode: 0644]
src/prepare.c [new file with mode: 0644]
src/prints.c [new file with mode: 0644]
src/push.c

index 80d1055ade43cd533f680d26f880bd1b1cfef8a2..3044f308e2baac53a28ebbb95ed82d1e39692571 100644 (file)
--- 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))
 
index 77b61526c4f07a36cc0d67717650168ab4982c4e..7e429eff39f4c3bce9f2a8df9db35c51659794ba 100644 (file)
@@ -6,7 +6,7 @@
 /*   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       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -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;
index e03b18fcd524ddde201cfe7042f3d8e2b324df06..2b7f3d7166e8584fde3d51bb5d0f852dca61456d 100644 (file)
@@ -6,7 +6,7 @@
 /*   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       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -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 (file)
index 0000000..3029920
--- /dev/null
@@ -0,0 +1,33 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   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);
+}
diff --git a/src/prepare.c b/src/prepare.c
new file mode 100644 (file)
index 0000000..51e4c1f
--- /dev/null
@@ -0,0 +1,126 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   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 ;
+}
diff --git a/src/prints.c b/src/prints.c
new file mode 100644 (file)
index 0000000..9fe9b5a
--- /dev/null
@@ -0,0 +1,50 @@
+/* ************************************************************************** */
+/*                                                                            */
+/*                                                        :::      ::::::::   */
+/*   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 ;
+}
index 5184574e0e67e83f5ea59617410a966ee6a55afb..fcb1e93e367588e900d7c763869203b9783154e8 100644 (file)
 /*   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);
 }