--- /dev/null
+/* ************************************************************************** */
+/* */
+/* ::: :::::::: */
+/* algoritm_merlin_sort.c :+: :+: :+: */
+/* +:+ +:+ +:+ */
+/* By: agilliar <marvin@42.fr> +#+ +:+ +#+ */
+/* +#+#+#+#+#+ +#+ */
+/* Created: 2025/12/03 16:07:50 by agilliar #+# #+# */
+/* Updated: 2025/12/03 18:32:31 by agilliar ### ########.fr */
+/* */
+/* ************************************************************************** */
+
+#include "pushswap.h"
+
+const t_stack *stack_get(const t_stacks *stacks, t_stackid id);
+static bool stack_gt(t_stackid id, t_psval lhs, t_psval rhs)
+{
+ if (lhs == rhs)
+ cheatexit(1);
+ if ((lhs > rhs && id == STACKID_A) || (lhs < rhs && id == STACKID_B))
+ return (true);
+ return (false);
+}
+
+// n: > 2
+static void stack_invert_n(size_t n, t_closure cb, t_stackid id)
+{
+ size_t i;
+
+ i = 1;
+ while (i++ * 2 < n)
+ {
+ (cb.func)(cb.data, id, OP_PB);
+ (cb.func)(cb.data, id, OP_RR);
+ }
+ (cb.func)(cb.data, id, OP_PB);
+ (cb.func)(cb.data, id, OP_RB);
+ if (n % 2 == 0)
+ (cb.func)(cb.data, id, OP_PB);
+ i = 1;
+ while (i++ * 2 < n)
+ {
+ (cb.func)(cb.data, id, OP_RRR);
+ (cb.func)(cb.data, id, OP_PB);
+ }
+ (cb.func)(cb.data, id, OP_RRB);
+ i = 0;
+ while (i++ < n)
+ (cb.func)(cb.data, id, OP_PA);
+}
+
+static void clamp_disorder(t_stacks *const stacks, size_t len,
+ t_closure cb, t_stackid id)
+{
+ (void) stacks;
+ (void) len;
+ (void) cb;
+ (void) id;
+}
+
+// Returns the amount of unordered elements sifted out
+static size_t sift_unordered(t_stacks *const stacks, size_t len,
+ t_closure cb, t_stackid id)
+{
+ const t_stack *a;
+ const t_stack *b;
+
+ a = stack_get(stacks, id);
+ b = stack_get(stacks, !id);
+ (void) len;
+ (void) cb;
+ for (;;)
+ ;
+ __builtin_unreachable();
+}
+
+static void merlin_merge(t_stacks *const stacks, size_t kept, size_t sifted,
+ t_closure cb, t_stackid id)
+{
+ const t_stack *a;
+ const t_stack *b;
+
+ a = stack_get(stacks, id);
+ b = stack_get(stacks, !id);
+ while (kept && sifted)
+ {
+ if (stack_gt(id, clist_get_at(a->list, 1), clist_get_at(b->list, 0)))
+ {
+ (cb.func)(cb.data, id, OP_RRA);
+ kept--;
+ }
+ else
+ {
+ (cb.func)(cb.data, id, OP_PA);
+ sifted--;
+ }
+ }
+ while (kept--)
+ (cb.func)(cb.data, id, OP_RRA);
+ while (sifted--)
+ (cb.func)(cb.data, id, OP_PA);
+}
+
+
+static void merlin_sort_inner(t_stacks *const stacks, size_t len,
+ t_closure cb, t_stackid id)
+{
+ size_t sifted;
+ const t_clist *a;
+
+ a = stack_get(stacks, id)->list;
+ if (len == 2 && stack_gt(id, clist_get_at(a, 0), clist_get_at(a, -1)))
+ (cb.func)(cb.data, id, OP_SA);
+ if (len <= 2)
+ return ;
+ clamp_disorder(stacks, len, cb, id);
+ sifted = sift_unordered(stacks, len, cb, id);
+ merlin_sort_inner(stacks, sifted, cb, !id);
+ merlin_merge(stacks, len - sifted, sifted, cb, id);
+}
+
+static void stackid_wrap_fn(t_closure *inner, t_stackid id, t_op op)
+{
+ const t_op translation[] = {
+ OP_SB,
+ OP_SA,
+ OP_SS,
+ OP_PB,
+ OP_PA,
+ OP_RB,
+ OP_RA,
+ OP_RR,
+ OP_RRB,
+ OP_RRA,
+ OP_RRR,
+ };
+ if (id == STACKID_B)
+ op = translation[op];
+ (inner->func)(inner->data, op);
+}
+
+void algorithm_merlin_sort(t_stacks *const stacks, t_closure closure)
+{
+ t_closure cb;
+
+ cb.data = &closure;
+ cb.func = (void (*)()) &stackid_wrap_fn;
+ merlin_sort_inner(stacks, stacks->a.len, cb, STACKID_A);
+}
+
+void algorithm_revn(t_stacks *const stacks, t_closure closure)
+{
+ t_closure cb;
+
+ cb.data = &closure;
+ cb.func = (void (*)()) &stackid_wrap_fn;
+ merlin_sort_inner(stacks, stacks->a.len, cb, STACKID_A);
+}