5

Hi I came across a question in the Algorithms 4th Edition by Robert Sedgewick.

Dequeue sort. Explain how you would sort a deck of cards, with the restriction that the only allowed operations are to look at the values of the top two cards, to exchange the top two cards, and to move the top card to the bottom of the deck.

I was hoping someone could explain how this would be done, I am really lost. Thanks you

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
Navleen Singh
  • 155
  • 2
  • 11

3 Answers3

5

Rather than thinking of the deck having a top and a bottom, imagine that the deck of cards is arranged in a ring. You can imagine having a marker that you place between two specific cards, which then corresponds to the top of the deck. Your operations of "swap the top two cards" is then swapping the two cards to the left of the marker, and the operation of "move the top of the deck to the bottom" then corresponds to moving the marker one step to the left.

Given this, you can naturally adapt bubble sort to work in this setup. Permanently mark one of the positions in the ring as the start point. Then, repeatedly do the following: if the two cards to the left of the marker are out of order, swap them. Then, move the marker one step to the left. As an exception to the rule, if the marker is one step before the marker's initial position, don't do the comparison. If you go around the circle without exchanging anything, you're done!

In pseudocode, this would look as follows:

repeat the following until no swaps are made:
    counting from i = 1 to n - 1, inclusive:
       if the top two cards are out of order, swap them.
       move the top card of the deck to the bottom.
    then, move the top card of the deck to the bottom.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • How do we mark a card? In the provided methods you aren't allowed to access any of the data inside the deck, only swapped or move to the bottom. – Cameron Hall Feb 18 '18 at 22:46
  • @CameronHall The basic idea of this method is correct. Instead of considering "markers", you can do it in this way : Firstly, you iterate all cards and count numbers of the cards. Let's say 5 cards. Then you start to compare. At most you need to compare 4+3+2+1 times. So for the 1st time, compare 4 times(you record current pass's comparison times), then move the last 1 card to the bottom, and start the next pass. For the 2nd time, compare 3 times, then move 2 cards to the bottom and start the 3rd time iteration and so on. For any iterations, if no swap takes place, then it is sorted. – Rick Dec 17 '18 at 06:44
1

A very simple solution is here using java. Just keep shifting the top element by comparing and keep track of the number of sorted elements. On every iteration, it will give us one smallest element based on the position. We will do this based on n and k values. For n values, we will keep shifting based on bigger elements and for k values, we will just keep shifting based on smaller values and eventually, the solution will come. You can try this.

    private void sort(Integer[] a) {
        int n = a.length-1,k=1;
        while (n>0){
            for (int i = 0; i < n; i++) {
                if (a[1]>a[0]){
                    int temp = a[0];
                    a[0] = a[1];
                    a[1] = temp;
                }
                pushToBackAndShift(a);
            }
            for (int i = 0; i < k; i++) {
                if (a[1]<a[0]){
                    int temp = a[0];
                    a[0] = a[1];
                    a[1] = temp;
                }
                pushToBackAndShift(a);
            }
            n--;k++;
        }
        pushToBackAndShift(a);
    }

    private void pushToBackAndShift(Integer[] a) {
        int temp = a[0];
        for (int i = 0; i < a.length-1; i++) {
            a[i] = a[i+1];
        }
        a[a.length-1] = temp;
    }
tom
  • 21,844
  • 6
  • 43
  • 36
0

I have a strategy which seems very straightforward to myself:

Consier this the same as the bubble sort: 1) compare(possibly swap) and then move; 2) dont' compare and move(don't change the order). And two kinds of actions take 52 steps(the length of the decks) in one round.

Condition 1:

    def exchange_move(cards): 
        if cards[0] > cards[1]:
            cards[0], cards[1] = cards[1], cards[0]
            cards.append(cards.popleftL())
        else:    
            cards.append(cards.popleft())

Condition 2:

    def move(cards): 
        cards.append(cards.popleft())

And take these two kinds of actions in each round:

    for i in range(card_len-skip):
        exchange_move(cards)
    for i in range(skip)
        move(cards)

And this is the complete code in Python:

    from collections import deque
    import random
    from enum import Enum
    
    class Suit(Enum):
        __order__ = "spade heart club diamond"
        spade = 1
        heart = 2
        club = 3
        diamond = 4
    
    
    class Card(object):
        def __init__(self, suit, value):
            assert type(suit) == Suit
            assert value > 0 and value < 14
            self._suit = suit
            self._value = value
            self.value = self._get_value()
    
        def _get_value(self):
            return self._suit.value * 13 + self._value
    
        def __lt__(self, other):
            return self.value < other.value
    
        def __str__(self):
            return str((self._suit.name, self._value))
    
    cards = deque(maxlen=52)
    
    for s in Suit:
        for i in range(13):
            cards.append(Card(s, i+1))
    
    random.shuffle(cards)
    
    def is_sorted(cards):
        for i in range(len(cards)-2):
            if cards[i] > cards[i+1]:
                return False
        return True
    
    def exchange_move(cards):
        if cards[0] > cards[1]:
            cards[0], cards[1] = cards[1], cards[0]
        cards.append(cards.popleft())
    
    def move(cards):
        cards.append(cards.popleft())
    
    skip = 0
    while(not is_sorted(cards)):
        if skip == len(cards):
            print('something strange happened')
        for i in range(len(cards)-skip):
            exchange_move(cards)
        for i in range(skip):
            move(cards)
        skip += 1
    
    for c in cards:
        print(c)
Leaderboard
  • 371
  • 1
  • 10
Lerner Zhang
  • 6,184
  • 2
  • 49
  • 66