Skip to main content

Project Overview

Push Swap is a sorting algorithm implementation that sorts a stack of integers using a limited set of operations. The project is designed to meet 42 School standards and follows strict coding conventions.

Project Structure

The codebase is organized into functional modules:

Core Files

main.c            # Program entry, argument parsing
push_swap.c       # Main sorting logic and algorithm dispatcher
push_swap.h       # Header file with all function prototypes

Key Data Structure

The stack is implemented as a doubly-linked circular list:
push_swap.h:21-31
typedef struct s_list
{
    int             nbr;           // The integer value
    int             index;         // Current position in stack
    int             push_cost;     // Cost to push this node
    int             above_median;  // Boolean: above or below median
    int             cheapest;      // Boolean: is this the cheapest node?
    struct s_list   *target_node;  // Target in opposite stack
    struct s_list   *next;         // Next node
    struct s_list   *prev;         // Previous node
}   t_list;

Coding Standards

42 Norm Compliance

This project follows the 42 School norm:
1

Function Length

Functions must not exceed 25 lines (excluding braces).
// Good: concise function
void sa(t_list **a, bool print)
{
    t_list *tmp;
    
    if (!*a || !(*a)->next)
        return;
    tmp = *a;
    *a = (*a)->next;
    tmp->next = (*a)->next;
    (*a)->next = tmp;
    if (print)
        write(1, "sa\n", 3);
}
2

Line Length

Lines must not exceed 80 characters.
// Good: properly wrapped
if (cheapest_node->above_median
    && cheapest_node->target_node->above_median)
    rotate_both(a, b, cheapest_node);
3

Naming Conventions

  • Functions: lowercase with underscores (ft_push, sort_three)
  • Variables: lowercase with underscores (stack_a, push_cost)
  • Structures: prefix with s_ (s_list)
  • Typedefs: prefix with t_ (t_list)
4

Indentation

Use tabs for indentation, not spaces.
void example(void)
{
if (condition)
→   {
→   →   do_something();
→   }
}
5

Declarations

  • One declaration per line
  • Declare variables at the beginning of functions
  • Initialize variables when possible
void function(void)
{
    int     count;
    t_list  *current;
    t_list  *tmp;
    
    count = 0;
    current = stack;
    // ... rest of function
}

Forbidden Functions

Only the following standard library functions are allowed:
  • write
  • malloc
  • free
  • exit
All other functions (like printf, strlen, etc.) must be implemented manually or avoided.

Algorithm Architecture

Sorting Strategy

The algorithm uses different strategies based on stack size:
push_swap.c:59-70
void sort_stack(t_list **a, t_list **b)
{
    int size;
    
    size = ft_stack_size(*a);
    if (size == 2)
        sa(a, false);        // Simple swap
    else if (size == 3)
        sort_three(a);       // Optimized 3-element sort
    else
        sort_big_stacks(a, b); // Turk algorithm
}

Turk Algorithm (Large Stacks)

For stacks > 3 elements, the algorithm:
  1. Push to B: Push all but 3 elements to stack B, choosing optimal targets
  2. Sort remaining 3: Use sort_three() on stack A
  3. Push back to A: Move elements from B to A in optimal order
  4. Final rotation: Rotate stack A to position minimum at top
See sort_big_stacks.c:53-75 for implementation details.

Areas for Contribution

1. Performance Optimization

Current performance (approximate):
  • 100 elements: ~700 operations
  • 500 elements: ~5500 operations
Optimization opportunities:
  • Improve target node selection in init_a_to_b.c
  • Optimize cost calculation in init_nodes_a()
  • Experiment with different initial push strategies
  • Fine-tune the threshold for using sort_three()

2. Code Refactoring

Potential improvements:
  • Extract common patterns in operation functions
  • Reduce code duplication between init_a_to_b.c and init_b_to_a.c
  • Improve error message clarity
  • Add more comprehensive input validation

3. Documentation

Documentation needs:
  • Add inline comments explaining complex algorithms
  • Document the cost calculation formula
  • Create visual diagrams of the sorting process
  • Add more usage examples

4. Testing Infrastructure

Testing improvements:
  • Create automated test suite
  • Add benchmark comparison tools
  • Implement a checker program (bonus)
  • Add fuzzing for edge cases
  • Create visual debugging tools

5. Additional Features

Bonus implementations:
  • Checker program: Validates operation sequences
  • Visualizer: GUI to watch sorting in real-time
  • Performance analyzer: Detailed operation statistics
  • Alternative algorithms: Implement other sorting approaches

Development Workflow

Setting Up

1

Clone the repository

git clone <repository-url>
cd push_swap
2

Build the project

make
3

Run tests

# Basic functionality
./push_swap 3 2 1

# Performance test
ARG=$(seq 1 100 | shuf | tr '\n' ' ')
./push_swap $ARG | wc -l
4

Check for memory leaks

valgrind --leak-check=full ./push_swap 4 2 7 1 3

Making Changes

1

Create a feature branch

git checkout -b feature/your-feature-name
2

Make your changes

  • Follow the 42 norm strictly
  • Keep functions under 25 lines
  • Test thoroughly
  • Check for memory leaks
3

Test your changes

make re
./push_swap 5 2 8 1 9

# Run comprehensive tests
bash test_performance.sh
4

Commit your changes

git add .
git commit -m "feat: add optimization for target selection"
Use conventional commit messages:
  • feat: - New feature
  • fix: - Bug fix
  • refactor: - Code refactoring
  • docs: - Documentation
  • test: - Testing

Code Review Checklist

Before submitting:
  • Code follows 42 norm (use norminette if available)
  • All functions are under 25 lines
  • No lines exceed 80 characters
  • No forbidden functions used
  • No memory leaks (Valgrind clean)
  • All error cases handled properly
  • Code compiles with -Wall -Wextra -Werror
  • Tests pass for all stack sizes
  • Performance meets benchmarks

Common Pitfalls

Memory Management

// Always free on error
void free_errors(t_list **a, char **argv, int flag)
{
    if (flag == 1)
        free_split(argv);  // Free split results
    free_stack(a);         // Free stack
    write(1, "Error\n", 6);
    exit(1);
}

Edge Cases

// Always check for empty/single element
if (!*a || !(*a)->next)
    return;  // Nothing to sort

// Check for already sorted
if (is_stack_sorted(*a))
    return;  // Don't waste operations

Integer Overflow

// Use long for calculations that might overflow
long result = (long)a * (long)b;
if (result > INT_MAX || result < INT_MIN)
    return error;

Debugging Tips

Enable Debug Mode

Add a debug flag to print operations:
#ifdef DEBUG
    printf("Operation: sa\n");
    print_stack(*a);
#endif
Compile with:
cc -Wall -Wextra -Werror -DDEBUG *.c -o push_swap_debug

Track Operation Count

static int g_operation_count = 0;

void sa(t_list **a, bool print)
{
    g_operation_count++;
    // ... operation logic
}

Resources

Documentation

Tools

  • norminette: Norm checker for 42 projects
  • valgrind: Memory leak detection
  • gdb: Debugger for C programs
  • push_swap_visualizer: Visual debugging tool

Community

  • 42 Network: Connect with other students
  • GitHub Issues: Report bugs and request features
  • Pull Requests: Submit your improvements

Getting Help

If you need assistance:
  1. Check existing documentation and tests
  2. Review similar issues on GitHub
  3. Ask in the community forums
  4. Create a detailed issue report

License and Attribution

When contributing:
  • Maintain the existing header format in all files
  • Credit original author (iboiraza)
  • Add your contributions to a contributors list if appropriate
  • Respect 42 School academic integrity policies
This is an educational project. If you’re a 42 student, ensure your contributions comply with your school’s collaboration policies.

Next Steps

Build docs developers (and LLMs) love