NAME=push_swap
-SRCS=algorithm_leafsort.c algorithm_quicksort.c algorithm_selection_sort.c algorithm_splitsort.c cheatalloc.c clist.c closure.c leaf_sort.c leaf_sort_index.c leaf_sort_parse.c list.c main_pushswap.c op_output.c op_p.c op_parse.c op_r.c op_rr.c op_s.c ops.c ops_groups.c ops_optimizer.c output.c psval.c slice.c stack.c stacks.c stacks_get.c
+SRCS=algorithm_complex.c algorithm_leafsort.c algorithm_simple.c cheatalloc.c clist.c closure.c leaf_sort.c leaf_sort_index.c leaf_sort_parse.c list.c main_pushswap.c op_output.c op_p.c op_parse.c op_r.c op_rr.c op_s.c ops.c ops_groups.c ops_optimizer.c output.c psval.c slice.c splitsort.c splitsort_final.c splitsort_iter.c splitsort_part.c stack.c stacks.c stacks_get.c
RESSRCS=_res_leaf_sort_lookup.h
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* algorithm_complex.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/12/16 14:52:06 by agilliar #+# #+# */
+/* Updated: 2025/12/16 14:55:13 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "pushswap.h"
+
+void algorithm_complex(const t_stacks *stacks, t_closure cb)
+{
+ splitsort(stacks, cb, 5);
+}
+++ /dev/null
-/* ************************************************************************** */
-/* */
-/* ::: :::::::: */
-/* algorithm_quicksort.c :+: :+: :+: */
-/* +:+ +:+ +:+ */
-/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
-/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/12/05 19:07:14 by agilliar #+# #+# */
-/* Updated: 2025/12/11 01:12:14 by agilliar ### ########.fr */
-/* */
-/* ************************************************************************** */
-
-#include "pushswap.h"
-
-static void quicksort_sift(const t_stacks *stacks, t_closure cb, t_list range)
-{
- size_t a;
- size_t b;
- t_psval pivot;
-
- a = 0;
- b = 0;
- pivot = range.ptr[range.len / 2];
- while (a + b < range.len)
- {
- if (clist_get_at(stacks->a.list, 0) < pivot)
- {
- a++;
- closure_call(cb, OP_RA);
- }
- else
- {
- b++;
- closure_call(cb, OP_PB);
- }
- }
-}
-
-static void quicksort_rec(const t_stacks *stacks, t_closure cb, t_list range)
-{
- size_t i;
- size_t pivot;
-
- if (range.len == 2
- && clist_get_at(stacks->a.list, 0) > clist_get_at(stacks->a.list, -1))
- closure_call(cb, OP_SA);
- if (range.len <= 2)
- return ;
- pivot = range.len / 2;
- quicksort_sift(stacks, cb, range);
- i = 0;
- while (i++ < range.len - pivot)
- closure_call(cb, OP_PA);
- quicksort_rec(stacks, cb, list_sub(range, pivot, range.len));
- i = 0;
- while (i++ < pivot)
- closure_call(cb, OP_RRA);
- quicksort_rec(stacks, cb, list_sub(range, 0, pivot));
-}
-
-void algorithm_quicksort(const t_stacks *stacks, t_closure cb)
-{
- t_list sorted;
-
- sorted = list_new(stacks->a);
- list_sort(sorted);
- quicksort_rec(stacks, cb, sorted);
-}
/* By: clefrere <clefrere@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/09 15:43:09 by clefrere #+# #+# */
-/* Updated: 2025/12/11 01:12:26 by agilliar ### ########.fr */
+/* Updated: 2025/12/16 14:54:44 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include "pushswap.h"
-void algorithm_selection_sort(const t_stacks *stacks, t_closure cb)
+void algorithm_simple(const t_stacks *stacks, t_closure cb)
{
t_list sorted;
+++ /dev/null
-/* ************************************************************************** */
-/* */
-/* ::: :::::::: */
-/* algorithm_splitsort.c :+: :+: :+: */
-/* +:+ +:+ +:+ */
-/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
-/* +#+#+#+#+#+ +#+ */
-/* Created: 2025/12/11 12:45:16 by agilliar #+# #+# */
-/* Updated: 2025/12/16 12:55:57 by agilliar ### ########.fr */
-/* */
-/* ************************************************************************** */
-
-#include "splitsort.h"
-
-static t_iter iter_new(t_list range, size_t blocks, bool rev)
-{
- t_iter res;
-
- if (blocks > range.len)
- blocks = range.len;
- res.range = range;
- res.blocks = blocks;
- res.rev = rev;
- return (res);
-}
-
-static t_list iter_next(t_iter *self)
-{
- t_list res;
- size_t count;
-
- if (!self->blocks)
- return (list_split(&self->range, 0));
- count = self->range.len / self->blocks;
- if (self->rev)
- {
- res = self->range;
- self->range = list_split(&res, res.len - count);
- }
- else
- {
- if (self->range.len % self->blocks)
- count++;
- res = list_split(&self->range, count);
- }
- self->blocks--;
- return (res);
-}
-
-static bool iter_nexti(t_iter *self, t_list *dst)
-{
- *dst = iter_next(self);
- return (dst->len != 0);
-}
-
-// Takes the self iterator, skip n elements, and return an iterator which only
-// yields said elements
-static t_iter iter_splitoff(t_iter *self, size_t n)
-{
- t_iter res;
-
- res = *self;
- while (n--)
- iter_next(self);
- res.range.len -= self->range.len;
- res.blocks -= self->blocks;
- if (res.rev)
- res.range.ptr += self->range.len;
- return (res);
-}
-
-static void splitsort_part_once(t_part self, t_splitsort sort, size_t count)
-{
- const t_stack *src;
- t_psval val;
-
- src = stacks_geta(sort.stacks, self.mirror);
- while (count--)
- {
- if (self.rev)
- closure_callm(sort.cb, OP_RRA, self.mirror);
- val = clist_get_at(src->list, 0);
- if (list_get_sorted(self.top, val) != -1)
- {
- closure_callm(sort.cb, OP_PB, self.mirror);
- closure_callm(sort.cb, OP_RB, self.mirror);
- }
- else if (list_get_sorted(self.bottom, val) != -1)
- closure_callm(sort.cb, OP_PB, self.mirror);
- else if (!self.rev)
- closure_callm(sort.cb, OP_RA, self.mirror);
- }
-}
-
-static void splitsort_part(t_splitsort sort, t_list range, t_mode mode)
-{
- t_iter topi;
- t_iter bottomi;
- t_part part;
- size_t top_count;
-
- bottomi = iter_new(range, sort.blocks, mode == MODE_A);
- topi = iter_splitoff(&bottomi, sort.blocks / 2);
- bottomi.rev = mode == MODE_B;
- topi.rev = !bottomi.rev;
- top_count = 0;
- part.mirror = mode == MODE_B;
- part.rev = false;
- while (iter_nexti(&topi, &part.top) | iter_nexti(&bottomi, &part.bottom))
- {
- splitsort_part_once(part, sort, range.len - top_count);
- part.rev = !part.rev;
- top_count += part.top.len;
- range.len -= part.bottom.len;
- }
- while (mode != MODE_A_WRAP && top_count--)
- closure_callm(sort.cb, OP_RRB, mode == MODE_B);
-}
-
-// Paritions b while also sorting the leaves of a
-void splitsort_final_mixed(t_splitsort sort, t_list range)
-{
- t_iter iter;
- t_part part;
-
- iter = iter_new(range, sort.blocks, true);
- part.mirror = true;
- part.rev = false;
- while (iter_nexti(&iter, &part.bottom) | iter_nexti(&iter, &part.top))
- {
- splitsort_part_once(part, sort, range.len);
- part.rev = !part.rev;
- range.len -= part.bottom.len + part.top.len;
- leaf_top_a_a(sort.stacks, sort.cb, part.bottom.len);
- leaf_bot_a_a(sort.stacks, sort.cb, part.top.len);
- }
-}
-
-void splitsort_final_simple(t_splitsort sort, t_list range)
-{
- leaf_top_b_a(sort.stacks, sort.cb, range.len);
-}
-
-// Parts range elements from stack a (which is in ascending order) onto stack b
-// in descending order
-static void splitsort_part_a(t_splitsort sort, t_list range)
-{
- splitsort_part(sort, range, MODE_A);
-}
-
-// Parts range elements from stack a (which is in ascending order) onto stack b
-// in descending order, assuming that stack b is initially empty
-static void splitsort_part_a_wrap(t_splitsort sort, t_list range)
-{
- splitsort_part(sort, range, MODE_A_WRAP);
-}
-
-// Parts range elements from stack b (which is in descending order) onto stack
-// a in ascending order
-static void splitsort_part_b(t_splitsort sort, t_list range)
-{
- splitsort_part(sort, range, MODE_B);
-}
-
-static t_layer_func *layer_from_info(size_t depth, size_t blocks, size_t len)
-{
- size_t i;
- size_t state;
-
- i = 0;
- state = 4;
- while (i++ < depth)
- state *= blocks;
- if (depth == 0)
- return (&splitsort_part_a_wrap);
- if (depth % 2 == 0)
- return (&splitsort_part_a);
- if (len <= state)
- return (&splitsort_final_simple);
- if (len <= state * blocks)
- return (&splitsort_final_mixed);
- return (&splitsort_part_b);
-}
-
-static void splitsort_visit_layer(t_visit self, t_splitsort sort)
-{
- t_iter iter;
-
- if (self.depth == 0)
- return (self.cb(sort, self.range));
- self.depth--;
- iter = iter_new(self.range, sort.blocks, self.rev);
- while (iter_nexti(&iter, &self.range))
- splitsort_visit_layer(self, sort);
-}
-
-void splitsort_part_layer(t_splitsort sort, t_list range, size_t depth)
-{
- t_visit visit;
-
- visit.range = range;
- visit.depth = depth;
- visit.cb = layer_from_info(depth, sort.blocks, range.len);
- visit.rev = depth % 2 == 1;
- splitsort_visit_layer(visit, sort);
-}
-
-void test_splitsort(const t_stacks *stacks, t_closure cb)
-{
- t_splitsort sort;
- t_list range;
- size_t i;
-
- sort.stacks = stacks;
- sort.cb = cb;
- sort.blocks = 5;
- range = list_new(stacks->a);
- list_sort(range);
- i = 0;
- while (!stacks_is_solved(stacks))
- splitsort_part_layer(sort, range, i++);
-}
/* By: clefrere <clefrere@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/02 22:15:12 by agilliar #+# #+# */
-/* Updated: 2025/12/16 13:03:28 by agilliar ### ########.fr */
+/* Updated: 2025/12/16 14:55:34 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
return (str1[i] == '\0' && str2[i] == '\0');
}
-void test_splitsort(const t_stacks *stacks, t_closure cb);
-
static void arg_step(char *str, t_args *arg)
{
if (ft_streq(str, "--simple"))
- arg->algo = &algorithm_selection_sort;
+ arg->algo = &algorithm_simple;
else if (ft_streq(str, "--medium"))
arg->algo = NULL;
else if (ft_streq(str, "--complex"))
- arg->algo = &algorithm_quicksort;
+ arg->algo = &algorithm_complex;
else if (ft_streq(str, "--adaptive"))
arg->algo = NULL;
else if (ft_streq(str, "--leaf"))
arg->algo = &algorithm_leafsort;
- else if (ft_streq(str, "--split"))
- arg->algo = &test_splitsort;
else if (ft_streq(str, "--bench"))
arg->bench = true;
else
/* By: clefrere <clefrere@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/02 11:02:44 by agilliar #+# #+# */
-/* Updated: 2025/12/15 20:28:36 by agilliar ### ########.fr */
+/* Updated: 2025/12/16 14:54:32 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
void leaf_top_b_a(const t_stacks *stacks, t_closure cb,
size_t size);
-void algorithm_selection_sort(const t_stacks *stacks, t_closure cb);
-void algorithm_quicksort(const t_stacks *stacks, t_closure cb);
+void splitsort(const t_stacks *stacks, t_closure cb, size_t blocks);
+
+void algorithm_simple(const t_stacks *stacks, t_closure cb);
+void algorithm_complex(const t_stacks *stacks, t_closure cb);
void algorithm_leafsort(const t_stacks *stacks, t_closure cb);
+
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* splitsort.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/12/11 12:45:16 by agilliar #+# #+# */
+/* Updated: 2025/12/16 14:46:51 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "splitsort.h"
+
+static t_layer_func *layer_from_info(size_t depth, size_t blocks, size_t len)
+{
+ size_t i;
+ size_t state;
+
+ i = 0;
+ state = 4;
+ while (i++ < depth)
+ state *= blocks;
+ if (depth == 0)
+ return (&splitsort_part_a_wrap);
+ if (depth % 2 == 0)
+ return (&splitsort_part_a);
+ if (len <= state)
+ return (&splitsort_final_simple);
+ if (len <= state * blocks)
+ return (&splitsort_final_mixed);
+ return (&splitsort_part_b);
+}
+
+static void splitsort_visit_layer(t_visit self, t_splitsort sort)
+{
+ t_iter iter;
+
+ if (self.depth == 0)
+ return (self.cb(sort, self.range));
+ self.depth--;
+ iter = iter_new(self.range, sort.blocks, self.rev);
+ while (iter_nexti(&iter, &self.range))
+ splitsort_visit_layer(self, sort);
+}
+
+static void splitsort_part_layer(t_splitsort sort, t_list range, size_t depth)
+{
+ t_visit visit;
+
+ visit.range = range;
+ visit.depth = depth;
+ visit.cb = layer_from_info(depth, sort.blocks, range.len);
+ visit.rev = depth % 2 == 1;
+ splitsort_visit_layer(visit, sort);
+}
+
+void splitsort(const t_stacks *stacks, t_closure cb, size_t blocks)
+{
+ t_splitsort sort;
+ t_list range;
+ size_t i;
+
+ sort.stacks = stacks;
+ sort.cb = cb;
+ sort.blocks = blocks;
+ if (blocks < 2)
+ cheatexit(1);
+ range = list_new(stacks->a);
+ list_sort(range);
+ i = 0;
+ while (!stacks_is_solved(stacks))
+ splitsort_part_layer(sort, range, i++);
+}
/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/16 12:54:11 by agilliar #+# #+# */
-/* Updated: 2025/12/16 12:56:36 by agilliar ### ########.fr */
+/* Updated: 2025/12/16 14:49:37 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
bool rev;
} t_visit;
+t_iter iter_new(t_list range, size_t blocks, bool rev);
+t_list iter_next(t_iter *self);
+bool iter_nexti(t_iter *self, t_list *dst);
+t_iter iter_splitoff(t_iter *self, size_t n);
+
+void splitsort_part_once(t_part self, t_splitsort sort, size_t count);
+void splitsort_part(t_splitsort sort, t_list range, t_mode mode);
+void splitsort_part_a(t_splitsort sort, t_list range);
+void splitsort_part_a_wrap(t_splitsort sort, t_list range);
+void splitsort_part_b(t_splitsort sort, t_list range);
+
+void splitsort_final_mixed(t_splitsort sort, t_list range);
+void splitsort_final_simple(t_splitsort sort, t_list range);
+
#endif
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* splitsort_final.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/12/16 14:43:59 by agilliar #+# #+# */
+/* Updated: 2025/12/16 14:51:41 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "splitsort.h"
+
+// Paritions b while also sorting the leaves of a
+void splitsort_final_mixed(t_splitsort sort, t_list range)
+{
+ t_iter iter;
+ t_part part;
+
+ iter = iter_new(range, sort.blocks, true);
+ part.mirror = true;
+ part.rev = false;
+ while (iter_nexti(&iter, &part.bottom) | iter_nexti(&iter, &part.top))
+ {
+ splitsort_part_once(part, sort, range.len);
+ part.rev = !part.rev;
+ range.len -= part.bottom.len + part.top.len;
+ leaf_top_a_a(sort.stacks, sort.cb, part.bottom.len);
+ leaf_bot_a_a(sort.stacks, sort.cb, part.top.len);
+ }
+}
+
+void splitsort_final_simple(t_splitsort sort, t_list range)
+{
+ leaf_top_b_a(sort.stacks, sort.cb, range.len);
+}
/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/12/16 12:57:22 by agilliar #+# #+# */
-/* Updated: 2025/12/16 12:57:29 by agilliar ### ########.fr */
+/* Updated: 2025/12/16 14:39:19 by agilliar ### ########.fr */
/* */
/* ************************************************************************** */
#include "splitsort.h"
+
+t_iter iter_new(t_list range, size_t blocks, bool rev)
+{
+ t_iter res;
+
+ if (blocks > range.len)
+ blocks = range.len;
+ res.range = range;
+ res.blocks = blocks;
+ res.rev = rev;
+ return (res);
+}
+
+t_list iter_next(t_iter *self)
+{
+ t_list res;
+ size_t count;
+
+ if (!self->blocks)
+ return (list_split(&self->range, 0));
+ count = self->range.len / self->blocks;
+ if (self->rev)
+ {
+ res = self->range;
+ self->range = list_split(&res, res.len - count);
+ }
+ else
+ {
+ if (self->range.len % self->blocks)
+ count++;
+ res = list_split(&self->range, count);
+ }
+ self->blocks--;
+ return (res);
+}
+
+bool iter_nexti(t_iter *self, t_list *dst)
+{
+ *dst = iter_next(self);
+ return (dst->len != 0);
+}
+
+// Takes the self iterator, skip n elements, and return an iterator which only
+// yields said elements
+t_iter iter_splitoff(t_iter *self, size_t n)
+{
+ t_iter res;
+
+ res = *self;
+ while (n--)
+ iter_next(self);
+ res.range.len -= self->range.len;
+ res.blocks -= self->blocks;
+ if (res.rev)
+ res.range.ptr += self->range.len;
+ return (res);
+}
--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* splitsort_part.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/12/16 14:42:51 by agilliar #+# #+# */
+/* Updated: 2025/12/16 14:44:49 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "splitsort.h"
+
+void splitsort_part_once(t_part self, t_splitsort sort, size_t count)
+{
+ const t_stack *src;
+ t_psval val;
+
+ src = stacks_geta(sort.stacks, self.mirror);
+ while (count--)
+ {
+ if (self.rev)
+ closure_callm(sort.cb, OP_RRA, self.mirror);
+ val = clist_get_at(src->list, 0);
+ if (list_get_sorted(self.top, val) != -1)
+ {
+ closure_callm(sort.cb, OP_PB, self.mirror);
+ closure_callm(sort.cb, OP_RB, self.mirror);
+ }
+ else if (list_get_sorted(self.bottom, val) != -1)
+ closure_callm(sort.cb, OP_PB, self.mirror);
+ else if (!self.rev)
+ closure_callm(sort.cb, OP_RA, self.mirror);
+ }
+}
+
+void splitsort_part(t_splitsort sort, t_list range, t_mode mode)
+{
+ t_iter topi;
+ t_iter bottomi;
+ t_part part;
+ size_t top_count;
+
+ bottomi = iter_new(range, sort.blocks, mode == MODE_A);
+ topi = iter_splitoff(&bottomi, sort.blocks / 2);
+ bottomi.rev = mode == MODE_B;
+ topi.rev = !bottomi.rev;
+ top_count = 0;
+ part.mirror = mode == MODE_B;
+ part.rev = false;
+ while (iter_nexti(&topi, &part.top) | iter_nexti(&bottomi, &part.bottom))
+ {
+ splitsort_part_once(part, sort, range.len - top_count);
+ part.rev = !part.rev;
+ top_count += part.top.len;
+ range.len -= part.bottom.len;
+ }
+ while (mode != MODE_A_WRAP && top_count--)
+ closure_callm(sort.cb, OP_RRB, mode == MODE_B);
+}
+
+// Parts range elements from stack a (which is in ascending order) onto stack b
+// in descending order
+void splitsort_part_a(t_splitsort sort, t_list range)
+{
+ splitsort_part(sort, range, MODE_A);
+}
+
+// Parts range elements from stack a (which is in ascending order) onto stack b
+// in descending order, assuming that stack b is initially empty
+void splitsort_part_a_wrap(t_splitsort sort, t_list range)
+{
+ splitsort_part(sort, range, MODE_A_WRAP);
+}
+
+// Parts range elements from stack b (which is in descending order) onto stack
+// a in ascending order
+void splitsort_part_b(t_splitsort sort, t_list range)
+{
+ splitsort_part(sort, range, MODE_B);
+}