{"id":13460220,"url":"https://github.com/anyaschukin/Push_Swap","last_synced_at":"2025-03-24T18:33:28.005Z","repository":{"id":54242745,"uuid":"129937692","full_name":"anyaschukin/Push_Swap","owner":"anyaschukin","description":"A bespoke sorting algorithm, on 2 stacks. ","archived":false,"fork":false,"pushed_at":"2018-09-06T21:01:25.000Z","size":3980,"stargazers_count":34,"open_issues_count":0,"forks_count":4,"subscribers_count":0,"default_branch":"master","last_synced_at":"2024-08-01T10:20:57.966Z","etag":null,"topics":["42","42-school","42born2code","algorithm","c","push-swap","sorting","sorting-algorithms"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anyaschukin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-17T16:57:11.000Z","updated_at":"2024-07-28T22:02:54.000Z","dependencies_parsed_at":"2022-08-13T09:50:45.623Z","dependency_job_id":null,"html_url":"https://github.com/anyaschukin/Push_Swap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anyaschukin%2FPush_Swap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anyaschukin%2FPush_Swap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anyaschukin%2FPush_Swap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anyaschukin%2FPush_Swap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anyaschukin","download_url":"https://codeload.github.com/anyaschukin/Push_Swap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222004172,"owners_count":16914873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["42","42-school","42born2code","algorithm","c","push-swap","sorting","sorting-algorithms"],"created_at":"2024-07-31T10:00:37.540Z","updated_at":"2024-10-29T06:30:31.011Z","avatar_url":"https://github.com/anyaschukin.png","language":"C","funding_links":[],"categories":["WELCOME"],"sub_categories":["**Push_swap**"],"readme":"# Push_Swap\n\n#### Final Score 105/100\n\n## Challenge\n\nSort a random list of integers using the smallest number of moves, 2 stacks\nand a limited set of operations. \u003cbr /\u003e\n\u003cbr /\u003e\n\nYou start with two empty stacks: **a** and **b**. You are given a random list of integers via command line arguments.\n\u003cbr /\u003e\n\u003cbr /\u003e\n\nOnly these moves are allowed:\n- `sa` : swap a - swap the first 2 elements at the top of stack a. Do nothing if there is only one or no elements).\n- `sb` : swap b - swap the first 2 elements at the top of stack b. Do nothing if there is only one or no elements).\n- `ss` : `sa` and `sb` at the same time.\n- `pa` : push a - take the first element at the top of b and put it at the top of a. Do\nnothing if b is empty.\n- `pb` : push b - take the first element at the top of a and put it at the top of b. Do\nnothing if a is empty.\n- `ra` : rotate a - shift up all elements of stack a by 1. The first element becomes\nthe last one.\n- `rb` : rotate b - shift up all elements of stack b by 1. The first element becomes the last one.\n- `rr` : `ra` and `rb` at the same time.\n- `rra` : reverse rotate a - shift down all elements of stack a by 1. The last element becomes the first one.\n- `rrb` : reverse rotate b - shift down all elements of stack b by 1. The last element becomes the first one.\n- `rrr` : `rra` and `rrb` at the same time.\n\u003cbr /\u003e\n\nAt the end, **stack b** must empty empty and all integers must be in **stack a**, sorted in ascending order. \u003cbr /\u003e\n\u003cbr /\u003e\n\n## The Project\nCreate two programs: ```checker``` and ```push_swap```. \u003cbr /\u003e\n\nThe ```checker``` program reads a random list of integers from the stdin, stores them, and checks to see\nif they are sorted. \u003cbr /\u003e\n\u003cbr /\u003e\nThe ```push_swap``` program calculates the moves to sort the integers – *pushing, popping, swapping* and *rotating* \nthem between **stack a** and **stack b** – and displays those directions on the stdout. \u003cbr /\u003e\n\u003cbr /\u003e\nYou can pipe ```push_swap``` into ```checker```, and ```checker``` will verify that ```push_swap```'s instructions were successful. \n\u003cbr /\u003e\n\nBoth programs must mandatorily parse input for errors, including empty strings, no parameters, \nnon-numeric parameters, duplicates, and invalid/non-existent instructions.\n\n**Push_Swap** must conform to the [42 Norm](https://cdn.intra.42.fr/pdf/pdf/960/norme.en.pdf). \u003cbr /\u003e\nUsing normal ```libc``` functions is strictly forbidden. Students are however, allowed to use: ```write```, ```read```, ```malloc```, ```free```, ```exit```. \nIt must not have any memory leaks. Errors must be handled carefully. \u003cbr /\u003e\nIn no way can it quit in an unexpected manner (segmentation fault, bus error, double free, etc).\n\n## Approach\n\nI stored all integers parsed into the stack in a **doubly-circular linked list**. This permitted me to access both the top and bottom of each stack (**a** and **b**) in the fewest number of moves, giving me the most efficient access to sort through all integers.  \u003cbr /\u003e\n\n```./push_swap``` writes recommended moves to the ```stdout```, which ```./checker``` then reads off the ```stdin``` and parses. I used a **jump table** to parse the moves and launch the corresponding function. This was much more efficient than an ```if tree```, and triggered an error message for invalid input. \u003cbr /\u003e\n\nTo try this out, launch ```./checker```. To push an integer to **stack b**, type ```pb``` and hit ‘enter’. To see if a combination of moves has sorted the stack, type ```control D``` to finish, and the ```./checker``` will display “OK” for sorted or “KO” for unsorted. \u003cbr /\u003e\n\nThe algorithms in ```./push_swap``` to sort the stack are relatively straight-forward. I had 3 different algorithms: one for 5 numbers or less, one for 100 numbers or less, and one for 500 numbers or less. \u003cbr /\u003e\n\nFor 100 \u003c  numbers, I find the median and push everything below the median into **stack b**. Then I identify each the largest and smallest integer in **stack b**, and determine which is most efficient to rotate up/down and push back to **stack a** (along with the specific moves to make that happen). Then I execute those moves. \u003cbr /\u003e\n\nIn this way, integers are pushed back to **stack a** already sorted. I then repeat the process for everything above the median. \u003cbr /\u003e\n\nFor 500 \u003c numbers,  I executed the same process but divided **stack a** by quarters instead of median. \u003cbr /\u003e\n\n## Usage\nRun ```make```.\n\nThe **checker** program is used as follows:\n```c\n  ./checker 5 2 3 1 4\n```\n```c\n  ./checker \"-50 -400 -20 -1 -100\"\n```\n```c\n  ./checker \"-22\" \"35\" \"40\" \"-15\" \"75\"\n```\n\nThe **push_swap** program is used in the same way\n```c\n  ./push_swap 5 2 3 1 4\n```\n\nYou can run the two together using:\n```c\n  ARG=`ruby -e \"puts (0..100).to_a.shuffle.join(' ')\"`; ./push_swap $ARG | ./checker -v $ARG\n```\nNote: the **-v (debug) flag** shows the stack status after each operation. \n![screen capture of checker and push_swap](./images/visualizer.gif)\n\u003cbr /\u003e\n\nTo see push_swap in action, run ```make``` and then the following script:\n```\npython3 pyviz.py `ruby -e \"puts (1..20).to_a.shuffle.join(' ')\"`\n```\n![screen capture of checker and push_swap](./images/visualizer2.gif)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanyaschukin%2FPush_Swap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanyaschukin%2FPush_Swap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanyaschukin%2FPush_Swap/lists"}