Open In App

Patience Sorting

Last Updated : 24 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Patience sorting is a sorting algorithm based on card game Patience. In this sorting algorithm, the rules of patience game is used to sort an list of elements based on their values.
Rules of Patience Game: 
 

  • Cards with lower value can be placed over the card.
  • If there is no possible position for a card, then a new pile can be created.
  • Goal is to form as much as few piles possible.

Below is the visualization of the game as follows: 
 

As in the above visualization, It’s clear that cards are only placed when the value of them is less than the highest card of the pile. Otherwise, If there is no such pile then create a new one.
Patience Sorting: There are generally two steps in the patience sorting that is creation of the piles and merging the piles. Below is the illustration of the steps: 
 

  • Initialize a 2D array to store the piles.
  • Traverse the given array and perform the following operations: 
    1. Iterate over all the piles and check the top of the stack of each pile is less than the current element or not. IF found to be true, then push the current element to the top of the stack.
    2. Otherwise, create a new pile with the current element as the top of that stack.
  • Merge the Piles:The idea is to perform a k-way merge of the p piles, each of which is internally sorted. Iterate over all the piles while count of elements in the pile is greater than or equal to 0 and find the minimum element from the top of each stack and push it into the sorted array.

Below is the visualization of the sorting steps: 
 

Below is the implementation of the above approach:
 

C++




// C++ program of the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to merge piles in a sorted order
vector<int> merge_piles(vector<vector<int> >& v)
{
 
    // Store minimum element from
    // the top of stack
    vector<int> ans;
 
    // In every iteration find the smallest element
    // of top of pile and remove it from the piles
    // and store into the final array
    while (1) {
 
        // Stores the smallest element
        // of the top of the piles
        int minu = INT_MAX;
 
        // Stores index of the smallest element
        // of the top of the piles
        int index = -1;
 
        // Calculate the smallest element
        // of the top of the every stack
        for (int i = 0; i < v.size(); i++) {
 
            // If minu is greater than
            // the top of the current stack
            if (minu > v[i][v[i].size() - 1]) {
 
                // Update minu
                minu = v[i][v[i].size() - 1];
 
                // Update index
                index = i;
            }
        }
 
        // Insert the smallest element
        // of the top of the stack
        ans.push_back(minu);
 
        // Remove the top element from
        // the current pile
        v[index].pop_back();
 
        // If current pile is empty
        if (v[index].empty()) {
 
            // Remove current pile
            // from all piles
            v.erase(v.begin() + index);
        }
 
        // If all the piles are empty
        if (v.size() == 0)
            break;
    }
    return ans;
}
 
// Function to sort the given array
// using the patience sorting
vector<int> patienceSorting(vector<int> arr)
{
 
    // Store all the created piles
    vector<vector<int> > piles;
 
    // Traverse the array
    for (int i = 0; i < arr.size(); i++) {
 
        // If no piles are created
        if (piles.empty()) {
 
            // Initialize a new pile
            vector<int> temp;
 
            // Insert current element
            // into the pile
            temp.push_back(arr[i]);
 
            // Insert current pile into
            // all the piles
            piles.push_back(temp);
        }
        else {
 
            // Check if top element of each pile
            // is less than or equal to
            // current element or not
            int flag = 1;
 
            // Traverse all the piles
            for (int j = 0; j < piles.size(); j++) {
 
                // Check if the element to be
                // inserted is less than
                // current pile's top
                if (arr[i] < piles[j][piles[j].size() - 1]) {
                    piles[j].push_back(arr[i]);
 
                    // Update flag
                    flag = 0;
                    break;
                }
            }
 
            // If flag is true
            if (flag) {
 
                // Create a new pile
                vector<int> temp;
 
                // Insert current element
                // into temp
                temp.push_back(arr[i]);
 
                // Insert current pile
                // into all the piles
                piles.push_back(temp);
            }
        }
    }
 
    // Store the sorted sequence
    // of the given array
    vector<int> ans;
 
    // Sort the given array
    ans = merge_piles(piles);
 
    // Traverse the array, ans[]
    for (int i = 0; i < ans.size(); i++)
        cout << ans[i] << " ";
 
    return ans;
}
 
// Driver Code
int main()
{
    vector<int> arr = { 6, 12, 2, 8, 3, 7 };
 
    // Function Call
    patienceSorting(arr);
}


Java




// Java program of the above approach
import java.util.*;
 
public class Main {
 
    // Function to merge piles in a sorted order
    public static List<Integer>
    mergePiles(List<List<Integer> > v)
    {
        // Store minimum element from
        // the top of stack
        List<Integer> ans = new ArrayList<Integer>();
 
        // In every iteration find the smallest element
        // of top of pile and remove it from the piles
        // and store into the final array
        while (true) {
 
            // Stores the smallest element
            // of the top of the piles
            int minu = Integer.MAX_VALUE;
 
            // Stores index of the smallest element
            // of the top of the piles
            int index = -1;
 
            // Calculate the smallest element
            // of the top of the every stack
            for (int i = 0; i < v.size(); i++) {
 
                // If minu is greater than
                // the top of the current stack
                if (!v.get(i).isEmpty()
                    && minu > v.get(i).get(v.get(i).size()
                                           - 1)) {
                    minu
                        = v.get(i).get(v.get(i).size() - 1);
                    index = i;
                }
            }
 
            if (index == -1) {
                break;
            }
 
            ans.add(minu);
            v.get(index).remove(v.get(index).size() - 1);
 
            // If current pile is empty
 
            if (v.get(index).isEmpty()) {
                // Remove current pile
                // from all piles
                v.remove(index);
            }
        }
 
        return ans;
    }
 
    // Function to sort the given array
    // using the patience sorting
    public static List<Integer>
    patienceSorting(List<Integer> arr)
    {
        List<List<Integer> > piles
            = new ArrayList<List<Integer> >();
        // Store all the created piles
 
        for (int i = 0; i < arr.size(); i++) {
            // If no piles are created
 
            if (piles.isEmpty()) {
                // Initialize a new pile
 
                List<Integer> temp
                    = new ArrayList<Integer>();
                temp.add(arr.get(i));
                piles.add(temp);
            }
            else {
                // Check if top element of each pile
                // is less than or equal to
                // current element or not
                int flag = 1;
 
                for (int j = 0; j < piles.size(); j++) {
 
                    // Check if the element to be
                    // inserted is less than
                    // current pile's top
                    if (arr.get(i) < piles.get(j).get(
                            piles.get(j).size() - 1)) {
                        piles.get(j).add(arr.get(i));
                        flag = 0;
                        break;
                    }
                }
 
                if (flag == 1) {
                    List<Integer> temp
                        = new ArrayList<Integer>();
                    // Insert current element
                    // into temp
                    temp.add(arr.get(i));
 
                    // Insert current pile
                    // into all the piles
                    piles.add(temp);
                }
            }
        }
 
        // Store the sorted sequence
        // of the given array
        List<Integer> ans = mergePiles(piles);
 
        for (int i = 0; i < ans.size(); i++) {
            System.out.print(ans.get(i) + " ");
        }
 
        return ans;
    }
 
    // Driver Code
 
    public static void main(String[] args)
    {
        List<Integer> arr = new ArrayList<Integer>();
        arr.add(6);
        arr.add(12);
        arr.add(2);
        arr.add(8);
        arr.add(3);
        arr.add(7);
 
        patienceSorting(arr);
    }
}


Javascript




<script>
// Javascript program of the above approach
 
// Function to merge piles in a sorted order
function merge_piles(v) {
 
    // Store minimum element from
    // the top of stack
    let ans = [];
 
    // In every iteration find the smallest element
    // of top of pile and remove it from the piles
    // and store into the final array
    while (1) {
 
        // Stores the smallest element
        // of the top of the piles
        let minu = Number.MAX_SAFE_INTEGER;
 
        // Stores index of the smallest element
        // of the top of the piles
        let index = -1;
 
        // Calculate the smallest element
        // of the top of the every stack
        for (let i = 0; i < v.length; i++) {
 
            // If minu is greater than
            // the top of the current stack
            if (minu > v[i][v[i].length - 1]) {
 
                // Update minu
                minu = v[i][v[i].length - 1];
 
                // Update index
                index = i;
            }
        }
 
        // Insert the smallest element
        // of the top of the stack
        ans.push(minu);
 
        // Remove the top element from
        // the current pile
        v[index].pop();
 
        // If current pile is empty
        if (v[index].length == 0) {
 
            // Remove current pile
            // from all piles
            v.splice(index, 1);
        }
 
        // If all the piles are empty
        if (v.length == 0)
            break;
    }
    return ans;
}
 
// Function to sort the given array
// using the patience sorting
function patienceSorting(arr) {
 
    // Store all the created piles
    let piles = [];
 
    // Traverse the array
    for (let i = 0; i < arr.length; i++) {
 
        // If no piles are created
        if (piles.length == 0) {
 
            // Initialize a new pile
            let temp = [];
 
            // Insert current element
            // into the pile
            temp.push(arr[i]);
 
            // Insert current pile into
            // all the piles
            piles.push(temp);
        }
        else {
 
            // Check if top element of each pile
            // is less than or equal to
            // current element or not
            let flag = 1;
 
            // Traverse all the piles
            for (let j = 0; j < piles.length; j++) {
 
                // Check if the element to be
                // inserted is less than
                // current pile's top
                if (arr[i] < piles[j][piles[j].length - 1]) {
                    piles[j].push(arr[i]);
 
                    // Update flag
                    flag = 0;
                    break;
                }
            }
 
            // If flag is true
            if (flag) {
 
                // Create a new pile
                let temp = [];
 
                // Insert current element
                // into temp
                temp.push(arr[i]);
 
                // Insert current pile
                // into all the piles
                piles.push(temp);
            }
        }
    }
 
    // Store the sorted sequence
    // of the given array
    let ans = [];
 
    // Sort the given array
    ans = merge_piles(piles);
 
    // Traverse the array, ans[]
    for (let i = 0; i < ans.length; i++)
        document.write(ans[i] + " ");
 
    return ans;
}
 
// Driver Code
 
let arr = [6, 12, 2, 8, 3, 7];
 
// Function Call
patienceSorting(arr);
 
// This code is contributed by _saurabh_jaiswal.
</script>


Python3




# Python code to implement the above approach
 
# Function to merge piles in a sorted order
def merge_piles(v):
    # Store minimum element from the top of stack
    ans = []
 
    # In every iteration find the smallest element
    # of top of pile and remove it from the piles
    # and store into the final array
    while True:
        # Stores the smallest element of the top of the piles
        minu = float("inf")
 
        # Stores index of the smallest element of the top of the piles
        index = -1
 
        # Calculate the smallest element of the top of the every stack
        for i in range(len(v)):
            # If minu is greater than the top of the current stack
            if minu > v[i][-1]:
                # Update minu
                minu = v[i][-1]
 
                # Update index
                index = i
 
        # Insert the smallest element of the top of the stack
        ans.append(minu)
 
        # Remove the top element from the current pile
        v[index].pop()
 
        # If current pile is empty
        if not v[index]:
            # Remove current pile from all piles
            v.pop(index)
 
        # If all the piles are empty
        if not v:
            break
 
    return ans
 
# Function to sort the given array using the patience sorting
def patienceSorting(arr):
    # Store all the created piles
    piles = []
 
    # Traverse the array
    for i in range(len(arr)):
        # If no piles are created
        if not piles:
            # Initialize a new pile
            temp = []
 
            # Insert current element into the pile
            temp.append(arr[i])
 
            # Insert current pile into all the piles
            piles.append(temp)
        else:
            # Check if top element of each pile is less than or equal to
            # current element or not
            flag = True
 
            # Traverse all the piles
            for j in range(len(piles)):
                # Check if the element to be inserted is less than
                # current pile's top
                if arr[i] < piles[j][-1]:
                    piles[j].append(arr[i])
 
                    # Update flag
                    flag = False
                    break
 
            # If flag is True
            if flag:
                # Create a new pile
                temp = []
 
                # Insert current element into temp
                temp.append(arr[i])
 
                # Insert current pile into all the piles
                piles.append(temp)
 
    # Store the sorted sequence of the given array
    ans = []
 
    # Sort the given array
    ans = merge_piles(piles)
 
 
    return ans
 
# Driver code
arr = [6, 12, 2, 8, 3, 7]
 
# Function call
print(patienceSorting(arr))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program {
    // Function to merge piles in a sorted order
    public static List<int> MergePiles(List<List<int>> v) {
        // Store minimum element from
        // the top of stack
        List<int> ans = new List<int>();
 
        // In every iteration find the smallest element
        // of top of pile and remove it from the piles
        // and store into the final array
        while (true) {
            // Stores the smallest element
            // of the top of the piles
            int minu = int.MaxValue;
 
            // Stores index of the smallest element
            // of the top of the piles
            int index = -1;
 
            // Calculate the smallest element
            // of the top of the every stack
            for (int i = 0; i < v.Count; i++) {
                // If minu is greater than
                // the top of the current stack
                if (v[i].Any() && minu > v[i].Last()) {
                    minu = v[i].Last();
                    index = i;
                }
            }
 
            if (index == -1) {
                break;
            }
 
            ans.Add(minu);
            v[index].RemoveAt(v[index].Count - 1);
 
            // If current pile is empty
            if (!v[index].Any()) {
                // Remove current pile
                // from all piles
                v.RemoveAt(index);
            }
        }
 
        return ans;
    }
 
    // Function to sort the given array
    // using the patience sorting
    public static List<int> PatienceSorting(List<int> arr) {
        List<List<int>> piles = new List<List<int>>();
 
        // Store all the created piles
        for (int i = 0; i < arr.Count; i++) {
            // If no piles are created
            if (!piles.Any()) {
                // Initialize a new pile
                List<int> temp = new List<int>();
                temp.Add(arr[i]);
                piles.Add(temp);
            } else {
                // Check if top element of each pile
                // is less than or equal to
                // current element or not
                int flag = 1;
 
                for (int j = 0; j < piles.Count; j++) {
                    // Check if the element to be
                    // inserted is less than
                    // current pile's top
                    if (arr[i] < piles[j].Last()) {
                        piles[j].Add(arr[i]);
                        flag = 0;
                        break;
                    }
                }
 
                if (flag == 1) {
                    List<int> temp = new List<int>();
                    // Insert current element
                    // into temp
                    temp.Add(arr[i]);
 
                    // Insert current pile
                    // into all the piles
                    piles.Add(temp);
                }
            }
        }
 
        // Store the sorted sequence
        // of the given array
        List<int> ans = MergePiles(piles);
 
        foreach (int num in ans) {
            Console.Write(num + " ");
        }
 
        return ans;
    }
 
    // Driver Code
    public static void Main(string[] args) {
        List<int> arr = new List<int>() { 6, 12, 2, 8, 3, 7 };
 
        PatienceSorting(arr);
    }
}


Output: 

2 3 6 7 8 12

 

Time Complexity: O(N2) 
Auxiliary Space: O(N)

Note: The above approach can be optimized by merging of piles using priority_queue
Time Complexity: O(N * log(N)) 
Auxiliary Space: O(N)

</br>function playGif(){ </br> var gif = document.getElementById(‘gif’); </br> if (gif.src == “https://media.geeksforgeeks.org/wp-content/uploads/20200501171647/Patience.gif”){ </br> gif.src = “https://media.geeksforgeeks.org/wp-content/uploads/20200501175532/base2.jpg”; </br> }else{ </br> gif.src = “https://media.geeksforgeeks.org/wp-content/uploads/20200501171647/Patience.gif”; </br> } </br>} </br>function playSortingGif(){ </br> var gif1 = document.getElementById(‘sorting’); </br> var gif2 = document.getElementById(‘sorting_gif1’); </br> gif1.style.display = “none”; </br> gif2.style.display = “block”; </br>}</br>function pauseSortingGif(){ </br> var gif1 = document.getElementById(‘sorting’); </br> var gif2 = document.getElementById(‘sorting_gif1’); </br> gif1.style.display = “block”; </br> gif2.style.display = “none”; </br>} </br>
 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads