#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "stack_pair.h"


/************************************************/
/*********  helper functions    *****************/
/************************************************/

void print_array(int* ar, int n) {
  for (int i=0; i < n; i++)
    printf("%d ", ar[i]);
  printf("\n");
}


void swap(int* a, int* b){
  int tmp = *a; 
  *a = *b;
  *b = tmp; 
}
/************************************************/
/*********  helper functions    *****************/
/************************************************/

// rearrange
int rearrange(int *ar, int n, int pivot_index){
  printf("rearrange: ");
  print_array(ar, n);

  if (n<=1)
    return n;

  int pivot_value = ar[pivot_index]; 

  // swap pivot to ar[0]
  swap(&ar[0], &ar[pivot_index]); 

  int left_ptr=1, right_ptr=n-1;
  
  while (left_ptr<right_ptr) {
    while (left_ptr<right_ptr && ar[right_ptr]>pivot_value)
      right_ptr--;
    while (left_ptr<right_ptr && ar[left_ptr]<pivot_value)
      left_ptr++;
 
    if (left_ptr<right_ptr)
      swap(&ar[left_ptr++], &ar[right_ptr--]);
  }

  int ret_ind = left_ptr;
  // the pivot will move to either left_ptr or left_ptr-1
  if (ar[left_ptr]<pivot_value)
    ret_ind = left_ptr;
  else
    ret_ind = left_ptr-1;

  swap(&ar[0], &ar[ret_ind]);
  return ret_ind;
}

// gets an array of length n
// implements quick sort without recursion
void quick_sort_iter(int* ar, int n) {

  // stack of pairs
  // pairs contains the first index and the last index of the subarray
  stack_t* s = stack_create();

  stack_push(s, (pair){0,n-1}); 

  int pivot_ind;
  
  while (!stack_is_empty(s)) {
    pair next = stack_pop(s);

    pivot_ind = rearrange(ar+next.first, next.second-next.first+1, 0) + next.first;

    if (pivot_ind+1<next.second) // recursive call sort large numbers
      stack_push(s,(pair){pivot_ind+1,next.second});

    if (pivot_ind-1>next.first) // recursive call sort small numbers
      stack_push(s,(pair){next.first, pivot_ind-1});

  } // end of while loop

  free(s);
}

int main() {

  int a[] = {4,1,8,5,7,3,22,2,17,6,9};
  int n = 11;

//  rearrange(a,n,0);
//  print_array(a,n);

  quick_sort_iter(a,n);
  print_array(a,n);
  return 0;
}
