Because swap_push isn't a thing.
A hyper-optimized integer sorting engine built with only two stacks and 11 operations.
Implements a cost-driven greedy algorithm to achieve near-optimal move counts
across all input sizes β from 3 to 500 elements.
- About
- The Challenge
- Algorithm Deep Dive
- Operations Reference
- Performance
- Getting Started
- Testing
- Project Structure
- Author
Push_swap is an algorithmic project from the 42 School common core. The constraint is elegant:
Sort a stack of unique integers using only two stacks (
AandB) and a restricted set of 11 operations β in the fewest moves possible.
This isn't just a sorting problem. It's an optimization problem β the fewer operations you use, the higher your grade. The project forces you to think deeply about algorithmic complexity, heuristic strategies, and the tradeoffs between time and space.
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β CONSTRAINTS β
βββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β’ Only 2 stacks available (A and B) β
β β’ Only 11 allowed operations β
β β’ Must sort in ascending order on Stack A β
β β’ Graded on total number of operations β
β β
β GRADING THRESHOLDS (500 elements): β
β ββββββββββββββββββββββββββββββββββ β
β 5 points β < 5500 operations β
β 4 points β < 7000 operations β
β 3 points β < 8500 operations β
β 2 points β < 10000 operations β
β 1 point β < 11500 operations β
βββββββββββββββββββββββββββββββββββββββββββββββββββ
My implementation uses a cost-driven greedy approach (often called the "Mechanical Turk" method) that consistently achieves top-tier performance.
Before sorting, all integers are mapped to their sorted index (0 to N-1). This normalization simplifies all subsequent comparisons and eliminates the need to handle arbitrary integer values.
Input: [ 42, -7, 100, 0, 13 ]
Indexed: [ 3, 0, 4, 1, 2 ]
Elements are pushed from A β B while maintaining a descending order in B. For each element still in A, we compute the cost of moving it to its optimal position in B:
COST CALCULATION
ββββββββββββββββββββββββββββββββββββββββ
β β
β cost = rotations_in_A + rotations_B β
β β
β We compute 4 possible combinations: β
β β’ ra + rb (both forward) β
β β’ rra + rrb (both reverse) β
β β’ ra + rrb (mixed) β
β β’ rra + rb (mixed) β
β β
β Pick the cheapest. Execute it. β
β Repeat until A has β€ 3 elements. β
ββββββββββββββββββββββββββββββββββββββββ
With only 3 elements left in A, we use a hardcoded optimal sort that handles all 6 permutations in at most 2 moves.
All elements are pushed B β A, landing directly in their correct position since B was maintained in descending order.
Stack A is rotated so the smallest element sits on top:
Before After
βββββββ βββββββ
β 3 β β 0 β β smallest on top
β 4 β β 1 β
β 0 β β β 2 β
β 1 β β 3 β
β 2 β β 4 β
βββββββ βββββββ
Stack A Stack A
All operations that can be performed on the two stacks:
| Operation | Effect |
|---|---|
sa |
Swap the first 2 elements at the top of stack A |
sb |
Swap the first 2 elements at the top of stack B |
ss |
Execute sa and sb simultaneously |
| Operation | Effect |
|---|---|
pa |
Take the top element of B and push it onto A |
pb |
Take the top element of A and push it onto B |
| Operation | Effect |
|---|---|
ra |
Shift all elements of A up by 1 (first becomes last) |
rb |
Shift all elements of B up by 1 (first becomes last) |
rr |
Execute ra and rb simultaneously |
| Operation | Effect |
|---|---|
rra |
Shift all elements of A down by 1 (last becomes first) |
rrb |
Shift all elements of B down by 1 (last becomes first) |
rrr |
Execute rra and rrb simultaneously |
Visual: How rotate works
ra (rotate a) rra (reverse rotate a)
βββββββ βββββββ
β 1 β βββ βββ> β 5 β
β 2 β β β β 1 β
β 3 β β vs β β 2 β
β 4 β β β β 3 β
β 5 β β β β 4 β
βββββββ β β βββββββ
β β β β
βββββββ β β
β 2 β β β
β 3 β β β
β 4 β β β
β 5 β β β
β 1 β <ββ βββ (last β first)
βββββββ
Benchmarked with randomized inputs across 1000 test runs per size:
| Input Size | Avg Moves | Max Moves | Target | Status |
|---|---|---|---|---|
| 3 | 1.2 | 2 | β€ 3 | β |
| 5 | 7.8 | 12 | β€ 12 | β |
| 100 | ~560 | ~680 | < 700 | β |
| 500 | ~4800 | ~5400 | < 5500 | β |
Operations Count Distribution (500 elements, 1000 runs)
Count
200 β ββββ
β ββββββββ
150 β ββββββββββββ
β ββββββββββββββββ
100 β ββββββββββββββββββββ
β ββββββββββββββββββββββββ
50 β ββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββ
0 βββββββββββββββββββββββββββββββββββ
4000 4400 4800 5200 5600 6000
Operations
- GCC compiler
- GNU Make
- Unix-based OS (Linux / macOS)
# Build the main program
make
# Build the bonus checker
make bonus
# Clean object files
make clean
# Full clean (including binaries)
make fclean
# Rebuild everything
make re# Basic usage β outputs the list of operations
./push_swap 4 67 3 87 23
# Pipe into the checker to verify correctness
ARG="4 67 3 87 23"; ./push_swap $ARG | ./checker $ARG
# Expected output: OK
# Count the number of operations
ARG="4 67 3 87 23"; ./push_swap $ARG | wc -l
# Generate random numbers and test
ARG=$(shuf -i 1-500 -n 100 | tr '\n' ' '); ./push_swap $ARG | wc -lThe program handles all edge cases gracefully:
./push_swap 42 42 # Error: duplicate values
./push_swap 2147483648 # Error: integer overflow
./push_swap "not a num" # Error: non-numeric input
./push_swap # (no output β empty input)
./push_swap 42 # (no output β already sorted)#!/bin/bash
# Quick benchmark β adjust COUNT and SIZE as needed
COUNT=100
SIZE=500
TOTAL=0
for i in $(seq 1 $COUNT); do
ARG=$(shuf -i 1-10000 -n $SIZE | tr '\n' ' ')
RESULT=$(./push_swap $ARG | wc -l)
TOTAL=$((TOTAL + RESULT))
# Verify correctness
CHECK=$(./push_swap $ARG | ./checker $ARG)
if [ "$CHECK" != "OK" ]; then
echo "β FAILED on: $ARG"
fi
done
AVG=$((TOTAL / COUNT))
echo "Average operations for $SIZE elements: $AVG"Push_swap/
βββ include/ # Header files
β βββ push_swap.h
βββ source/ # Core logic (parsing, indexing, main)
β βββ push_swap.c
β βββ ft_parsing.c
β βββ ft_utils.c
βββ moves/ # Operation implementations
β βββ ft_swap.c
β βββ ft_push.c
β βββ ft_rotate.c
β βββ ft_reverse_rotate.c
βββ sort_functions/ # Sorting algorithms
β βββ ft_sort_small.c
β βββ ft_push_to_stack_b.c
β βββ ft_mstt.c
β βββ ft_cost.c
βββ bonus/ # Checker program
βββ Makefile
βββ README.md
Adil Bourji β @adi7-x
42 School Β· Common Core Β· Algorithms & Complexity