# 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...

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

Topics: Python Algorithm