catalogue
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