Programmer's algorithm Q50: Perfect Shuffle

Posted by ryclem on Sun, 10 Oct 2021 03:11:05 +0200

catalogue

1. Problem description

  2. Problem solving analysis

2.1 train of thought 1

2.2 train of thought 2

3. Code and test

4. Postscript

1. Problem description

 

         Question: shuffle 2n cards and find out how many n can restore the original order after 2(n-1) shuffles when 1 < = n < = 100? Consider in two cases:

         Case1: after 2 (n-1) shuffles, the cards return to the original order

         Case2: the first recovery sequence after 2 (n-1) shuffles

         Case2 can be regarded as a special case of case1. Case1 means that if you shuffle m {where m is a factor of 2(n-1)} times, you can return to the original order.

  2. Problem solving analysis

2.1 train of thought 1

         The first feeling is the following "tall" idea:

         Uh... Nevertheless, group theory has only been learned once... When I learn group theory first, I'll see if this road can go through. In fact, there have been several problems that can be solved by group theory in this series. Group theory learning has experienced many times from the beginning to giving up. This time, take the problem to learn and see if you can go further.  

 

2.2 train of thought 2

         (when there is no other way to dazzle) just act recklessly...

         For each n, start from the initial state (it doesn't matter what the initial state is), perform the above permutation operation in an iterative manner, and judge whether it returns to the initial state.

         The algorithm flow is as follows:

 

3. Code and test

# -*- coding: utf-8 -*-
"""
Created on Sat Oct  9 19:33:11 2021

@author: chenxy
"""

# import sys
import time
# import datetime
# import math
# import random
# from   typing import List
# from   queue import Queue
# from   collections import deque
# import itertools as it
import numpy as np

N = 100

ok_list = []

tStart = time.perf_counter()
for n in range(1,N+1):
    start = np.arange(2*n)
    p     = np.zeros_like(start)
    for k in range(n):
        p[2*k]   = start[k]
        p[2*k+1] = start[n+k]
    # print(p)
    
    cur = start
    cnt = 0
    # recover = False
    while 1:
        cur = cur[p]
        cnt = cnt + 1
        if np.array_equal(cur, start):
            # print(n, cur, start, cnt)
            if (2*(n-1) % cnt) == 0:
            # if (2*(n-1)) == cnt:
                # print(n, cur, start, cnt)
                # recover = True
                ok_list.append(n)
                break
        if cnt > 2*(n-1):
            break
    # if recover:
        # ok_list.append(n)
tCost  = time.perf_counter() - tStart
        
print('length of ok_list = {0}, tCost = {1:6.3f}(sec)'.format(len(ok_list),tCost))
print(ok_list)        
    

case1 running result:

length of ok_list = 46, tCost =  0.046(sec)
[1, 2, 3, 4, 6, 7, 9, 10, 12, 15, 16, 19, 21, 22, 24, 27, 30, 31, 34, 36, 37, 40, 42, 45, 49, 51, 52, 54, 55, 57, 64, 66, 69, 70, 75, 76, 79, 82, 84, 87, 90, 91, 96, 97, 99, 100]

case2 running result (comment out "if (2 * (n-1)% CNT) = = 0:", open“   if (2*(n-1)) == cnt:)":

length of ok_list = 45, tCost =  0.059(sec)
[2, 3, 4, 6, 7, 9, 10, 12, 15, 16, 19, 21, 22, 24, 27, 30, 31, 34, 36, 37, 40, 42, 45, 49, 51, 52, 54, 55, 57, 64, 66, 69, 70, 75, 76, 79, 82, 84, 87, 90, 91, 96, 97, 99, 100]

         Embarrassment... The result of case 2 is inconsistent with the result of the original book. I can't think of anything wrong. Which little partner sees the problem. Please don't hesitate to give me advice^-^

4. Postscript

        Two remaining issues:

        (1) Solution based on group theory

        (2) The result of case2 is incorrect

        Well, I'll be back...

        Previous: Programmer's interesting algorithm Q49: more speed, less speed

         For the general catalogue of this series, see: Programmer's interesting algorithm: detailed analysis and Python complete solution

Topics: Python Algorithm