This project's goal is to make the student get in contact with the idea of sorting algorithms and complexity. In possession of a list of numbers, the program must be able to use only two stacks and a restricted number of movements in order to sort the list out.
For the mandatory part, we should:
- Be able to sort the given list of numbers correctly;
- Do it so with the least possible number of movements.
For the bonus part we should:
- Do a checker program in order to access if the movements done can correctly sort the list given.
You have 2 stacks named A and B.
- The
stack Acontains a random amount of negative and/or positive numbers which cannot be duplicated. - The
stack Bis empty.
The goal is to sort in ascending order numbers into stack A.
To do so you have the following operations at your disposal:
sa(swap a): Swap the first 2 elements at the top ofstack A. Do nothing if there is only one or no elements.sb(swap b): Swap the first 2 elements at the top ofstack B. Do nothing if there is only one or no elements.ss:saandsbat the same time.pa(push a): Take the first element at the top ofBand put it at the top ofA. Do nothing ifBis empty.pb(push b): Take the first element at the top ofAand put it at the top ofB. Do nothing ifAis empty.ra(rotate a): Shift up all elements ofstack Aby 1. The first element becomes the last one.rb(rotate b): Shift up all elements ofstack Bby 1. The first element becomes the last one.rr:raandrbat the same time.rra(reverse rotate a): Shift down all elements ofstack Aby 1. The last element becomes the first one.rrb(reverse rotate b): Shift down all elements ofstack Bby 1. The last element becomes the first one.rrr:rraandrrbat the same time.
You can launch the program by doing
> $ ./push_swap <list_of_integers> The list can be passed as a single array of multiple numbers, indiferently.
> $ ./push_swap 1 3 5 4 2 0 -4or
> $ ./push_swap "1 3 5 4 2 0 -4"The expected output should be the instructions applied in order to sort the stack:
> $ ./push_swap 0 4 2
> pb
> ra
> paOr an Error message in case of errors of any kind:
> $ ./push_swap 0 4 two
> ErrorIf no parameters are passed, the command prompted will be returned with no error message:
Or an Error message in case of errors of any kind:
> $ ./push_swap
> $After extensive research, one thing became clear to me: this project is not about finding the best algorithm. It is, however, about subverting some existing ones into thinking and doing whatever is necessary to accomplish the goal in the minimum possible number of operations - no matter how long or how much computational power it takes.
Thankfully, I came across Victor Nunes's solution a while ago and thought it was one of the best ever made for this project. So, I put all my efforts and my mind in trying it out! (Thanks again, Victor!).
The idea of this "algorithm" is to ensure that the most efficient movement will be done at each interation. I took Victor's idea to heart and implemented it myself as if to prove that it actually works (spoiler alert: it does beautifully!). The program runs on average 22% more efficiently then the maximum accepted for a 100% score. For example, in a 500 numbers' stack, the average iteration count is around 4300 movements (where the aim is to reach up to 5500 for an A grade).
The idea is very simple and is divided in four basic steps:
Step 1: calculate if the top number at stack A is among the 30%ish lowest numbers in the entire stack (this number was not chosen on random - it came from multiple test for the most optimized combination). If it is, push it to stack B. The program will do the math for every number on stack A until it is at most 5 numbers long;Step 2: sort the five numbers left at stack A, so that it becomes ready to receive the numbers at stack B back;Step 3: push the numbers from stack B back to A, but with a minor detail: the program will calculate the correct place for that number to be, so that when it is pushed, stack A will never be out of order again. More then that, it will calculate which number from stack B takes the minimum amount of movements (the one at the top, the second or the last one). It will only move a number if it can make sure that it is the most optimum choice;Step 4: when all the numbers from stack B are back and in order on stack A, then the program will align the stack, making sure that it starts with the lowest number.
As you can see, it takes a lot of computational power. The stacks are iterated over multiple times, and a bunch of calculations are done at every step. However, this is the beauty of push_swap: it is not about computational performance; it is about being smart and subverting the algorithms to work in your favor.
Header file
Main function
Initialization
Linked list utils
Stack management and operations
Sorting
Code utilities
Error management and program closing
The bonus part of this project consists in producing a checker executable that will check, for the stack given, it the instructions passed on the command prompt in fact are able to sort the stack.
You can launch the program by typing:
> $ ./checker <list_of_integers> And then typing the instructions in order to sort them, only separated by a new line. By pressing Ctrl+D at the end, the program will return OK if list is sorted:
> $ ./push_swap 0 4 2
> $ pb
> $ ra
> $ pa
> OKKO if not:
> $ ./push_swap 0 4 2
> $ pb
> $ ra
> KOAnd Error if there were any errors in reading the instructions or parsing the list:
> $ ./push_swap 0 4 2
> $ not_a_comand
> ErrorThe implementation for the Bonus part can be found below:


