├── 15 Puzzle ├── fig_puzzle.gif ├── fig_puzzle.py ├── fig_puzzle1.gif ├── n_puzzle.py ├── puzzle.gif ├── puzzle00.gif ├── puzzle1.gif └── readme.md ├── 24 Point ├── 24_point.py └── readme.md ├── Abnormal Curve ├── ac1.png ├── ac2.png ├── plot_paper.py ├── readme.md ├── result1.txt └── result2.txt ├── Convex Hull ├── ch.png ├── convexhull.py └── readme.md ├── Cross River ├── c_r.png ├── people_river.py └── readme.md ├── Einstein's Puzzle ├── 11.png ├── 71.png ├── 72.png ├── 73.png ├── 74.png ├── 75.png ├── 76.png ├── 77.png ├── Albert_Einstein_Problem.py └── readme.md ├── Fractal ├── Chaos_Game.py ├── Koch_curve.py ├── fractal_figure.py ├── julia_140.png ├── julia_20.png ├── julia_28.png ├── koch_3.png ├── m_2_200.png ├── mandelbrot.png ├── mandelbrot1.png ├── readme.md └── tri.png ├── Klotski ├── 0.jpg ├── 1.txt ├── 10.txt ├── 10_k.gif ├── 11.txt ├── 11_k.gif ├── 12.txt ├── 12_k.gif ├── 13.txt ├── 13_k.gif ├── 14.txt ├── 14_k.gif ├── 15.txt ├── 15_k.gif ├── 16.txt ├── 16_k.gif ├── 17.txt ├── 17_k.gif ├── 18.txt ├── 18_k.gif ├── 19.txt ├── 19_k.gif ├── 1_k.gif ├── 1h.jpg ├── 1s.jpg ├── 2.txt ├── 20.txt ├── 20_k.gif ├── 21.txt ├── 21_k.gif ├── 22.txt ├── 22_k.gif ├── 23.txt ├── 23_k.gif ├── 24.txt ├── 24_k.gif ├── 2_k.gif ├── 2h.jpg ├── 2s.jpg ├── 3.txt ├── 3_k.gif ├── 3h.jpg ├── 3s.jpg ├── 4.txt ├── 4_k.gif ├── 4h.jpg ├── 4s.jpg ├── 5.txt ├── 5_k.gif ├── 5h.jpg ├── 5s.jpg ├── 6.jpg ├── 6.txt ├── 6_k.gif ├── 7.jpg ├── 7.txt ├── 7_k.gif ├── 8.jpg ├── 8.txt ├── 8_k.gif ├── 9.jpg ├── 9.txt ├── 9_k.gif ├── k_problerms.py ├── klotski_bfs.py └── readme.md ├── Lottery ├── DLT_DATA.py ├── DLT_SPYDER.py ├── MODEL.py ├── Red_Pro_model1.md ├── SSQ_DATA.py ├── SSQ_DLT_PREDICT.py ├── SSQ_SPYDER.py └── TEST.py ├── Magic Square ├── 10.png ├── 7.png ├── 8.png ├── Magic_Square.py └── readme.md ├── N Queens ├── 8_1.png ├── 8_10.png ├── 8_11.png ├── 8_12.png ├── 8_2.png ├── 8_3.png ├── 8_4.png ├── 8_5.png ├── 8_6.png ├── 8_7.png ├── 8_8.png ├── 8_9.png ├── N_Queens.py ├── queen.gif └── readme.md ├── One_Stroke ├── 108.png ├── 57.png ├── Find_One_Path_Dfs.py ├── Find_Path.py ├── Find_Path_Plus.py ├── dfs.png ├── lujing.jpg ├── readme.md ├── shibie.jpg └── timian.jpg ├── Perfect Maze ├── Maze_AnFany_Wall.py ├── Maze_AnFay_Cell.py ├── Path_For_Cell_AnFany.py ├── Path_For_Wall_AnFany.py ├── Simple_Prim_Maze_Cell.py ├── Simple_Prim_Maze_Wall.py ├── c.png ├── cell.jpg ├── readme.md ├── w.jpg └── wall.jpg ├── README.md ├── Seven Bridge ├── 0.png ├── 00.png ├── 1.png ├── 2.png ├── Seven_Bridge.py ├── fig.png ├── fig_progress.png ├── read_fig_html.py ├── readme.md ├── y1.png └── y2.png ├── Sudoku ├── Sudoku.py ├── Sudoku.xlsx ├── a.png ├── readme.md └── s.png ├── Tower of Hanoi ├── Hanoi.gif ├── Hanoi.py └── readme.md ├── Traveling Salesman ├── 34.png ├── city_distance.csv ├── city_sign.csv ├── genetic_algorithm_tsp_greedy.py ├── get_distance.py ├── iter_path.png ├── read_distance.py ├── readme.md ├── show_result.py ├── tsp.gif └── 城市经纬度.csv ├── bezier ├── Bezier_2.gif ├── Bezier_3.gif ├── Bezier_4.gif ├── Bezier_false.gif ├── Bezier_more_false.gif ├── Bezier_more_true.gif ├── Bezier_n.gif ├── Bezier_true.gif ├── bezier_curve.py ├── bezier_point.py └── readme.md ├── lifegame ├── example_lifegame.py ├── find_relation.py ├── life_game.py ├── life_game_move_shake.py ├── life_game_shake.py ├── life_game_still.py └── readme.md └── plot_puzzle.py /15 Puzzle/fig_puzzle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/15 Puzzle/fig_puzzle.gif -------------------------------------------------------------------------------- /15 Puzzle/fig_puzzle.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | 5 | # 利用IDA*算法实现拼图谜题的生成和解决方案 6 | import n_puzzle 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | import matplotlib.gridspec as gridspec 10 | import imageio # 引入合成gif的库 11 | 12 | 13 | class FigPuzzle(n_puzzle.MNPuzzle): 14 | def __init__(self): 15 | super(FigPuzzle, self).__init__() 16 | # 将图片分成的行数和列数 17 | self.m = 3 18 | self.n = 3 19 | 20 | # 分块后,缺失图片的编号,默认为最后一块:self.m * self.n 21 | self.miss_sign = 9 22 | 23 | # 图片的编号,缺失图片的位置用数字0代替 24 | self.e_p_list = list(range(1, self.m * self.n + 1)) 25 | self.initial_e_p_list = self.e_p_list.copy() 26 | # 谜题的结束状态 27 | self.e_p_list[self.miss_sign - 1] = 0 28 | 29 | # 谜题的开始状态 30 | self.p_list = self.generate_puzzle() 31 | 32 | # 图片路径 33 | self.fig_file = r'C:\Users\GWT9\Desktop\love.jpg' 34 | # 切割线的宽度为多少像素 35 | self.cut_width = 5 36 | # 可以自定义切割线的颜色的RGB字典 37 | self.cut_color_number = 1 38 | 39 | # 需要作为谜题的图片的矩阵 40 | self.matrix = self.fig_to_matrix() 41 | 42 | self.height, self.width, self.channel = self.matrix.shape # 矩阵是三维的,第三个值一般为4(RGBA)或者为3(RGB),没有影响 43 | 44 | # 不考虑除不尽的情形,因为self.row, self.column都比较小。 45 | self.per_h = self.height // self.m 46 | self.per_w = self.width // self.n 47 | 48 | # 数字对应的图片的矩阵,依据数字不同排列,从而展示不同的组合的图片 49 | self.digital_matrix_dict = self.cut_matrix_dict() 50 | 51 | def fig_to_matrix(self): 52 | """ 53 | 将图片转化为分块的数据矩阵的字典 54 | :return: 55 | """ 56 | plt.figure() 57 | matrix = plt.imread(self.fig_file) 58 | if self.fig_file[-3:] == 'jpg': 59 | return matrix / 255 60 | 61 | return matrix 62 | 63 | def cut_matrix_dict(self): 64 | # 下面就按照编号对矩阵矩阵进行分块 65 | 66 | # 开始分块 67 | sign_matrix_dict = {} 68 | for i in range(1, self.m * self.n + 1): 69 | r_i = (i - 1) // self.n 70 | c_i = (i - 1) % self.n 71 | sign_matrix_dict[i] = self.matrix[r_i * self.per_h: (r_i + 1) * self.per_h, 72 | c_i * self.per_w: (c_i + 1) * self.per_w, :] 73 | return sign_matrix_dict 74 | 75 | def matrix_to_fig(self, number_list): 76 | """ 77 | 根据数字的序列,返回重新排列的矩阵,重新排列的矩阵,需要包括中间的分割线。以及缺失的图片 78 | :param number_list: 数字的序列 79 | :return: 数字矩阵 80 | """ 81 | # 计算新的矩阵需要的维度,初始值定义为cut_color_number 82 | new_matrix = np.ones((self.height + (self.m - 1) * self.cut_width, 83 | self.width + (self.n - 1) * self.cut_width, self.channel)) * self.cut_color_number 84 | 85 | # 开始更新矩阵 86 | for index, value in enumerate(number_list): 87 | if value != 0: 88 | # 计算该数字对应的矩阵位置在哪里 89 | a_row = index // self.n 90 | a_column = index % self.n 91 | # 开始更新矩阵 92 | new_matrix[a_row * self.per_h + (a_row * self.cut_width): 93 | (a_row + 1) * self.per_h + (a_row * self.cut_width), 94 | a_column * self.per_w + (a_column * self.cut_width): 95 | (a_column + 1) * self.per_w + (a_column * self.cut_width), :] \ 96 | = self.digital_matrix_dict[value] 97 | return new_matrix 98 | 99 | def generate_puzzle(self): 100 | """ 101 | 对于图片谜题而言,结束状态的逆序数一定为0,因此要保证随机生成的谜题的逆序数为偶数 102 | 为了保证谜题的复杂。此时要使得谜题的逆序数稍微大点 103 | :return: 数码谜题 104 | """ 105 | # 随机50次,获取其中最大的逆序数对应的谜题 106 | times = 0 107 | i_count = 0 108 | p_list = self.e_p_list.copy() 109 | start_p_list = [] 110 | while times < 50: 111 | np.random.shuffle(p_list) 112 | # 计算逆序数 113 | new_i = self.inverse_count(p_list) 114 | # 根据列数的奇偶性判断 115 | if self.n % 2 == 1: 116 | if i_count < new_i and new_i % 2 == 0: 117 | i_count = new_i 118 | start_p_list = p_list.copy() 119 | else: 120 | z_index = p_list.index(0) 121 | z_row = z_index // self.n 122 | if i_count < new_i and (new_i + self.m - 1 - z_row) % 2 == 0: 123 | i_count = new_i 124 | start_p_list = p_list.copy() 125 | times += 1 126 | return start_p_list 127 | 128 | def get_state_list(self): 129 | """ 130 | 根据起始和结束状态,获取行为列表,根据行为列表获取状态列表 131 | :return: 状态列表 132 | """ 133 | action_str = self.ida_star_puzzle() 134 | state_list = [self.p_list] 135 | for a in action_str: 136 | state_list.append(self.get_next_p(state_list[-1], a)) 137 | return state_list 138 | 139 | def plot_fig_puzzle(self, state_list): 140 | """ 141 | 根据状态列表绘制图片 142 | :param state_list: 状态列表 143 | :return: 图片 144 | """ 145 | for index, value in enumerate(state_list): 146 | # 首先根据起始和结束状态获取行为列表 147 | fig = plt.figure() 148 | gs = gridspec.GridSpec(2, 3) 149 | # 绘制初始状态 150 | ax = fig.add_subplot(gs[0, 0]) 151 | ax.set_xticks([]) 152 | ax.set_yticks([]) 153 | ax.set_title('起始') 154 | start_array = self.matrix_to_fig(self.p_list) 155 | ax.imshow(start_array) 156 | 157 | # 绘制结束状态 158 | ax = fig.add_subplot(gs[1, 0]) 159 | ax.set_title('结束,第%d块空白' % self.miss_sign) 160 | ax.set_xticks([]) 161 | ax.set_yticks([]) 162 | end_array = self.matrix_to_fig(self.initial_e_p_list) 163 | ax.imshow(end_array) 164 | 165 | # 绘制中间状态 166 | ax = fig.add_subplot(gs[:, 1:]) 167 | if index == 0: 168 | ax.set_title('中间转换:开始转换') 169 | elif index != len(state_list) - 1: 170 | ax.set_title('中间转换状态:总共$%d$步,当前$%d$步' % (len(state_list) - 1, index)) 171 | else: 172 | ax.set_title('转换完成') 173 | ax.set_xticks([]) 174 | ax.set_yticks([]) 175 | end_array = self.matrix_to_fig(value) 176 | ax.imshow(end_array) 177 | plt.savefig(r'./fig_%d_%d.png' % (len(state_list), index+1)) 178 | plt.close() 179 | 180 | image_list = ['fig_%d_%d.png' % (len(state_list), index+1) for index in range(len(state_list))] 181 | 182 | frames = [] 183 | for image_name in image_list + [image_list[-1]] * 10: 184 | frames.append(imageio.imread(image_name)) 185 | imageio.mimsave('fig_puzzle.gif', frames, 'GIF', duration=0.9) # 图片合成为动图 186 | 187 | return print('gif生成完毕') 188 | 189 | # 主函数 190 | 191 | 192 | if __name__ == "__main__": 193 | 194 | f_p = FigPuzzle() 195 | print('谜题的初始状态为:\n', np.array(f_p.p_list).reshape(f_p.m, f_p.n)) 196 | # 获取谜题移动的中间状态 197 | a = f_p.get_state_list() 198 | print('中间状态生成完毕,绘制动图……') 199 | # 绘制图 200 | f_p.plot_fig_puzzle(a) 201 | 202 | 203 | -------------------------------------------------------------------------------- /15 Puzzle/fig_puzzle1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/15 Puzzle/fig_puzzle1.gif -------------------------------------------------------------------------------- /15 Puzzle/puzzle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/15 Puzzle/puzzle.gif -------------------------------------------------------------------------------- /15 Puzzle/puzzle00.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/15 Puzzle/puzzle00.gif -------------------------------------------------------------------------------- /15 Puzzle/puzzle1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/15 Puzzle/puzzle1.gif -------------------------------------------------------------------------------- /15 Puzzle/readme.md: -------------------------------------------------------------------------------- 1 | ### 十五谜题 2 | 3 | 4 | #### 一、MN数码谜题 5 | 6 | * **程序:[n_puzzle.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/n_puzzle.py)** 7 | 8 | * **结果展示** 9 | 10 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/puzzle1.gif) 11 | 12 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/puzzle.gif) 13 | 14 | 15 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/puzzle00.gif) 16 | 17 | 18 | #### 二、图片拼图谜题 19 | 20 | * **程序:[fig_puzzle.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/fig_puzzle.py)** 21 | 22 | * **结果展示** 23 | 24 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/fig_puzzle.gif) 25 | 26 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/15%20Puzzle/fig_puzzle1.gif) 27 | 28 | 29 | -------------------------------------------------------------------------------- /24 Point/24_point.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 引入组合库 5 | import itertools 6 | 7 | # 算子列表 8 | operator = ['+', '-', '*', '/'] 9 | # 算子和括号的组合只存在如下五种表达式结构 10 | format = ['((%d%s%d)%s%d)%s%d', \ 11 | '(%d%s%d)%s(%d%s%d)', \ 12 | '(%d%s(%d%s%d))%s%d', \ 13 | '%d%s((%d%s%d)%s%d)', \ 14 | '%d%s(%d%s(%d%s%d))'] 15 | 16 | 17 | # 数字和字母穿插 18 | def Chuan(num, letter): 19 | chuan = [] 20 | for jj in range(len(num)): 21 | chuan.append(num[jj]) 22 | try: 23 | chuan.append(letter[jj]) 24 | except IndexError: 25 | pass 26 | return chuan 27 | 28 | 29 | # 构建数字和算子的组合 30 | def Combine(numlist, oplist=operator): 31 | expre = [] 32 | for jj in list(itertools.permutations(numlist, len(numlist))): 33 | for ii in list(itertools.product(oplist, repeat=3)): 34 | expre.append(Chuan(list(jj), list(ii))) 35 | return expre 36 | 37 | 38 | # 获取全部表达式 39 | def GetExpression(numlist, target, form=format): 40 | expre = set() 41 | exall = Combine(numlist) 42 | for gg in exall: 43 | for ff in form: 44 | try: 45 | ex = str(ff) % tuple(gg) 46 | if eval(ex) == target: 47 | expre.add(ex) 48 | except ZeroDivisionError: 49 | pass 50 | return expre 51 | 52 | 53 | import re 54 | 55 | 56 | # 提取表达是中数字和算子的函数 57 | def NumOperator(nustr): 58 | save = [] 59 | start = '' 60 | for sr in nustr: 61 | try: 62 | int(sr) 63 | start += sr 64 | except ValueError: 65 | if start == '': 66 | save.append(sr) 67 | else: 68 | save.append(start) 69 | save.append(sr) 70 | start = '' 71 | if start != '': 72 | save.append(start) 73 | return save 74 | 75 | 76 | # 删剪掉相近的表达式函数 77 | def Simple(exprelist): 78 | simple = [] 79 | last = [] 80 | for ex in exprelist: 81 | sr = ex 82 | rema = re.findall("\([^()]+\)", ex) # 匹配小括号里的内容 83 | # 将匹配出来的内容进行替换 84 | for ii in rema: 85 | ex = ex.replace(ii, str(eval(ii))) 86 | # 提取简化表达式中的数字和算子 87 | simop = NumOperator(ex) 88 | if sorted(simop) not in simple: 89 | simple.append(sorted(simop)) 90 | last.append(sr) 91 | return last 92 | 93 | 94 | express = Simple(list(GetExpression([2, 5, 8, 8], 24))) 95 | if len(express) == 0: 96 | print('无结果') 97 | else: 98 | print('去掉数学角度上重复的表达式后:') 99 | for sig in express: 100 | print('%s = %d' % (sig, eval(sig))) 101 | -------------------------------------------------------------------------------- /24 Point/readme.md: -------------------------------------------------------------------------------- 1 | # 24 Point 2 | 3 | 4 | * **程序文件**:[24_point.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/24%20Point/24_point.py) 5 | 6 | 7 | * **结果示图**: 8 | 9 | ```python 10 | 去掉数学角度上重复的表达式后: 11 | (5*8)-(8*2) = 24 12 | (8+(8*5))/2 = 24 13 | ``` 14 | -------------------------------------------------------------------------------- /Abnormal Curve/ac1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Abnormal Curve/ac1.png -------------------------------------------------------------------------------- /Abnormal Curve/ac2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Abnormal Curve/ac2.png -------------------------------------------------------------------------------- /Abnormal Curve/readme.md: -------------------------------------------------------------------------------- 1 | # 变态曲线 Abnormal Curve 2 | 3 | * **程序文件** 4 | 5 | + [plot_paper.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Abnormal%20Curve/plot_paper.py) 6 | 7 | 8 | * **结果图示** 9 | 10 | + **标准样式:X、Y轴间隔均为1,其中直线条数取15** 11 | 12 | - 面积分布文本:[result1.txt](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Abnormal%20Curve/result1.txt) 13 | 14 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Abnormal%20Curve/ac1.png) 15 | 16 | + **其他样式:X、Y轴间隔分别为3、4,其中直线条数取50** 17 | 18 | - 面积分布文本:[result2.txt](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Abnormal%20Curve/result2.txt) 19 | 20 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Abnormal%20Curve/ac2.png) 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Abnormal Curve/result1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Abnormal Curve/result1.txt -------------------------------------------------------------------------------- /Abnormal Curve/result2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Abnormal Curve/result2.txt -------------------------------------------------------------------------------- /Convex Hull/ch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Convex Hull/ch.png -------------------------------------------------------------------------------- /Convex Hull/readme.md: -------------------------------------------------------------------------------- 1 | # Convex Hull 程序说明 2 | 3 | 4 | * **动态生成凸包**:[convexhull.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Convex%20Hull/convexhull.py) 5 | 6 | * **示图:** 7 | 8 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Convex%20Hull/ch.png) 9 | 10 | 11 | -------------------------------------------------------------------------------- /Cross River/c_r.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Cross River/c_r.png -------------------------------------------------------------------------------- /Cross River/readme.md: -------------------------------------------------------------------------------- 1 | ## 八人过河问题 2 | 3 | 4 | #### 思路 5 | 6 | 利用状态空间BFS搜索算法,获取过河方案。 7 | 8 | 9 | #### Python3程序 10 | 11 | [people_river.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Cross%20River/people_river.py) 12 | 13 | #### 解决方案 14 | 15 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Cross%20River/c_r.png) 16 | -------------------------------------------------------------------------------- /Einstein's Puzzle/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/11.png -------------------------------------------------------------------------------- /Einstein's Puzzle/71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/71.png -------------------------------------------------------------------------------- /Einstein's Puzzle/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/72.png -------------------------------------------------------------------------------- /Einstein's Puzzle/73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/73.png -------------------------------------------------------------------------------- /Einstein's Puzzle/74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/74.png -------------------------------------------------------------------------------- /Einstein's Puzzle/75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/75.png -------------------------------------------------------------------------------- /Einstein's Puzzle/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/76.png -------------------------------------------------------------------------------- /Einstein's Puzzle/77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Einstein's Puzzle/77.png -------------------------------------------------------------------------------- /Einstein's Puzzle/readme.md: -------------------------------------------------------------------------------- 1 | # 爱因斯坦问题 2 | 3 | 在一条街上,有5座房子,喷了不同的5种颜色。每个房子里住着不同国籍的人。每个人喝着不同的饮料,抽不同品牌的香烟,养不同的宠物。 问:谁养鱼? 4 | 5 | 提示: 6 | ``` 7 | 1、英国人住红色房子。 8 | 2、瑞典人养狗。 9 | 3、丹麦人喝茶。 10 | 4、绿色房子紧挨着白色房子,并在白色房子左边。 11 | 5、绿色房子主人喝咖啡。 12 | 6、抽Pall Mall香烟的人养鸟。 13 | 7、黄色房子主人抽Dunhill香烟。 14 | 8、住在中间房子的人喝牛奶。 15 | 9、挪威人住第一间房。 16 | 10、抽Blends香烟的人住在养猫的人隔壁。 17 | 11、养马的人住抽Dunhill香烟的人隔壁。 18 | 12、抽Blue Master的人喝啤酒。 19 | 13、德国人抽Prince香烟。 20 | 14、挪威人住蓝色房子隔壁。 21 | 15、抽Blends香烟的人有一个喝水的邻居。 22 | ``` 23 | **注意**:条件4中绿色房子和白色房子是相邻的,此时最终结果只有一种可能性。如果绿色房子也可以和白色房子不相邻,则有7种结果。 24 | 25 | 26 | * **程序文件**:[Albert_Einstein_Problem.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/Albert_Einstein_Problem.py) 27 | 28 | * **结果展示:一种可能性** 29 | 30 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/11.png) 31 | 32 | 33 | 34 | * **绿色房子在白色房子左边,相邻或者不相邻均可:七种可能性** 35 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/71.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/72.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/73.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/74.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/75.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/76.png)![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Einstein's%20Puzzle/77.png) 36 | -------------------------------------------------------------------------------- /Fractal/Chaos_Game.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | 5 | # 利用python绘制混沌游戏产生的图形,也就是 6 | 7 | from matplotlib.path import Path 8 | from matplotlib.patches import PathPatch 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from pylab import mpl # 作图显示中文 12 | 13 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 设置中文字体为新宋体 14 | 15 | 16 | class CHAOS(): 17 | def __init__(self): 18 | 19 | # 设定图像的横纵坐标最大最小值, 最大最小值 20 | self.x_min_max = [4, 10] 21 | self.y_min_max = [1, 8] 22 | 23 | # 初始的三个点的位置的横纵坐标系列 24 | self.initial_point = [[sum(self.x_min_max) / 2, self.x_min_max[0] + 1, self.x_min_max[1] - 1], 25 | [self.y_min_max[1] - 1, self.y_min_max[0] + 1, self.y_min_max[0] + 1]] 26 | 27 | # 迭代次数 28 | self.t = 8 # 该数值越大,产生的图像越接近于谢尔宾斯基三角形 29 | 30 | # 初始三个点的颜色 31 | self.i_c = 'tab:red' 32 | # 第四个随机点的颜色 33 | self.f_c = 'tab:green' 34 | # 其他点的颜色 35 | self.o_c = 'tab:blue' 36 | 37 | self.p_fig = r'C:\Users\GWT9\Desktop' # 保存图片的地址 38 | 39 | def SierpinskiTriangle_chaos_game(self): 40 | """ 41 | 绘制混沌游戏产生的图形,也就是利用随机方法生成谢尔宾斯基三角形 42 | :return: 图形 43 | """ 44 | # 需要绘制的散点的集合 45 | need_plot = self.initial_point 46 | # 随机选取第四个点的位置,为了便于展示,在横纵坐标的范围内随机选取一点。 47 | the_firth_point = [np.random.randint(self.x_min_max[0], self.x_min_max[1] + 1, 1), 48 | np.random.randint(self.y_min_max[0], self.y_min_max[1] + 1, 1)] 49 | times = 0 50 | 51 | # 第四个点添加到集合中 52 | need_plot[0].append(the_firth_point[0]) 53 | need_plot[1].append(the_firth_point[1]) 54 | 55 | while 1: 56 | # 在初始的3个点中随机选择1个。 57 | random = np.random.randint(0, 3, 1)[0] 58 | # 被选中的点 59 | selected_point_x = self.initial_point[0][random] 60 | selected_point_y = self.initial_point[1][random] 61 | 62 | # 选取这个点和最后一个新加入的点的中点作为下一个新加入的点 63 | next_point = [(selected_point_x + need_plot[0][-1]) / 2, 64 | (selected_point_y + need_plot[1][-1]) / 2] 65 | 66 | need_plot[0].append(next_point[0]) 67 | need_plot[1].append(next_point[1]) 68 | 69 | times += 1 70 | if times > self.t: 71 | break 72 | 73 | # 开始绘制散点图 74 | plt.scatter(need_plot[0][:3], need_plot[1][:3], s=25, marker='^', c=self.i_c, label='初始点') 75 | plt.scatter(need_plot[0][3:4], need_plot[1][3:4], s=25, marker='*', c=self.f_c, label='第四个点') 76 | plt.scatter(need_plot[0][4:], need_plot[1][4:], s=5, marker='o', c=self.o_c, label='其他点') 77 | plt.title('谢尔宾斯基三角形:随机方法, 加入点的个数%d' % self.t) 78 | plt.rcParams['savefig.dpi'] = 1000 # 数值越大,图片越清晰 79 | plt.legend() 80 | plt.axis('off') 81 | 82 | plt.savefig(r'%s\SierpinskiTriangle_chaos.png' % self.p_fig) 83 | return print('SierpinskiTriangle随机图片保存完毕') 84 | 85 | def SierpinskiTriangle_iter_game(self): 86 | """ 87 | 利用迭代的方法生成谢尔宾斯基三角形 88 | :return: 谢尔宾斯基三角形 89 | """ 90 | # 初始的三个点的坐标 91 | initial_point_set = [[self.initial_point[0][0], self.initial_point[1][0]], 92 | [self.initial_point[0][1], self.initial_point[1][1]], 93 | [self.initial_point[0][2], self.initial_point[1][2]]] 94 | 95 | codes = [Path.MOVETO] + [Path.LINETO] * 2 + [Path.CLOSEPOLY] 96 | vertices = np.array(initial_point_set + [[0, 0]], float) 97 | path = Path(vertices, codes) 98 | pathpatch = PathPatch(path, facecolor='k', edgecolor=None) 99 | 100 | # 开始绘图 101 | fig, ax = plt.subplots() 102 | ax.add_patch(pathpatch) 103 | 104 | times = 0 105 | 106 | # 存储需要切割的三角形 107 | need_to_cut = [initial_point_set] 108 | while 1: 109 | # 遍历当前所有需要切割的三角形 110 | cc = [] 111 | for t in need_to_cut: 112 | # 获取这个三角形的三边的中点 113 | center_point = [] 114 | for o, l in zip(t, t[1:] + [t[0]]): 115 | center_point.append([(o[0] + l[0]) / 2, (o[1] + l[1]) / 2]) 116 | # 新组成的三角形需要被挖空 117 | codes = [Path.MOVETO] + [Path.LINETO] * 2 + [Path.CLOSEPOLY] 118 | vertices = np.array(center_point + [[0, 0]], float) 119 | path = Path(vertices, codes) 120 | pathpatch = PathPatch(path, facecolor='white', edgecolor=None) 121 | ax.add_patch(pathpatch) 122 | 123 | # 此时需要将新形成的三个三角形添加到需要切割的三角形集合中 124 | 125 | cc.append([t[0], center_point[0], center_point[2]]) 126 | cc.append([center_point[0], t[1], center_point[1]]) 127 | cc.append([center_point[1], t[2], center_point[2]]) 128 | 129 | need_to_cut = cc.copy() 130 | 131 | times += 1 132 | if times > self.t: 133 | break 134 | ax.set_title('谢尔宾斯基三角形:迭代方法, 迭代次数%d' % self.t) 135 | ax.set_xlim(self.x_min_max[0], self.x_min_max[1]) 136 | ax.set_ylim(self.y_min_max[0], self.y_min_max[1]) 137 | plt.axis('off') 138 | plt.savefig(r'%s\SierpinskiTriangle_iter.png' % self.p_fig) 139 | return print('SierpinskiTriangle迭代图片保存完毕') 140 | 141 | 142 | # 主函数 143 | if __name__ == "__main__": 144 | # 随机方法 145 | s = CHAOS() 146 | s.t = 20000 147 | s.SierpinskiTriangle_chaos_game() 148 | 149 | # 迭代方法 150 | s = CHAOS() 151 | s.t = 8 152 | s.SierpinskiTriangle_iter_game() 153 | -------------------------------------------------------------------------------- /Fractal/Koch_curve.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | 5 | # 利用python绘制科赫雪花曲线 6 | from math import cos, sin, radians 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | from pylab import mpl # 作图显示中文 10 | 11 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 设置中文字体为新宋体 12 | 13 | 14 | class KOCH(): 15 | def __init__(self): 16 | 17 | # 设定图像的横纵坐标最大最小值, 最大最小值 18 | self.x_min_max = [4, 10] 19 | self.y_min_max = [1, 8] 20 | 21 | # 初始的三角形三个点的位置的横纵坐标系列,因为要保证凸起的点是逆时针旋转的,因此下面的点的顺序要是顺时针的 22 | self.initial_point = [[sum(self.x_min_max) / 2, self.x_min_max[1] - 1, self.x_min_max[0] + 1], 23 | [self.y_min_max[1] - 1, self.y_min_max[0] + 1, self.y_min_max[0] + 1]] 24 | 25 | # 迭代次数 26 | self.t = 3 27 | 28 | self.p_fig = r'C:\Users\GWT9\Desktop' # 保存图片的地址 29 | 30 | def plot_koch(self): 31 | """ 32 | 利用迭代的方法生成科赫雪花曲线 33 | :return: 科赫雪花曲线 34 | """ 35 | # 初始的三个点的坐标 36 | 37 | times = 1 38 | # 存储需要连接的点的横、纵坐标 39 | 40 | need_to_line_x = self.initial_point[0] + [self.initial_point[0][0]] 41 | need_to_line_y = self.initial_point[1] + [self.initial_point[0][0]] 42 | 43 | while 1: 44 | 45 | # 遍历当前所有需要连接的点 46 | cc_x = [] 47 | cc_y = [] 48 | for nx1, ny1, nx2, ny2 in zip(need_to_line_x[:-1], need_to_line_y[:-1], 49 | need_to_line_x[1:], need_to_line_y[1:]): 50 | 51 | cc_x.append(nx1) 52 | cc_y.append(ny1) 53 | 54 | # 两点之间线段的,2个三分点的坐标 55 | x1 = nx1 + (nx2 - nx1) / 3 56 | x2 = nx1 + 2 * (nx2 - nx1) / 3 57 | 58 | y1 = ny1 + (ny2 - ny1) / 3 59 | y2 = ny1 + 2 * (ny2 - ny1) / 3 60 | 61 | cc_x.append(x1) 62 | cc_y.append(y1) 63 | 64 | # 计算突出的点, 65 | new_x = (x2 - x1) * cos(radians(60)) - (y2 - y1) * sin(radians(60)) + x1 66 | 67 | new_y = (x2 - x1) * sin(radians(60)) + (y2 - y1) * cos(radians(60)) + y1 68 | 69 | cc_x.append(new_x) 70 | cc_y.append(new_y) 71 | 72 | cc_x.append(x2) 73 | cc_y.append(y2) 74 | 75 | cc_x.append(cc_x[0]) 76 | cc_y.append(cc_y[0]) 77 | 78 | need_to_line_x = cc_x.copy() 79 | need_to_line_y = cc_y.copy() 80 | 81 | times += 1 82 | if times > self.t: 83 | break 84 | 85 | plt.plot(need_to_line_x, need_to_line_y, c='k', lw=1) 86 | plt.axis('off') 87 | plt.title('koch雪花曲线迭代图 迭代次数%d' % self.t) 88 | plt.show() 89 | plt.savefig(r'%s\koch.png' % self.p_fig) 90 | return print('koch雪花曲线迭代图片保存完毕') 91 | 92 | 93 | # 主函数 94 | if __name__ == "__main__": 95 | # 随机方法 96 | k = KOCH() 97 | k.plot_koch() 98 | 99 | 100 | -------------------------------------------------------------------------------- /Fractal/julia_140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/julia_140.png -------------------------------------------------------------------------------- /Fractal/julia_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/julia_20.png -------------------------------------------------------------------------------- /Fractal/julia_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/julia_28.png -------------------------------------------------------------------------------- /Fractal/koch_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/koch_3.png -------------------------------------------------------------------------------- /Fractal/m_2_200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/m_2_200.png -------------------------------------------------------------------------------- /Fractal/mandelbrot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/mandelbrot.png -------------------------------------------------------------------------------- /Fractal/mandelbrot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/mandelbrot1.png -------------------------------------------------------------------------------- /Fractal/readme.md: -------------------------------------------------------------------------------- 1 | ### 分形 2 | 3 | 4 | #### 一、基于复动力系统 5 | 6 | * **Julia集和Mandelbrot集** 7 | 8 | + **程序:[fractal_figure.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/fractal_figure.py)** 9 | 10 | + **图示** 11 | 12 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/julia_20.png) 13 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/julia_28.png) 14 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/julia_140.png) 15 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/m_2_200.png) 16 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/mandelbrot.png) 17 | 18 | 具有局部放大的图像: 19 | 20 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/mandelbrot1.png) 21 | 22 | 23 | 24 | #### 二、基于迭代函数系统 25 | 26 | * **科赫雪花** 27 | 28 | + **程序:[Koch_curve.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/Koch_curve.py)** 29 | 30 | + **图示** 31 | 32 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/koch_3.png) 33 | 34 | 35 | * **谢尔宾斯基三角形** 36 | 37 | + **程序:[Chaos_Game.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/Chaos_Game.py)** 38 | 39 | + **图示** 40 | 41 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Fractal/tri.png) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Fractal/tri.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Fractal/tri.png -------------------------------------------------------------------------------- /Klotski/0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/0.jpg -------------------------------------------------------------------------------- /Klotski/1.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/1.txt -------------------------------------------------------------------------------- /Klotski/10.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/10.txt -------------------------------------------------------------------------------- /Klotski/10_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/10_k.gif -------------------------------------------------------------------------------- /Klotski/11.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/11.txt -------------------------------------------------------------------------------- /Klotski/11_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/11_k.gif -------------------------------------------------------------------------------- /Klotski/12.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/12.txt -------------------------------------------------------------------------------- /Klotski/12_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/12_k.gif -------------------------------------------------------------------------------- /Klotski/13.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/13.txt -------------------------------------------------------------------------------- /Klotski/13_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/13_k.gif -------------------------------------------------------------------------------- /Klotski/14.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/14.txt -------------------------------------------------------------------------------- /Klotski/14_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/14_k.gif -------------------------------------------------------------------------------- /Klotski/15.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/15.txt -------------------------------------------------------------------------------- /Klotski/15_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/15_k.gif -------------------------------------------------------------------------------- /Klotski/16.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/16.txt -------------------------------------------------------------------------------- /Klotski/16_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/16_k.gif -------------------------------------------------------------------------------- /Klotski/17.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/17.txt -------------------------------------------------------------------------------- /Klotski/17_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/17_k.gif -------------------------------------------------------------------------------- /Klotski/18.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/18.txt -------------------------------------------------------------------------------- /Klotski/18_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/18_k.gif -------------------------------------------------------------------------------- /Klotski/19.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/19.txt -------------------------------------------------------------------------------- /Klotski/19_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/19_k.gif -------------------------------------------------------------------------------- /Klotski/1_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/1_k.gif -------------------------------------------------------------------------------- /Klotski/1h.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/1h.jpg -------------------------------------------------------------------------------- /Klotski/1s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/1s.jpg -------------------------------------------------------------------------------- /Klotski/2.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/2.txt -------------------------------------------------------------------------------- /Klotski/20.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/20.txt -------------------------------------------------------------------------------- /Klotski/20_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/20_k.gif -------------------------------------------------------------------------------- /Klotski/21.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/21.txt -------------------------------------------------------------------------------- /Klotski/21_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/21_k.gif -------------------------------------------------------------------------------- /Klotski/22.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/22.txt -------------------------------------------------------------------------------- /Klotski/22_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/22_k.gif -------------------------------------------------------------------------------- /Klotski/23.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/23.txt -------------------------------------------------------------------------------- /Klotski/23_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/23_k.gif -------------------------------------------------------------------------------- /Klotski/24.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/24.txt -------------------------------------------------------------------------------- /Klotski/24_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/24_k.gif -------------------------------------------------------------------------------- /Klotski/2_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/2_k.gif -------------------------------------------------------------------------------- /Klotski/2h.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/2h.jpg -------------------------------------------------------------------------------- /Klotski/2s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/2s.jpg -------------------------------------------------------------------------------- /Klotski/3.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/3.txt -------------------------------------------------------------------------------- /Klotski/3_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/3_k.gif -------------------------------------------------------------------------------- /Klotski/3h.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/3h.jpg -------------------------------------------------------------------------------- /Klotski/3s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/3s.jpg -------------------------------------------------------------------------------- /Klotski/4.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/4.txt -------------------------------------------------------------------------------- /Klotski/4_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/4_k.gif -------------------------------------------------------------------------------- /Klotski/4h.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/4h.jpg -------------------------------------------------------------------------------- /Klotski/4s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/4s.jpg -------------------------------------------------------------------------------- /Klotski/5.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/5.txt -------------------------------------------------------------------------------- /Klotski/5_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/5_k.gif -------------------------------------------------------------------------------- /Klotski/5h.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/5h.jpg -------------------------------------------------------------------------------- /Klotski/5s.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/5s.jpg -------------------------------------------------------------------------------- /Klotski/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/6.jpg -------------------------------------------------------------------------------- /Klotski/6.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/6.txt -------------------------------------------------------------------------------- /Klotski/6_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/6_k.gif -------------------------------------------------------------------------------- /Klotski/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/7.jpg -------------------------------------------------------------------------------- /Klotski/7.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/7.txt -------------------------------------------------------------------------------- /Klotski/7_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/7_k.gif -------------------------------------------------------------------------------- /Klotski/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/8.jpg -------------------------------------------------------------------------------- /Klotski/8.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/8.txt -------------------------------------------------------------------------------- /Klotski/8_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/8_k.gif -------------------------------------------------------------------------------- /Klotski/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/9.jpg -------------------------------------------------------------------------------- /Klotski/9.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/9.txt -------------------------------------------------------------------------------- /Klotski/9_k.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Klotski/9_k.gif -------------------------------------------------------------------------------- /Klotski/k_problerms.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 24局的三国华容道题目 5 | 6 | # 按照'曹操', '关羽', '张飞', '赵云', '马超', '黄忠', '兵1', '兵2', '兵3', '兵4'的顺序 7 | # [2, 0], 2, 2]表示关羽所占的左下角的位置为2行0列。关羽占的高度为2,宽度也为2 8 | 9 | K_SIGN = {1: '横刀立马1', 2: '横刀立马2', 3: '齐头并前', 4: '兵分三路', 5: '屯兵东路', 10 | 6: '左右步兵', 7: '前挡后阻', 8: '插翅难飞', 9: '近在咫尺', 10: '层层设防', 11 | 11: '水泄不通', 12: '小燕出巢', 13: '兵挡将阻', 14: '过五关', 15: '一夫当关', 12 | 16: '一字长蛇', 17: '四面楚歌', 18: '比翼横空', 19: '兵临曹营', 20: '逃之夭夭', 13 | 21: '网开一面', 22: '羊肠小道', 23: '壁垒森严', 24: '横眉立目', } 14 | 15 | 16 | K_DICT = {'横刀立马1': [[[2, 1], 2, 2], [[3, 1], 1, 2], [[2, 0], 2, 1], [[2, 3], 2, 1], [[4, 0], 2, 1], [[4, 3], 2, 1], 17 | [[5, 0], 1, 1], [[5, 3], 1, 1], [[4, 1], 1, 1], [[4, 2], 1, 1]], 18 | 19 | '横刀立马2': [[[2, 1], 2, 2], [[3, 1], 1, 2], [[2, 0], 2, 1], [[2, 3], 2, 1], [[5, 0], 2, 1], [[5, 3], 2, 1], 20 | [[3, 0], 1, 1], [[3, 3], 1, 1], [[4, 1], 1, 1], [[4, 2], 1, 1]], 21 | 22 | '齐头并前': [[[2, 1], 2, 2], [[4, 1], 1, 2], [[2, 0], 2, 1], [[2, 3], 2, 1], [[5, 0], 2, 1], [[5, 3], 2, 1], 23 | [[3, 0], 1, 1], [[3, 1], 1, 1], [[3, 2], 1, 1], [[3, 3], 1, 1]], 24 | 25 | '兵分三路': [[[2, 1], 2, 2], [[3, 1], 1, 2], [[3, 0], 2, 1], [[3, 3], 2, 1], [[5, 0], 2, 1], [[5, 3], 2, 1], 26 | [[1, 0], 1, 1], [[1, 3], 1, 1], [[4, 1], 1, 1], [[4, 2], 1, 1]], 27 | 28 | '屯兵东路': [[[2, 0], 2, 2], [[3, 0], 1, 2], [[2, 2], 2, 1], [[2, 3], 2, 1], [[5, 0], 2, 1], [[5, 1], 2, 1], 29 | [[3, 2], 1, 1], [[3, 3], 1, 1], [[4, 2], 1, 1], [[4, 3], 1, 1]], 30 | 31 | '左右步兵': [[[2, 1], 2, 2], [[5, 1], 1, 2], [[2, 0], 2, 1], [[2, 3], 2, 1], [[4, 1], 2, 1], [[4, 2], 2, 1], 32 | [[4, 0], 1, 1], [[4, 3], 1, 1], [[5, 0], 1, 1], [[5, 3], 1, 1]], 33 | 34 | '前挡后阻': [[[2, 0], 2, 2], [[1, 2], 1, 2], [[5, 1], 1, 2], [[4, 0], 2, 1], [[3, 2], 2, 1], [[4, 1], 2, 1], 35 | [[4, 2], 1, 1], [[4, 3], 1, 1], [[3, 3], 1, 1], [[2, 3], 1, 1]], 36 | 37 | '插翅难飞': [[[2, 1], 2, 2], [[5, 0], 1, 2], [[5, 2], 1, 2], [[2, 0], 2, 1], [[4, 1], 2, 1], [[2, 3], 2, 1], 38 | [[3, 0], 1, 1], [[4, 0], 1, 1], [[3, 3], 1, 1], [[4, 3], 1, 1]], 39 | 40 | '近在咫尺': [[[5, 2], 2, 2], [[3, 0], 1, 2], [[4, 0], 1, 2], [[2, 1], 2, 1], [[2, 2], 2, 1], [[2, 3], 2, 1], 41 | [[1, 0], 1, 1], [[2, 0], 1, 1], [[3, 2], 1, 1], [[3, 3], 1, 1]], 42 | 43 | '层层设防': [[[2, 1], 2, 2], [[3, 2], 1, 2], [[4, 2], 1, 2], [[5, 1], 1, 2], [[4, 0], 2, 1], [[4, 1], 2, 1], 44 | [[1, 0], 1, 1], [[2, 0], 1, 1], [[1, 3], 1, 1], [[2, 3], 1, 1]], 45 | 46 | '水泄不通': [[[2, 0], 2, 2], [[1, 2], 1, 2], [[2, 2], 1, 2], [[3, 2], 1, 2], [[4, 0], 2, 1], [[4, 1], 2, 1], 47 | [[5, 0], 1, 1], [[4, 2], 1, 1], [[4, 3], 1, 1], [[5, 3], 1, 1]], 48 | 49 | '小燕出巢': [[[2, 1], 2, 2], [[4, 1], 1, 2], [[3, 0], 1, 2], [[3, 2], 1, 2], [[2, 0], 2, 1], [[2, 3], 2, 1], 50 | [[4, 0], 1, 1], [[4, 3], 1, 1], [[5, 0], 1, 1], [[5, 3], 1, 1]], 51 | 52 | '兵挡将阻': [[[2, 1], 2, 2], [[4, 1], 1, 2], [[3, 1], 1, 2], [[5, 1], 1, 2], [[3, 0], 2, 1], [[3, 3], 2, 1], 53 | [[1, 0], 1, 1], [[1, 3], 1, 1], [[4, 0], 1, 1], [[4, 3], 1, 1]], 54 | 55 | '过五关': [[[2, 1], 2, 2], [[5, 1], 1, 2], [[4, 0], 1, 2], [[4, 2], 1, 2], [[3, 0], 1, 2], [[3, 2], 1, 2], 56 | [[1, 0], 1, 1], [[1, 3], 1, 1], [[2, 0], 1, 1], [[2, 3], 1, 1]], 57 | 58 | '一夫当关': [[[2, 0], 2, 2], [[4, 1], 2, 1], [[1, 2], 1, 2], [[2, 2], 1, 2], [[3, 2], 1, 2], [[4, 2], 1, 2], 59 | [[3, 0], 1, 1], [[4, 0], 1, 1], [[5, 0], 1, 1], [[5, 1], 1, 1]], 60 | 61 | '一字长蛇': [[[2, 0], 2, 2], [[4, 2], 2, 1], [[4, 0], 1, 2], [[3, 0], 1, 2], [[1, 2], 1, 2], [[2, 2], 1, 2], 62 | [[5, 2], 1, 1], [[3, 3], 1, 1], [[4, 3], 1, 1], [[5, 3], 1, 1]], 63 | 64 | '四面楚歌': [[[3, 1], 2, 2], [[4, 1], 1, 2], [[1, 0], 1, 2], [[5, 0], 2, 1], [[3, 0], 2, 1], [[3, 3], 2, 1], 65 | [[1, 2], 1, 1], [[1, 3], 1, 1], [[4, 3], 1, 1], [[5, 3], 1, 1]], 66 | 67 | '比翼横空': [[[2, 2], 2, 2], [[1, 0], 1, 2], [[2, 0], 1, 2], [[3, 0], 1, 2], [[3, 2], 1, 2], [[5, 3], 2, 1], 68 | [[4, 0], 1, 1], [[4, 2], 1, 1], [[5, 0], 1, 1], [[5, 2], 1, 1]], 69 | 70 | '兵临曹营': [[[2, 1], 2, 2], [[3, 1], 1, 2], [[4, 0], 2, 1], [[4, 3], 2, 1], [[5, 1], 2, 1], [[5, 2], 2, 1], 71 | [[1, 0], 1, 1], [[2, 0], 1, 1], [[1, 3], 1, 1], [[2, 3], 1, 1]], 72 | 73 | '逃之夭夭': [[[2, 0], 2, 2], [[5, 1], 1, 2], [[4, 0], 1, 2], [[4, 2], 1, 2], [[1, 2], 1, 2], [[2, 2], 1, 2], 74 | [[3, 0], 1, 1], [[3, 1], 1, 1], [[3, 2], 1, 1], [[3, 3], 1, 1]], 75 | 76 | '网开一面': [[[2, 2], 2, 2], [[5, 3], 2, 1], [[2, 0], 1, 2], [[3, 0], 1, 2], [[4, 0], 1, 2], [[3, 2], 1, 2], 77 | [[5, 0], 1, 1], [[5, 1], 1, 1], [[5, 2], 1, 1], [[4, 2], 1, 1]], 78 | 79 | '羊肠小道': [[[3, 1], 2, 2], [[5, 3], 2, 1], [[5, 0], 2, 1], [[5, 1], 2, 1], [[1, 0], 1, 2], [[1, 2], 1, 2], 80 | [[2, 0], 1, 1], [[2, 3], 1, 1], [[3, 0], 1, 1], [[3, 3], 1, 1]], 81 | 82 | '壁垒森严': [[[3, 1], 2, 2], [[1, 1], 1, 2], [[5, 0], 2, 1], [[5, 1], 2, 1], [[5, 2], 2, 1], [[5, 3], 2, 1], 83 | [[2, 0], 1, 1], [[2, 3], 1, 1], [[3, 0], 1, 1], [[3, 3], 1, 1]], 84 | 85 | '横眉立目': [[[2, 1], 2, 2], [[3, 2], 1, 2], [[5, 1], 2, 1], [[5, 0], 2, 1], [[2, 3], 2, 1], [[2, 0], 2, 1], 86 | [[3, 0], 1, 1], [[3, 1], 1, 1], [[4, 2], 1, 1], [[4, 3], 1, 1]]} 87 | -------------------------------------------------------------------------------- /Klotski/readme.md: -------------------------------------------------------------------------------- 1 | ### Klotski华容道 2 | 3 | #### 一、程序文件: 4 | 5 | * **24局题目配置程序:[k_problerms.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/k_problerms.py)** 6 | 7 | * **解决方案程序:[klotski_bfs.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/klotski_bfs.py)** 8 | 9 | 10 | #### 二、24局解决方案 11 | 12 | * **具体的移动方案:见名称为“相应局数.txt”的文件** 13 | 14 | 15 | * **结果图示:** 16 | 17 | 18 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/1_k.gif) 19 | 20 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/2_k.gif) 21 | 22 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/3_k.gif) 23 | 24 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/4_k.gif) 25 | 26 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/5_k.gif) 27 | 28 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/6_k.gif) 29 | 30 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/7_k.gif) 31 | 32 | 33 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/8_k.gif) 34 | 35 | 36 | 37 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/9_k.gif) 38 | 39 | 40 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/10_k.gif) 41 | 42 | 43 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/11_k.gif) 44 | 45 | 46 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/12_k.gif) 47 | 48 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/13_k.gif) 49 | 50 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/14_k.gif) 51 | 52 | 53 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/15_k.gif) 54 | 55 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/16_k.gif) 56 | 57 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/17_k.gif) 58 | 59 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/18_k.gif) 60 | 61 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/19_k.gif) 62 | 63 | 64 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/20_k.gif) 65 | 66 | 67 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/21_k.gif) 68 | 69 | 70 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/22_k.gif) 71 | 72 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/23_k.gif) 73 | 74 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Klotski/24_k.gif) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /Lottery/DLT_DATA.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 首先更新数据 5 | import DLT_SPYDER as dltdata 6 | 7 | # 对存储在文件中的DLT数据进行处理 8 | import pandas as pd 9 | 10 | # 定义处理数据的类 11 | class CP: 12 | def __init__(self): 13 | # 基础信息设定 14 | self.qian = list(range(1, 36)) 15 | self.qc = 5 16 | self.hou = list(range(1, 13)) 17 | self.hc = 2 18 | 19 | # 数据文件路径 20 | self.filepath = r'C:\Users\GWT9\Desktop' 21 | 22 | # 没有经过处理的数据 23 | self.dlt = self.ReadFile('dlt.csv', '前区', '后区') 24 | 25 | # 经过日期分解的数据 26 | self.dlt_dd = self.ChangeDate(self.dlt) 27 | 28 | # 添加顺序标识的数据 29 | self.oodata = self.AddOrder(self.dlt_dd) 30 | 31 | 32 | # 读取文件的函数 33 | def ReadFile(self, filename, c1, c2): 34 | data = pd.read_csv(r'%s\%s' % (self.filepath, filename)) 35 | # 此外需要将存储号码的字符串形式转为列表形式 36 | data[c1] = [list(map(int, ii[1:-1].split(', '))) for ii in data[c1]] 37 | data[c2] = [list(map(int, ii[1:-1].split(', '))) for ii in data[c2]] 38 | return data 39 | 40 | # 将日期变为年份,月份, 日 41 | def ChangeDate(self, data): 42 | newdf = data['日期'].str.split('-', expand=True) 43 | # 更新名字 44 | newdf = newdf.rename(columns={0: '年份', 1: '月份', 2: '日'}) 45 | # 和原来的合并 46 | data = data.join(newdf) 47 | return data 48 | 49 | # 按照日期的先后顺序,添加顺序标识.日期越近,序号越大 50 | def AddOrder(self, data): 51 | data.sort_values("日期", inplace=True) 52 | data['序号'] = list(range(1, len(data) + 1)) 53 | return data 54 | 55 | # 首先爬取最新数据 56 | print('爬取DLT最新数据') 57 | dltdata.dc_order() 58 | # 主函数 59 | dlt_data = CP() 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Lottery/DLT_SPYDER.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 获取08069至18130期的大乐透开球顺序的信息,08069是第一期有开奖顺序的 5 | import requests # 这个网页编码方式比较特殊,需打开网页需要用到headers 6 | from bs4 import BeautifulSoup as bs # 格式化网页源码 7 | import pandas as pd 8 | import datetime 9 | 10 | 11 | headers = { 12 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0', 13 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 14 | 'Accept-Encoding': 'gizp,defale', 15 | 'Accept-Language': 'zh-CN,zh;q=0.9' 16 | } 17 | 18 | xingqi = {'0': '日', '1': '一', '2': '二', '3': '三', '4': '四', '5': '五', '6': '六'} 19 | 20 | # 函数 21 | def dc_order(start='08069', end='99999', head=headers, xqdict=xingqi): # end设置较大数值,可保证获取最新的数据 22 | 23 | # 需要存储的数据 24 | qihao = [] 25 | riqi = [] 26 | zhouji = [] 27 | qianqu = [] 28 | houqu = [] 29 | 30 | response = requests.get('https://datachart.500.com/dlt/history/newinc/outball.php?start=%s&end=%s' %(start, end), headers=head).text 31 | 32 | bsoh = bs(response, "lxml") 33 | 34 | fu = bsoh.find_all('tr', class_='t_tr1') 35 | 36 | for jj in fu: 37 | ii = jj.get_text().split()[0] # 数据比较规整:按位选取数据 38 | 39 | qihao.append('20%s' % str(ii[:5])) 40 | riqi.append(ii[5:15]) 41 | # 根据日期添加星期几 42 | fu = datetime.datetime.strptime(ii[5:15], '%Y-%m-%d') 43 | 44 | anyday = fu.strftime("%w") 45 | 46 | zhouji.append('周%s' % xqdict[anyday]) 47 | 48 | # 需要转变为列表的形式 49 | exlist = list(ii[15:25]) 50 | 51 | numlist = [int(exlist[i] + exlist[i + 1]) for i in range(0, len(exlist), 2)] 52 | 53 | qianqu.append(numlist) 54 | 55 | 56 | exli = list(ii[-4:]) 57 | 58 | numl = [int(exli[i] + exli[i + 1]) for i in range(0, len(exli), 2)] 59 | 60 | houqu.append(numl) 61 | 62 | data = pd.DataFrame() 63 | 64 | data['期号'] = qihao 65 | data['日期'] = riqi 66 | data['星期'] = zhouji 67 | data['前区'] = qianqu 68 | data['后区'] = houqu 69 | 70 | 71 | 72 | data.to_csv(r'C:\Users\GWT9\Desktop\dlt.csv', index=False, encoding= u'utf-8') 73 | 74 | return print('爬取的DLT数据保存完毕,最新期号%s' % qihao[0]) 75 | 76 | 77 | # 主函数 78 | if __name__ == '__main__': 79 | dc_order() 80 | 81 | -------------------------------------------------------------------------------- /Lottery/MODEL.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 模型:根据历史数据得到前后同样位置号码之间的转移概率 5 | # 选择最近几期出现的号码对应的概率最大的前几个号码,作为预测号码 6 | # 当前以及之前的所有数据作为计算转移概率的历史数据。 7 | from scipy.special import comb 8 | 9 | # 模型的类 10 | class MODEL(): 11 | def __init__(self, data, houxuan, houxuangeshu, name, qishu, sign): 12 | ''' 13 | data:dataframe格式 14 | houxuan:号码序列 15 | houxuangeshu:号码个数 16 | name:要研究的字段 17 | qishu:计算前几期号码对应的最大转移概率 18 | sign:从sign期到最后一期数据作为统计数据,超过最大期数,则为预测 19 | ''' 20 | 21 | self.data = data 22 | self.houxuan = houxuan 23 | self.houxuangehsu = houxuangeshu 24 | 25 | # 计算前几期号码对应的最大转移概率 26 | self.qishu = qishu 27 | 28 | # 从sign期到最后一期数据作为统计数据, 超过最大期数,则为预测 29 | self.sign = sign 30 | 31 | 32 | # 要研究的字段名称 33 | self.name = name 34 | 35 | # 存储转移次数的字典 36 | self.transdict = self.InitGai() 37 | 38 | # 存储出现次数的字典 39 | self.chuxiandict = {h: 0 for h in self.houxuan} 40 | 41 | # 存储转移概率的字典 42 | self.zhuanyidict = self.gailv() 43 | 44 | # 计算转移概率的字典 45 | def gailv(self): 46 | exdict = {} 47 | for jj in self.transdict: 48 | exdict[jj] = {} 49 | for hh in self.transdict[jj]: 50 | if self.chuxiandict[jj] != 0: 51 | exdict[jj][hh] = self.transdict[jj][hh] / self.chuxiandict[jj] 52 | else: 53 | exdict[jj][hh] = 0 54 | return exdict 55 | 56 | # 定义概率字典格式的函数 57 | def InitGai(self): 58 | ecdict = {} 59 | for jj in self.houxuan: 60 | ecdict[jj] = {} 61 | for hh in self.houxuan: 62 | ecdict[jj][hh] = 0 63 | return ecdict 64 | 65 | # 自定义可以回溯的期数,不止是前一期,将前几期号码合并的函数 66 | def Hebing(self, exdalsit): 67 | gu = [] 68 | for j in exdalsit: 69 | gu += j 70 | return list(set(gu)) 71 | 72 | # 根据转移概率字典,返回前几期号码对应的号码按照概率从大到小的号码序列 73 | def GetOrder(self, elist): 74 | exlist = self.Hebing(elist) 75 | exdict = {i: 0 for i in self.houxuan} 76 | for jj in exlist: 77 | for hh in self.zhuanyidict[jj]: 78 | exdict[hh] += self.zhuanyidict[jj][hh] 79 | # 按照从大到小输出键 80 | orderdict = sorted(exdict.items(), key=lambda du: du[1], reverse=True) 81 | 82 | # 号码序列 83 | haoma = [j[0] for j in orderdict] 84 | 85 | return haoma 86 | 87 | # 定义计算出现次数的函数字典 88 | def TongJICiShu(self, balldata): # 输入号码序列 89 | for jj in balldata: 90 | for kk in jj: 91 | self.chuxiandict[kk] += 1 92 | return self.chuxiandict 93 | 94 | # 统计前后对应次数的关系 95 | def GuanLian(self, balldata, jiande=1): # 输入号码序列 96 | qiandata = balldata[: -jiande] 97 | houdata = balldata[jiande:] 98 | for qq, hh in zip(qiandata, houdata): 99 | for j, k in zip(qq, hh): 100 | self.transdict[j][k] += 1 101 | return self.transdict 102 | 103 | 104 | # 根据序号确定从何时开始作为统计数据,要预测的数据序列,以及预测要用到的数据系列 105 | def Hietory(self): #sign不小于1 106 | if self.sign >= max(list(self.data['序号'].values)): 107 | yucedata = self.data[self.data['序号'] == max(list(self.data['序号'].values))] 108 | yongdao_yucedata = self.data[self.data['序号'] > max(list(self.data['序号'].values)) - self.qishu] 109 | return self.data, yucedata, yongdao_yucedata 110 | else: 111 | newdata = self.data[self.data['序号'] <= self.sign] # 因为当期也算做历史数据 112 | yucedata = self.data[self.data['序号'] >= self.sign] 113 | yongdao_yucedata = self.data[self.data['序号'] > self.sign - self.qishu] 114 | return newdata, yucedata, yongdao_yucedata 115 | 116 | 117 | # 开始进行获取转移次数、出现次数 118 | def HuoDe(self): 119 | # 历史数据、预测数据 120 | history_data, yuce_data, yongdao_yuce_data = self.Hietory() 121 | # 出现字典 122 | self.chuxiandict = self.TongJICiShu(history_data[self.name].values) 123 | # 转移字典 124 | self.transdict = self.GuanLian(history_data[self.name].values) 125 | # 概率字典 126 | self.zhuanyidict = self.gailv() 127 | 128 | 129 | # 返回编号为键,原始序列和号码序列为值的字典 130 | xuhaodict = {} 131 | 132 | # 判断是否为预测 133 | exlist = yuce_data[self.name].values 134 | 135 | bianhaolist = yuce_data['期号'].values 136 | 137 | yongdao_yu = yongdao_yuce_data[self.name].values 138 | 139 | if len(exlist) == 1: 140 | # 则返回预测序列 141 | yucede = self.GetOrder(yongdao_yu) 142 | bianhao = bianhaolist[0] 143 | xuhaodict[bianhao + 1] = ['%s期还没出现' % (bianhao + 1), yucede] 144 | return xuhaodict 145 | 146 | else: 147 | # 预测用到的数据系列的选取 148 | biaoshi = 0 149 | for qian, hou, bian in zip(exlist[: -1], exlist[1:], bianhaolist[1:]): 150 | # 出现字典 151 | self.chuxiandict = self.TongJICiShu([qian]) 152 | # 转移字典 153 | self.transdict = self.GuanLian([hou, qian]).copy() 154 | # 概率字典 155 | self.zhuanyidict = self.gailv() 156 | 157 | # 预测的 158 | yucede = self.GetOrder(yongdao_yu[biaoshi: biaoshi + self.qishu]) 159 | 160 | xuhaodict[bian] = [hou, yucede] 161 | 162 | biaoshi += 1 163 | 164 | return xuhaodict 165 | 166 | # 定义结果比对的函数 167 | def Resu_Bdui(self, exlist, count): 168 | # 判断是否为预测 169 | if '期' in exlist[0]: 170 | return '双色球%s期号码(%s)优选方案:%s' % (exlist[0][:7], self.name, exlist[1][: count]) 171 | else: 172 | hu = {} 173 | for jj in range(1, count + 1): 174 | hu[jj] = {} 175 | jiaoji = len(list(set(exlist[0]).intersection(set(exlist[1][: jj])))) 176 | hu[jj][jiaoji] = 1 177 | return hu 178 | 179 | 180 | # 根据字典统计命中球数的概率 181 | def MingZhong(self, exdict, count): 182 | # 为每一种结果都获得命中球数的概率 183 | qiu = {mm: {fu: 0 for fu in range(0, self.houxuangehsu + 1)} for mm in range(1, count + 1)} 184 | # 开始计算 185 | for hh in exdict: 186 | ddcit = self.Resu_Bdui(exdict[hh], count) 187 | if "期" not in ddcit: 188 | for ghu in ddcit: 189 | qiu[ghu][list(ddcit[ghu].keys())[0]] += 1 190 | else: 191 | return ddcit 192 | # 返回概率 193 | gaidct = {} 194 | for gg in qiu: 195 | sunhe = sum(list(qiu[gg].values())) 196 | gaidct[gg] = {ji: qiu[gg][ji] / sunhe for ji in qiu[gg]} 197 | 198 | # 每种情况按着命中球的个数形成列表 199 | lidi = {} 200 | for ut in gaidct: 201 | lidi[ut] = [] 202 | for jie in range(self.houxuangehsu + 1): 203 | lidi[ut].append(gaidct[ut][jie]) 204 | return lidi 205 | 206 | # 随机选择的理论概率 207 | def Random_Method(self, n): 208 | redict = {} 209 | fu = 0 210 | for i in range(self.houxuangehsu + 1): 211 | if n >= i: 212 | tu = comb((len(self.houxuan) - self.houxuangehsu), 213 | (n - i)) * comb(self.houxuangehsu, i) / comb(len(self.houxuan), n) 214 | fu += tu 215 | redict[i] = tu 216 | # 按命中球的个数返回值 217 | redu = [] 218 | for j in range(self.houxuangehsu + 1): 219 | if j <= n: 220 | if j not in redict: 221 | redu.append(0) 222 | else: 223 | redu.append(redict[j]) 224 | return redu -------------------------------------------------------------------------------- /Lottery/Red_Pro_model1.md: -------------------------------------------------------------------------------- 1 | # 双色球、大乐透号码优选方案 2 | 3 | ### 程序文件说明 4 | 5 | 6 | #### 一、数据 7 | 8 | + 双色球 9 | 10 | + 爬虫程序:[SSQ_SPYDER.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/SSQ_SPYDER.py) 11 | 12 | + 数据处理:[SSQ_DATA.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/SSQ_DATA.py) 13 | 14 | + 大乐透: 15 | 16 | + 爬虫程序:[DLT_SPYDER.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/DLT_SPYDER.py) 17 | 18 | + 数据处理:[DLT_DATA.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/DLT_DATA.py) 19 | 20 | #### 二、模型程序 21 | 22 | + 模型:[MODEL.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/MODEL.py) 23 | 24 | #### 三、真实数据概率对比程序 25 | 26 | + 数据测试:[TEST.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/TEST.py) 27 | 28 | #### 四、下一期预测程序 29 | 30 | + 预测:[SSQ_DLT_PREDICT.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Lottery/SSQ_DLT_PREDICT.py) 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Lottery/SSQ_DATA.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 首先更新数据 5 | import SSQ_SPYDER as ssqdata 6 | 7 | # 对存储在文件中的SSQ数据进行处理 8 | import pandas as pd 9 | 10 | # 定义处理数据的类 11 | class CP: 12 | def __init__(self): 13 | # 基础信息设定 14 | self.red = list(range(1, 34)) 15 | self.rc = 6 16 | self.blue = list(range(1, 17)) 17 | self.bc = 1 18 | 19 | # 数据文件路径 20 | self.filepath = r'C:\Users\GWT9\Desktop' 21 | 22 | # 没有经过处理的数据 23 | self.ssq = self.ReadFile('ssq.csv', '红球', '蓝球') 24 | 25 | # 经过日期分解的数据 26 | self.ssq_ss = self.ChangeDate(self.ssq) 27 | 28 | # 添加顺序标识的数据 29 | self.oodata = self.AddOrder(self.ssq_ss) 30 | 31 | 32 | # 读取文件的函数 33 | def ReadFile(self, filename, c1, c2): 34 | data = pd.read_csv(r'%s\%s' % (self.filepath, filename)) 35 | # 此外需要将存储号码的字符串形式转为列表形式 36 | data[c1] = [list(map(int, ii[1:-1].split(', '))) for ii in data[c1]] 37 | data[c2] = [list(map(int, ii[1:-1].split(', '))) for ii in data[c2]] 38 | return data 39 | 40 | # 将日期变为年份,月份, 日 41 | def ChangeDate(self, data): 42 | newdf = data['日期'].str.split('-', expand=True) 43 | # 更新名字 44 | newdf = newdf.rename(columns={0: '年份', 1: '月份', 2: '日'}) 45 | # 和原来的合并 46 | data = data.join(newdf) 47 | return data 48 | 49 | # 按照日期的先后顺序,添加顺序标识.日期越近,序号越大 50 | def AddOrder(self, data): 51 | data.sort_values("日期", inplace=True) 52 | data['序号'] = list(range(1, len(data) + 1)) 53 | return data 54 | 55 | 56 | # 首先爬取最新数据 57 | print('爬取SSQ最新数据') 58 | ssqdata.dc_order() 59 | 60 | # 主函数 61 | ssq_data = CP() 62 | 63 | -------------------------------------------------------------------------------- /Lottery/SSQ_DLT_PREDICT.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 预测下一期数据 5 | import MODEL as MM 6 | import SSQ_DATA as data_ssq 7 | import DLT_DATA as data_dlt 8 | 9 | # 定义预测SSQ的函数 10 | 11 | def Predict_SSQ(outcount=[6, 1], xuhao=999999): 12 | ''' 13 | :param outcount: 红球、蓝球的输出个数 14 | :param xuhao: 设置一个大数,则为预测下一期。 15 | :return: 返回预测的号码 16 | ''' 17 | # 红球 18 | model_red = MM.MODEL(data_ssq.ssq_data.oodata, data_ssq.ssq_data.red, data_ssq.ssq_data.rc, '红球', 1, xuhao) 19 | fu_red = model_red.HuoDe() 20 | # 确定输出候选号码的个数 21 | maxcount_red = outcount[0] 22 | # 输出 23 | gail_red = model_red.MingZhong(fu_red, maxcount_red) 24 | print(gail_red) 25 | # 蓝球 26 | model_blue = MM.MODEL(data_ssq.ssq_data.oodata, data_ssq.ssq_data.blue, data_ssq.ssq_data.bc, '蓝球', 1, xuhao) 27 | fu = model_blue.HuoDe() 28 | # 确定输出候选号码的个数 29 | maxcount_blue = outcount[1] 30 | # 输出 31 | gail_blue = model_blue.MingZhong(fu, maxcount_blue) 32 | print(gail_blue) 33 | return print('SSQ预测完毕') 34 | 35 | 36 | # 定义预测DLT的函数 37 | def Predict_DLT(outcount=[5, 2], xuhao=999999): 38 | ''' 39 | :param outcount: 前区、后区的输出个数 40 | :param xuhao: 设置一个大数,则为预测下一期。 41 | :return: 返回预测的号码 42 | ''' 43 | # 前区 44 | model_qian = MM.MODEL(data_dlt.dlt_data.oodata, data_dlt.dlt_data.qian, data_dlt.dlt_data.qc, '前区', 1, xuhao) 45 | fu_qian = model_qian.HuoDe() 46 | # 确定输出候选号码的个数 47 | maxcount_qian = outcount[0] 48 | # 输出 49 | gail_qian = model_qian.MingZhong(fu_qian, maxcount_qian) 50 | print(gail_qian) 51 | # 后区 52 | model_hou = MM.MODEL(data_dlt.dlt_data.oodata, data_dlt.dlt_data.hou, data_dlt.dlt_data.hc, '后区', 2, xuhao) 53 | fu_hou = model_hou.HuoDe() 54 | # 确定输出候选号码的个数 55 | maxcount_hou = outcount[1] 56 | # 输出 57 | gail_hou = model_hou.MingZhong(fu_hou, maxcount_hou) 58 | print(gail_hou) 59 | return print('DLT预测完毕') 60 | 61 | # 预测主函数 62 | 63 | if __name__ == "__main__": 64 | 65 | Predict_SSQ() 66 | Predict_DLT() 67 | -------------------------------------------------------------------------------- /Lottery/SSQ_SPYDER.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 双色球第一期为03001 5 | import requests # 这个网页编码方式比较特殊,需打开网页需要用到headers 6 | from bs4 import BeautifulSoup as bs # 格式化网页源码 7 | import pandas as pd 8 | import datetime 9 | 10 | 11 | headers = { 12 | 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0', 13 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 14 | 'Accept-Encoding': 'gizp,defale', 15 | 'Accept-Language': 'zh-CN,zh;q=0.9' 16 | } 17 | 18 | xingqi = {'0': '日', '1': '一', '2': '二', '3': '三', '4': '四', '5': '五', '6': '六'} 19 | 20 | # 函数 21 | def dc_order(start='03001', end='99001', head=headers, xqdict=xingqi): #end值设置较大,保证可以获取所有的数据 22 | 23 | # 需要存储的数据 24 | qihao = [] # 存储期号 25 | riqi = [] # 存储日期 26 | zhouji = [] # 存储周几 27 | hongqiu = [] # 存储红球顺序 28 | lanqiu = [] # 存储蓝球 29 | 30 | response = requests.get('https://datachart.500.com/ssq/history/newinc/outball.php?start=%s&end=%s' % (start, end), headers=head).text 31 | 32 | bsoh = bs(response, "lxml") 33 | 34 | fu = bsoh.find_all('tr', class_='t_tr1') 35 | 36 | for jj in fu: 37 | ii = jj.get_text().split()[0] # 数据比较规整:按位选取数据 38 | qihao.append('20%s' % str(ii[:5])) 39 | riqi.append(ii[5:15]) 40 | 41 | # 根据日期添加星期几 42 | fu = datetime.datetime.strptime(ii[5:15], '%Y-%m-%d') 43 | 44 | anyday = fu.strftime("%w") 45 | 46 | # 数据中存在日期出现错误的情况,在这里需要更正。 47 | if anyday not in ['0', '2', '4']: 48 | # 需要将日期往前算一天 49 | newday = fu + datetime.timedelta(days=-1) 50 | # 更改日期 51 | riqi[-1] = newday 52 | anyday = newday.strftime('%w') 53 | 54 | zhouji.append('周%s' % xqdict[anyday]) 55 | 56 | # 需要转变为列表的形式 57 | exlist = list(ii[15:27]) 58 | 59 | numlist = [int(exlist[i] + exlist[i + 1]) for i in range(0, len(exlist), 2)] 60 | 61 | hongqiu.append(numlist) 62 | lanqiu.append([int(ii[-2:])]) 63 | 64 | 65 | data = pd.DataFrame() 66 | 67 | data['期号'] = qihao 68 | data['日期'] = riqi 69 | data['星期'] = zhouji 70 | data['红球'] = hongqiu 71 | data['蓝球'] = lanqiu 72 | 73 | data.to_csv(r'C:\Users\GWT9\Desktop\ssq.csv', index=False, encoding=u'utf-8') 74 | 75 | return print('爬取的SSQ数据保存完毕,最新期号%s' % qihao[0]) 76 | 77 | # 主函数 78 | if __name__ == '__main__': 79 | dc_order() 80 | 81 | 82 | -------------------------------------------------------------------------------- /Lottery/TEST.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 真实数据的结果 5 | import MODEL as moxing 6 | import SSQ_DATA as data_ssq # 双色球数据 7 | import DLT_DATA as data_dlt # 大乐透数据 8 | # 绘制概率对比 9 | 10 | from pylab import mpl 11 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 显示中文 12 | mpl.rcParams['axes.unicode_minus'] = False # 显示负号 13 | import matplotlib.pyplot as plt 14 | 15 | # 主函数, 输出概率和随机选择概率的对比 16 | 17 | if __name__ == "__main__": 18 | print('计算阶段') 19 | # 验证红球 20 | model = moxing.MODEL(data_ssq.ssq_data.oodata, data_ssq.ssq_data.red, data_ssq.ssq_data.rc, '红球', 1, 1239) 21 | # # 验证蓝球 22 | # model = moxing.MODEL(data_ssq.ssq_data.oodata, data_ssq.ssq_data.blue, data_ssq.ssq_data.bc, '蓝球', 9, 1500) 23 | 24 | # 验证前区 25 | # model = moxing.MODEL(data_dlt.dlt_data.oodata, data_dlt.dlt_data.qian, data_dlt.dlt_data.qc, '前区', 1, 1000) 26 | # # 验证后区 27 | # model = moxing.MODEL(data_dlt.dlt_data.oodata, data_dlt.dlt_data.hou, data_dlt.dlt_data.hc, '后区', 1, 1000) 28 | 29 | fu = model.HuoDe() 30 | # 选择选取不同球数的结果对比, 31 | maxcount = 8 32 | # 概率 33 | gail = model.MingZhong(fu, maxcount) 34 | 35 | if '期' in gail: # 预测情况 36 | print(gail) 37 | else: 38 | # 以1-7个球的结果为例 39 | for ss in range(1, maxcount + 1): 40 | # 转移 41 | yizhuan = gail[ss][: ss + 1] 42 | # 随机理论 43 | jisui = model.Random_Method(ss) 44 | 45 | plt.figure() 46 | 47 | row_labels = ['本文方法', '理论概率'] 48 | col_labels = ['%d球' % f for f in list(range(min(ss + 1, model.houxuangehsu + 1)))] 49 | table_vals = [['%.5f' % f for f in yizhuan], ['%.5f' % f for f in jisui]] 50 | row_colors = ['teal', 'plum'] 51 | my_table = plt.table(cellText=table_vals, 52 | cellColours=[['teal'] * len(col_labels), ['plum'] * len(col_labels)], \ 53 | rowLoc='center', colLoc='center', 54 | rowLabels=row_labels, colLabels=col_labels, rowColours=row_colors, 55 | loc='bottom') 56 | 57 | plt.plot(list(range(len(yizhuan))), yizhuan, '--', marker='o', lw=2.5, c='teal') 58 | 59 | plt.plot(list(range(len(jisui))), jisui, '-.', marker='p', lw=2.5, c='plum') 60 | plt.legend(['本文方法(真实数据:统计%d条)' % (max(list(model.data['序号'].values)) - model.qishu + 1), '理论概率']) 61 | plt.title('%s:选择%s个球的命中情况概率对比' % (model.name, ss)) 62 | plt.xlim(- 0.5, len(col_labels) - 0.5) 63 | plt.xticks([]) 64 | plt.grid() 65 | plt.savefig(r'C:\Users\GWT9\Desktop\%s_%s.jpg' % (ss, model.name)) 66 | plt.show() 67 | 68 | print('计算完毕') 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /Magic Square/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Magic Square/10.png -------------------------------------------------------------------------------- /Magic Square/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Magic Square/7.png -------------------------------------------------------------------------------- /Magic Square/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Magic Square/8.png -------------------------------------------------------------------------------- /Magic Square/Magic_Square.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 引入库 5 | import numpy as np 6 | 7 | 8 | # 奇数阶 9 | def OddMagic(jieshu): 10 | # 存储幻方结构 11 | huanfang = np.zeros((jieshu, jieshu)) 12 | # 需要填写的数字列表 13 | listnum = list(range(1, jieshu ** 2 + 1)) 14 | # 第一行中间填1 15 | i = 0 16 | j = int(jieshu / 2) 17 | # 记录填写的个数 18 | count = 0 19 | while count < jieshu ** 2: 20 | huanfang[i][j] = listnum[count] 21 | # 记录i,j 22 | cc = i 23 | dd = j 24 | # 超出了第一行,则填到最底下一行 25 | if i - 1 < 0: 26 | i = jieshu - 1 27 | else: 28 | i -= 1 29 | # 超出了最右边一列,则填到最左边一列 30 | if j + 1 == jieshu: 31 | j = 0 32 | else: 33 | j += 1 34 | # 遇到下一个格子里已经有数字的,就填到当前格子的下方 35 | if huanfang[i][j] != 0: 36 | i = cc + 1 37 | j = dd 38 | # 次序加1 39 | count += 1 40 | return huanfang 41 | 42 | 43 | # 双偶阶幻方:阶数=2*偶数 44 | def DoubleEvenMagic(jieshu): 45 | ##存储幻方结构 46 | huanfang = np.zeros((jieshu, jieshu)) 47 | # 需要填写的数字列表 48 | listnum = list(range(1, jieshu ** 2 + 1)) 49 | # 第一轮填充,从第一行第一列开始,从左到右,从上到下,从1到jieshu平方,依次填充 50 | # 每四乘四的正方形,画主副对角线。规则是只填充没对角线的,画了对角线格子不写 51 | # 记录个数 52 | count = 0 53 | for hang in range(len(huanfang)): 54 | for lie in range(len(huanfang)): 55 | if (hang % 4 in [0, 3] and lie % 4 in [1, 2]) or \ 56 | (hang % 4 in [1, 2] and lie % 4 in [0, 3]): # 判断对角线 57 | huanfang[hang][lie] = listnum[count] 58 | # 第二轮填充,从最后一行最后一列开始,从右到左,从下到上,从1到jieshu平方依次填充。 59 | # 规则是只填充画了对角线的,没画对角线的不填 60 | else: 61 | huanfang[hang][lie] = listnum[::-1][count] 62 | count += 1 63 | return huanfang 64 | 65 | 66 | # 单偶阶幻方:阶数=2*奇数 67 | def SingleEvenMagic(jieshu): 68 | # 幻方结构 69 | huanfang = np.zeros((jieshu, jieshu)) 70 | # 子幻方阶数 71 | son = int(jieshu / 2) 72 | # A象限幻方 73 | SAhf = OddMagic(son) 74 | huanfang[:, 0:son][0:son] = SAhf 75 | # 依次填充DBC象限 76 | huanfang[:, son:][son:] = huanfang[:, 0:son][0:son] + son ** 2 77 | huanfang[:, son:][0:son] = huanfang[:, son:][son:] + son ** 2 78 | huanfang[:, 0:son][son:] = huanfang[:, son:][0:son] + son ** 2 79 | # 计算K值 80 | k = int((jieshu - 2) / 4) 81 | # AC象限互换 82 | # 从A象限的中间行中间列开始为第一格,往右标出K格;标出A象限其他行的左边K列 83 | # 先换AC象限所有行的左边K列 84 | middle = huanfang[:, 0:k][0:son].copy() 85 | huanfang[:, 0:k][0:son] = huanfang[:, 0:k][son:] 86 | huanfang[:, 0:k][son:] = middle 87 | # 再换中间行的前2K列 88 | middle = huanfang[:, 0:2 * k][int(son / 2):(int(son / 2) + 1)].copy() 89 | huanfang[:, 0:2 * k][int(son / 2):(int(son / 2) + 1)] = huanfang[:, 0:2 * k][ 90 | int(son / 2) + son:(int(son / 2) + 1 + son)] 91 | huanfang[:, 0:2 * k][int(son / 2) + son:(int(son / 2) + 1 + son)] = middle 92 | # BD象限互换 93 | if k - 1 != 0: 94 | # 从B象限的中间列所有格子开始,向左标出K-1列,与D象限对换 95 | middle = huanfang[:, son:son + k - 1][0:son].copy() 96 | huanfang[:, son:son + k - 1][0:son] = huanfang[:, son:son + k - 1][son:] 97 | huanfang[:, son:son + k - 1][son:] = middle 98 | return huanfang 99 | 100 | 101 | # 最终构建幻方的函数 102 | def Magic(jieshu): 103 | if jieshu < 3: 104 | return '阶数不应小于3' 105 | elif jieshu % 2 == 1: 106 | huanfang = OddMagic(jieshu) 107 | elif jieshu % 4 != 0: 108 | huanfang = SingleEvenMagic(jieshu) 109 | else: 110 | huanfang = DoubleEvenMagic(jieshu) 111 | return huanfang 112 | 113 | 114 | # 验证幻方的函数 115 | def Test(jieshu): 116 | cc = Magic(jieshu) 117 | 118 | sumlist = list(cc.sum(axis=1)) + list(cc.sum(axis=0)) + [cc.trace()] # 所有行、列以及主对角线数字和 119 | vicediag = 0 120 | for iv in range(jieshu): 121 | vicediag += cc[iv][jieshu - iv - 1] 122 | sumlist += [vicediag] # 加上副对角线数字和 123 | if len(set(sumlist)) == 1: # 判断和相等 124 | print(cc) 125 | return '结果正确' 126 | else: 127 | print('%s阶程序有bug' % jieshu) 128 | return False 129 | 130 | 131 | print(Test(7)) -------------------------------------------------------------------------------- /Magic Square/readme.md: -------------------------------------------------------------------------------- 1 | # Magic Square 2 | 3 | * **程序文件:**[Magic_Square.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Magic%20Square/Magic_Square.py) 4 | 5 | 6 | * **结果:** 7 | 8 | * **阶数=7** 9 | 10 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Magic%20Square/7.png) 11 | 12 | 13 | * **阶数=8** 14 | 15 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Magic%20Square/8.png) 16 | 17 | 18 | * **阶数=10** 19 | 20 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Magic%20Square/10.png) 21 | -------------------------------------------------------------------------------- /N Queens/8_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_1.png -------------------------------------------------------------------------------- /N Queens/8_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_10.png -------------------------------------------------------------------------------- /N Queens/8_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_11.png -------------------------------------------------------------------------------- /N Queens/8_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_12.png -------------------------------------------------------------------------------- /N Queens/8_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_2.png -------------------------------------------------------------------------------- /N Queens/8_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_3.png -------------------------------------------------------------------------------- /N Queens/8_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_4.png -------------------------------------------------------------------------------- /N Queens/8_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_5.png -------------------------------------------------------------------------------- /N Queens/8_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_6.png -------------------------------------------------------------------------------- /N Queens/8_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_7.png -------------------------------------------------------------------------------- /N Queens/8_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_8.png -------------------------------------------------------------------------------- /N Queens/8_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/8_9.png -------------------------------------------------------------------------------- /N Queens/N_Queens.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 注意更改路径 5 | import os 6 | os.chdir(r'C:\Users\GWT9\Desktop\queen') # 设置当前工作目录 7 | 8 | import imageio # 引入合成gif的库 9 | 10 | queencount = 8 # 可随意设置,如果设置为大于12的数,程序运行较慢。 11 | # 根据已经选择的坐标点,输出与其冲突的在其斜线方向上的坐标集合 12 | # 为了简化运算,定义一些设置 13 | su = [[i, j] for i in ['+', '-'] for j in ['+', '-']] 14 | sdict = {'+': ' -1'} 15 | 16 | 17 | # 返回冲突的斜线坐标集合 18 | def simple(zuibiao, sign, sidict=sdict): 19 | save = [] 20 | hang = zuibiao[0] 21 | lie = zuibiao[1] 22 | while eval('hang%s' % sidict[sign[0]]) and eval('lie%s' % sidict[sign[1]]): 23 | save.append([hang, lie]) 24 | hang = eval('hang %s1' % sign[0]) 25 | lie = eval('lie%s1' % sign[1]) 26 | return save 27 | 28 | 29 | # 返回与其冲突的全部坐标 斜线方向+同行同列方向 30 | def allno(func, zuibiao, listsi=su, count=queencount): 31 | alist = [] 32 | # 斜线方向 33 | for hs in listsi: 34 | alist += func(zuibiao, hs) # 斜线方向上的冲突坐标集合 35 | # 同行同列方向上的冲突坐标集合 36 | for same in range(0, count): 37 | alist.append([same, zuibiao[1]]) 38 | alist.append([zuibiao[0], same]) 39 | return alist 40 | 41 | 42 | # 根据已经选择的坐标,以及冲突的坐标集合,输出摆放第n个皇后的可能的坐标集合 43 | def xikk(newlist, numb=queencount): 44 | fu = [] 45 | for tu in newlist: 46 | fu += allno(simple, tu) # 所有冲突的坐标集合 47 | slast = [] 48 | if len(newlist) >= numb: 49 | return slast 50 | else: 51 | for jgi in [[len(newlist), j] for j in range(0, numb)]: # 必须在第n行选取第n个坐标 52 | if jgi not in fu: 53 | slast.append(jgi) 54 | return slast # 返回可能选择的坐标集合 55 | 56 | 57 | startdict = {1: 0} # 表示的是: 下一次添加的是第一行的可行的坐标集合中的第0个元素 58 | 59 | # 尾递归优化 60 | import sys 61 | class TailRecurseException(BaseException): 62 | def __init__(self, args, kwargs): 63 | self.args = args 64 | self.kwargs = kwargs 65 | def tail_call_optimized(g): 66 | def func(*args, **kwargs): 67 | f = sys._getframe() 68 | if f.f_back and f.f_back.f_back and f.f_back.f_back.f_code == f.f_code: 69 | raise TailRecurseException(args, kwargs) 70 | else: 71 | while 1: 72 | try: 73 | return g(*args, **kwargs) 74 | except TailRecurseException as e: 75 | args = e.args 76 | kwargs = e.kwargs 77 | 78 | func.__doc__ = g.__doc__ 79 | return func 80 | 81 | 82 | # 回溯算法的函数 83 | @tail_call_optimized 84 | def huifu(select, exdict, save, nn=queencount): 85 | # select:已经选择的摆放皇后的坐标集合列表, exdict:存储第几个皇后的可行列表的第几个元素的字典, save:存储皇后问题的解 86 | # 判断当前的状况是不是皇后问题的解 87 | if len(select) == nn: # 如果是,则添加到save中 88 | save.append(select) 89 | # 求出当前对应select的可行性的坐标集合 90 | fulist = xikk(select) 91 | if len(fulist) != 0: # 如果可行性坐标集合不为空 92 | exdict[len(select) + 1] = 0 # 实时记录下一次选择应该是选择可行性坐标集合中的第几个元素 93 | return huifu(select + [fulist[exdict[len(select)]]], exdict, save) # 开始递归 94 | else: 95 | # 如果可行性坐标集合为空 96 | # 开始从后往前计算,找到哪一个可行性坐标集合还有选择的余地 97 | # 如果都已经没有选择了,则遍历完成 98 | for jsa in list(range(1, len(select)))[::-1]: # 从后往前计算 99 | fuud = xikk(select[0: jsa]) 100 | if exdict[len(select[0: jsa])] < len(fuud) - 1: # 说明有选择的余地 101 | # 说明找到一个满足条件的,需要更新字典 102 | newdict = {} 103 | for hh in exdict: 104 | if hh < jsa + 1: 105 | newdict[hh] = exdict[hh] 106 | fur = exdict[jsa] + 1 107 | newdict[jsa] = fur 108 | return huifu(select[0:jsa], newdict, save) # 开始递归 109 | return save 110 | 111 | sult = [] 112 | for jj in [[0, dfu] for dfu in range(0, queencount)]:#遍历第0行的元素,找到每一个位置有皇后时的所有解 113 | sult = huifu([jj], startdict, sult)#相加 114 | import numpy as np # 引入numpy数组库 115 | # 通过主对角线对称变换[也就是转置]可以得到的解 116 | def trans(exlist): 117 | yuannp = np.zeros((len(exlist), len(exlist))) 118 | for jj in exlist: 119 | yuannp[jj[0], jj[1]] = 1 120 | # 获得所有的同质解 121 | # 获得转置 122 | trannp = yuannp.T 123 | # 开始获得值为1 的坐标 124 | si = [] 125 | for ihang in range(0, len(exlist)): 126 | for jlie in range(0, len(exlist)): 127 | if trannp[ihang][jlie] == 1: 128 | si.append([ihang, jlie]) 129 | return si 130 | 131 | 132 | # 顺时针每旋转90度产生一个本质一样的解,以及关于主、副对角线对称的解 133 | def sameslover(siglelist): 134 | yuannp = np.zeros((len(siglelist), len(siglelist))) # 构建全0数组 135 | for jj in siglelist: 136 | yuannp[jj[0], jj[1]] = 1 # 选中的坐标,其值为1 137 | # 开始旋转3次,因为旋转4次,与开始的重合,所以旋转3次 138 | xuanzhuan = 0 139 | # 获得所有的同质解 140 | tongzhi = [] 141 | while xuanzhuan < 3: 142 | tongzhi.append(trans(siglelist)) # 添加 主对角线 对称的解 143 | xuanzhuan += 1 144 | # 开始向右翻转90度,形成的新数组的规则为:新数组的行从左到右,是旧数组的列从下往上依次组成的 145 | newnp = [] 146 | for lienu in range(0, len(siglelist)): 147 | lie = [] 148 | for low_up in range(len(siglelist) - 1, -1, -1): 149 | lie.append(yuannp[low_up, lienu]) 150 | newnp.append(lie) 151 | # 开始获得值为1 的坐标 152 | si = [] 153 | for ihang in range(0, len(siglelist)): 154 | for jlie in range(0, len(siglelist)): 155 | if newnp[ihang][jlie] == 1: 156 | si.append([ihang, jlie]) 157 | tongzhi.append(si) 158 | siglelist = si.copy() # 通过这种变换,来获得关于 副对角线 对称的解 159 | # 在此基础上继续翻转 160 | yuannp = np.array(newnp).copy() 161 | tongzhi.append(trans(siglelist)) # 因为需要四个主对角线,循环里面有3次,因此需要加上最后一次,也就是旋转了270度形成的解 的主对角线 对称的解 162 | return tongzhi 163 | 164 | 165 | # print(len(sult)) 166 | # 开始去除本质相同的解 167 | for jj in sult: 168 | for gggg in sameslover(jj): 169 | if gggg in sult and gggg != jj: # 不能删除和初始解一样的解 170 | sult.remove(gggg) 171 | # print(len(sult) 172 | 173 | # 开始绘图展示 174 | from pylab import mpl # 作图显示中文 175 | 176 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 设置中文字体为新宋体 177 | import matplotlib.pyplot as plt 178 | 179 | # 下图中以黑色方块代表皇后 180 | scount = 1 181 | for i_so in sult: 182 | # 开始绘制棋盘 183 | for i in range(0, len(i_so) + 1): 184 | plt.axhline(y=i, linewidth=3, color='k') 185 | plt.axvline(x=i, linewidth=3, color='k') 186 | plt.axis([0, len(i_so), 0, len(i_so)]) 187 | plt.title('%d皇后问题不同解: 第%s个解' % (queencount, scount)) 188 | # 开始绘制皇后, 黑色方块代表皇后 189 | for jif in i_so: 190 | plt.broken_barh([(jif[1], 1)], (len(i_so) - 1 - jif[0], 1), facecolors='k') 191 | plt.axis('off') # 关闭坐标轴 192 | plt.savefig(r"./%s_%s.png" % (queencount, scount)) # 图片保存 193 | plt.close() 194 | scount += 1 195 | 196 | # 最终的图片合成gif 197 | # 所有的图片name集合 198 | namelist = [] 199 | for jjj in range(1, len(sult) + 1): 200 | namelist += ['%s_%s.png' % (queencount, jjj)] * 8 # 数字8控制动态图中每类图片的显示时间 201 | 202 | 203 | # 创建gif的函数 204 | def create_gif(image_list, gif_name): 205 | frames = [] 206 | for image_name in image_list: 207 | frames.append(imageio.imread(image_name)) 208 | imageio.mimsave(gif_name, frames, 'GIF', duration=0.2) # duration控制动态图中每张图片的显示时间 209 | return 210 | 211 | 212 | create_gif(namelist + [namelist[-1]] * 8, 'queen.gif') # 数字8控制动态图中每类图片的显示时间 -------------------------------------------------------------------------------- /N Queens/queen.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/N Queens/queen.gif -------------------------------------------------------------------------------- /N Queens/readme.md: -------------------------------------------------------------------------------- 1 | # N Queens 2 | 3 | * **N皇后问题的程序**:[N_Queen.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/N%20Queens/N_Queens.py) 4 | 5 | 6 | 7 | 8 | * **解的示意图**: 9 | 10 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/N%20Queens/queen.gif) 11 | -------------------------------------------------------------------------------- /One_Stroke/108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/108.png -------------------------------------------------------------------------------- /One_Stroke/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/57.png -------------------------------------------------------------------------------- /One_Stroke/Find_Path_Plus.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # 一笔画完问题自动获取谜题 4 | 5 | """ 6 | 自动读取谜题的图片,获取谜题 7 | 然后利用DFS算法快速解决一笔画完问题, 8 | 也就是获得从起始网格开始,经过所有可以经过的网格,并且没有重复网格的路径 9 | """ 10 | import numpy as np 11 | import matplotlib.pylab as plt 12 | from PIL import Image 13 | from pylab import mpl 14 | import Find_One_Path_Dfs as f_p # 计算路径 15 | import time 16 | 17 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 显示中文 18 | mpl.rcParams['axes.unicode_minus'] = False # 显示负号 19 | 20 | # 变量声明 21 | Fig_Name = r'C:\Users\anaifan\Desktop\1350.jpg' # 谜题图片的绝对路径,图片尽量贴近谜题边框、清晰 22 | 23 | # 颜色转换为灰度模式,颜色越浅数值越大。默认起始网格的颜色 深于 可走网格的颜色 深于不可走网格的颜色(以微信小游戏一笔画完设置) 24 | 25 | Color_list = ['no_walk', 'walk', 'start'] # 可根据谜题图片自动调节 26 | 27 | # 此时需要用户提供谜题中垂直方向有几个网格,水平方向有几个网格 28 | find_one_path = f_p.Find_Path_DFS() 29 | find_one_path.Map_Height = int(input('竖直方向网格数:')) 30 | find_one_path.Map_Width = int(input('水平方向网格数:')) 31 | 32 | # 根据谜题图片以及高度、宽度自动读取各种网格的函数 33 | 34 | def read_puzzle_fig(fig=Fig_Name, error_tolerant_rate=0.8): 35 | """ 36 | 根据一笔画完的谜题的图片,自动识别各个节点 37 | :param fig: 图片的绝对路径 38 | :param error_tolerant_rate: 容错率,图片质量越低,这数设置越小 39 | :return: 自动识别的结果 40 | """ 41 | # 展示谜题照片 42 | puzzle_fig = Image.open(fig) 43 | plt.imshow(puzzle_fig) 44 | plt.axis('off') 45 | 46 | # 图片转为灰度模式 47 | im = Image.open(fig).convert('L') 48 | im_array = np.array(im) 49 | 50 | # 根据每一块中代表颜色数值的大小来确定节点的种类 51 | pixel_height, pixel_length = im_array.shape 52 | # 每个网格大致占有的高度和宽度 53 | per_h = int(pixel_height / find_one_path.Map_Height) 54 | per_l = int(pixel_length / find_one_path.Map_Width) 55 | # 记录每个网格的代表颜色的数值,分别记录网格的均值和标准差 56 | node_index_mean = {} 57 | node_index_std = {} 58 | # 从左上 右上 到左下 右下开始 59 | for i in range(find_one_path.Map_Height): 60 | for j in range(find_one_path.Map_Width): 61 | # 首先计算容错的高度和宽度 62 | t_h = int(round(per_h / 2 * (1 - error_tolerant_rate), 0)) 63 | t_l = int(round(per_l / 2 * (1 - error_tolerant_rate), 0)) 64 | # 选取审查的范围 65 | all_number = im_array[(i * per_h + t_h): ((i + 1) * per_h - t_h), (j * per_l + t_l): ((j + 1) * per_l - t_l)] 66 | arr = sorted(all_number.flatten()) # 平铺为一维的 67 | # 计算网格数值 68 | node_index_mean[(i, j)] = int(np.mean(arr)) 69 | node_index_std[(i, j)] = int(np.std(arr)) 70 | 71 | # # 将数值展示在图像上,看看,注意xy互换 72 | # plt.text((j + 0.3) * per_l, (i + 0.6) * per_h, 'm=%.0f\ns=%.0f' % (node_index_mean[(i, j)], node_index_std[(i, j)])) 73 | 74 | # # 在图像上绘制取数的范围,左上,右上,右下,左下 75 | # plt.plot([j * per_l + t_l, (j + 1) * per_l - t_l, (j + 1) * per_l - t_l, j * per_l + t_l, j * per_l + t_l], 76 | # [i * per_h + t_h, i * per_h + t_h, (i + 1) * per_h - t_h, (i + 1) * per_h - t_h, i * per_h + t_h], c='r') 77 | 78 | # 标准差和均值系列 79 | mean_list = sorted(list(node_index_mean.items()), key= lambda s: s[1], reverse=True) 80 | std_list = sorted(node_index_std.items(), key= lambda s: s[1], reverse=True) 81 | # 图片质量高,标准差高的视为初始点 82 | start_index = list(std_list[0][0]) 83 | # 计算均值序列前后2部分的标准差之和,最小的作为分界线 84 | std_dict = {} 85 | mean_number_list = [k[1] for k in mean_list] 86 | for i in range(1, len(mean_number_list) - 1): # 初始的不算在内 87 | std_dict[i] = np.std(np.array(mean_number_list[:i]), ddof=0) + np.std(np.array(mean_number_list[i:]), ddof=0) 88 | # 选择最小的标准差对应的键值 89 | min_index = sorted(std_dict.items(), key= lambda s: s[1])[0][0] 90 | # 不可走的网格 91 | stone_index = [[s_h[0][0], s_h[0][1]] for s_h in mean_list[:min_index]] 92 | # 获取当前展示的图片 93 | plt.title('识别各个网格完毕') 94 | # 在图上绘制出 95 | # 在初始网格绘制标记 96 | plt.text(start_index[1] * per_l, (start_index[0] + 0.6) * per_h, '初始' ) 97 | # 绘制不可走的网格标记 98 | for no in stone_index: 99 | plt.text(no[1] * per_l, (no[0] + 0.6) * per_h, '不可走') 100 | plt.pause(1) 101 | plt.title('计算路径中……') 102 | plt.pause(1) 103 | # 获得谜题数组 104 | find_one_path.Start_Index = start_index 105 | find_one_path.Stone_Index = stone_index 106 | 107 | start_time = time.perf_counter() 108 | # 更新数组 109 | find_one_path.problem_array = find_one_path.nodes() 110 | path_list = find_one_path.find_one_path_dfs([[find_one_path.Start_Index, 0]]) 111 | # 在图中添加路径 112 | if not path_list: 113 | plt.title('不存在解, 用时:%.3fs' % (time.perf_counter() - start_time)) 114 | else: 115 | x = [(p[0][1] + .5) * per_l for p in path_list] 116 | y = [(p[0][0] + .5) * per_h for p in path_list] 117 | plt.plot(x, y, '-o', c='r', lw=13) 118 | plt.title('路径添加完毕,方法:dfs, 用时:%.3fs' % (time.perf_counter() - start_time)) 119 | plt.pause(2) 120 | plt.ioff() 121 | plt.show() 122 | 123 | read_puzzle_fig() -------------------------------------------------------------------------------- /One_Stroke/dfs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/dfs.png -------------------------------------------------------------------------------- /One_Stroke/lujing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/lujing.jpg -------------------------------------------------------------------------------- /One_Stroke/readme.md: -------------------------------------------------------------------------------- 1 | # One Stroke 2 | 3 | #### 1. 一笔画完题目信息手动输入 4 | 5 | 6 | * **利用DFS和BFS算法获取所有的路径** 7 | 8 | + **程序:[Find_Path.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/Find_Path.py)** 9 | 10 | + **图示** 11 | 12 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/108.png) 13 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/57.png) 14 | 15 | * **利用DFS获取一条路径** 16 | 17 | + **程序:[Find_One_Path_Dfs.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/Find_One_Path_Dfs.py)** 18 | 19 | + **图示** 20 | 21 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/dfs.png) 22 | 23 | #### 2. 根据一笔画完问题截图,自动获取信息,利用dfs算法获得一条路径 24 | 25 | + **程序:[Find_Path_Plus.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/Find_Path_Plus.py)** 26 | 27 | 28 | + **图示** 29 | 30 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/shibie.jpg) 31 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/lujing.jpg) 32 | 33 | + **谜题图片示意图** 34 | 35 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/One_Stroke/timian.jpg) 36 | 37 | -------------------------------------------------------------------------------- /One_Stroke/shibie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/shibie.jpg -------------------------------------------------------------------------------- /One_Stroke/timian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/One_Stroke/timian.jpg -------------------------------------------------------------------------------- /Perfect Maze/Path_For_Cell_AnFany.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | """ 5 | 根据描述迷宫的数组,利用A*算法获得从开始网格到结束网格的路径 6 | 因为解决的迷宫是完美迷宫,任何的两点之间只存在唯一的路径, 7 | 但是A*算法是可以获得多条路径中的最优的 8 | """ 9 | 10 | 11 | # 利用A*获得起始点到结束点的最优路径 12 | def point_go(np_array, cell_index): 13 | """ 14 | 获得索引为[x, y]的网格的周围的网格 15 | :param np_array: 描述迷宫的二维数组 16 | :param cell_index: 网格索引 17 | :return: 可以去的索引的集合,索引为tuple形式 18 | """ 19 | point_list = [] 20 | height, length = len(np_array[0]), len(np_array) 21 | x, y = cell_index 22 | # 上 23 | if x >= 1: 24 | if np_array[x - 1, y] != 1: 25 | point_list.append((x - 1, y)) 26 | # 下 27 | if x < length - 1: 28 | if np_array[x + 1, y] != 1: 29 | point_list.append((x + 1, y)) 30 | # 左 31 | if y >= 1: 32 | if np_array[x, y - 1] != 1: 33 | point_list.append((x, y - 1)) 34 | # 右 35 | if y < height - 1: 36 | if np_array[x, y + 1] != 1: 37 | point_list.append((x, y + 1)) 38 | return point_list 39 | 40 | 41 | def manhattan(s_cell_index, e_cell_index): 42 | """ 43 | 计算索引为s_cell_index, 和e_cell_index网格之间的曼哈顿距离 44 | 曼哈顿距离:对应网格的横坐标差的绝对值与纵坐标的差的绝对值之和 45 | :param s_cell_index: 开始网格的索引 46 | :param e_cell_index: 结束网格的索引 47 | :return: 曼哈顿距离 48 | """ 49 | a, b = s_cell_index 50 | c, d = e_cell_index 51 | return abs(a - c) + abs(b - d) 52 | 53 | 54 | def a_star_best_path(np_array, start_cell, end_cell): 55 | """ 56 | 利用A*算法,返回迷宫中从起始点到结束点的最短路径 57 | :param np_array: 描述迷宫的数组 58 | :param start_cell: 起始点的索引 59 | :param end_cell: 结束点的索引 60 | :return: 最短路径经过的网格的索引列表 61 | """ 62 | # 需要进行索引的转换 63 | start_cell = [2 * s + 1 for s in start_cell] 64 | end_cell = [2 * e + 1 for e in end_cell] 65 | 66 | # 开始A*算法 67 | close_list = {} # 已经走过的网格的集合, 68 | open_list = {tuple(start_cell): [start_cell, 0]} # 将要走的网格的集合 69 | while tuple(end_cell) not in open_list and open_list: 70 | # 选择open_list里面代价函数最小的网格 71 | cost_least = min(open_list.items(), key=lambda k: k[1][1])[0] 72 | 73 | # 计算可以去的相邻的网格 74 | point_list = point_go(np_array, cost_least) 75 | 76 | copy_open_list = open_list.copy() 77 | if point_list: 78 | for j in point_list: 79 | if j in close_list: # 忽略 80 | pass 81 | elif j in open_list: # 需要对比值,选择较小的,并且更改父亲的节点 82 | new_cost = 1 + manhattan(j, end_cell) 83 | if new_cost < open_list[j][1]: 84 | copy_open_list[j][0] = list(cost_least) 85 | else: 86 | copy_open_list[j] = [list(cost_least), 1 + manhattan(j, end_cell) + open_list[tuple(cost_least)][1]] 87 | 88 | # 存储到已经走过的网格中 89 | close_list[cost_least] = open_list[cost_least][0] 90 | del copy_open_list[cost_least] 91 | 92 | open_list = copy_open_list 93 | 94 | if not open_list: # 无解 95 | return [] 96 | else: # 获得最佳的路径 97 | close_list[tuple(end_cell)] = open_list[tuple(end_cell)][0] 98 | end_sign = 0 99 | path_list = [end_cell] 100 | while end_sign != start_cell: 101 | end_sign = close_list[tuple(path_list[-1])] 102 | path_list.append(end_sign) 103 | return path_list[::-1] 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /Perfect Maze/Path_For_Wall_AnFany.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | """ 5 | 根据描述迷宫的字典,利用A*算法获得从开始网格到结束网格的路径 6 | 因为解决的迷宫是完美迷宫,任何的两点之间只存在唯一的路径, 7 | 但是A*算法是可以获得多条路径中的最优的 8 | """ 9 | 10 | 11 | def judge_cell_go(a, b, cell_sign, wall_dict): 12 | """ 13 | 判断从编号为cell_sign的网格,可以去的网格的集合 14 | :param a: 表示迷宫的大小 15 | :param b: 网格的横坐标 16 | :param cell_sign: 网格的编号 17 | :param wall_dict: 描述迷宫墙的字典,值为1的没有墙,值为0的不可以过去 18 | :return: 可以去的网格的编号集合 19 | """ 20 | walkable_cell_sign = [] 21 | all_cells = a * b 22 | row, column = cell_sign // b, cell_sign % b 23 | # 上面的网格编号 24 | up_sign = (row - 1) * b + column 25 | if 0 <= up_sign: 26 | if wall_dict[(cell_sign, 'u')] == 1 and wall_dict[(up_sign, 'd')] == 1: 27 | walkable_cell_sign.append(up_sign) 28 | 29 | # 下面的网格编号 30 | down_sign = (row + 1) * b + column 31 | if down_sign < all_cells: 32 | if wall_dict[(cell_sign, 'd')] == 1 and wall_dict[(down_sign, 'u')] == 1: 33 | walkable_cell_sign.append(down_sign) 34 | 35 | # 右面的网格编号 36 | right_sign = cell_sign + 1 37 | if right_sign % b != 0: 38 | if wall_dict[(cell_sign, 'r')] == 1 and wall_dict[(right_sign, 'l')] == 1: 39 | walkable_cell_sign.append(right_sign) 40 | 41 | # 上面的网格编号 42 | left_sign = cell_sign - 1 43 | if left_sign % b != b - 1: 44 | if wall_dict[(cell_sign, 'l')] == 1 and wall_dict[(left_sign, 'r')] == 1: 45 | walkable_cell_sign.append(left_sign) 46 | 47 | return walkable_cell_sign 48 | 49 | 50 | def manhattan(a, b, cell_1, cell_2): 51 | """ 52 | 计算网格编号为cell_1, cell_2的网格之间的曼哈顿距离,返回网格中心点坐标对应的距离 53 | 曼哈顿距离:对应网格的横坐标差的绝对值与纵坐标的差的绝对值之和 54 | :param a: 迷宫的行数 55 | :param b: 迷宫的列数 56 | :param cell_1: 开始的网格编号 57 | :param cell_2: 结束的网格编号 58 | :return: 曼哈顿距离 59 | """ 60 | cell_1_center_x, cell_1_center_y = cell_1 % b + 0.5, a - cell_1 // b - 1 + 0.5 61 | cell_2_center_x, cell_2_center_y = cell_2 % b + 0.5 , a - cell_2 // b - 1 + 0.5 62 | return abs(cell_1_center_x - cell_2_center_x) + abs(cell_1_center_y - cell_2_center_y) 63 | 64 | 65 | def a_star_best_path(a, b, maze_dict, enter_cell_sign, outer_cell_sign): 66 | """ 67 | 利用A*算法,返回迷宫中从起始网格到结束网格的最短路径 68 | :param a: 迷宫的行数 69 | :param b: 迷宫的列数 70 | :param maze_dict: 描述迷宫墙的字典 71 | :param enter_cell_sign: 起始的网格编号 72 | :param outer_cell_sign: 结束的网格编号 73 | :return: 最短的路径 74 | """ 75 | 76 | # 开始A*算法 77 | close_list = {} # 已经走过的网格的集合 78 | open_list = {enter_cell_sign: [enter_cell_sign, 0]} # 存储将要走的网格的集合 79 | 80 | # 当结束网格在已经遍历的路径里,或者将要走的网格为空时,结束循环。前者说明找到答案,后者说明题目无解 81 | while outer_cell_sign not in open_list and open_list: 82 | # 选择open_list里面代价函数最小的网格 83 | cost_least_cell = min(open_list.items(), key=lambda k: k[1][1])[0] 84 | 85 | # 计算可以去的相邻的网格 86 | cell_list = judge_cell_go(a, b, cost_least_cell, maze_dict) 87 | 88 | copy_open_list = open_list.copy() 89 | 90 | if cell_list: 91 | for j in cell_list: 92 | if j in close_list: # 忽略 93 | pass 94 | elif j in open_list: # 需要对比值,选择较小的,并且更改父亲的节点 95 | new_cost = 1 + manhattan(a, b, j, outer_cell_sign) 96 | if new_cost < open_list[j][1]: 97 | copy_open_list[j][0] = cost_least_cell 98 | else: 99 | copy_open_list[j] = [cost_least_cell, 100 | 1 + manhattan(a, b, j, outer_cell_sign) + open_list[cost_least_cell][1]] 101 | 102 | # 存储到已经走过的网格中 103 | close_list[cost_least_cell] = open_list[cost_least_cell][0] 104 | del copy_open_list[cost_least_cell] 105 | 106 | open_list = copy_open_list 107 | 108 | if not open_list: # 无解 109 | path_list = [] 110 | else: # 获得最佳的路径 111 | close_list[outer_cell_sign] = open_list[outer_cell_sign][0] 112 | end_sign = -1 113 | path_list = [outer_cell_sign] 114 | while end_sign != enter_cell_sign: 115 | end_sign = close_list[path_list[-1]] 116 | path_list.append(end_sign) 117 | 118 | # 将路径中的网格编号,转换为网格的中心点的坐标序列,便于绘图 119 | coordinate_x, coordinate_y = [], [] 120 | 121 | # 因为路径是从终点,一步步寻找到起点的,因此需要逆序 122 | path_list = path_list[::-1] 123 | for p in path_list: 124 | coordinate_x.append(p % b + 0.5) 125 | coordinate_y.append(a - p // b - 0.5) 126 | return path_list, coordinate_x, coordinate_y 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /Perfect Maze/Simple_Prim_Maze_Cell.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | """ 5 | Prim算法,遍历表示路的网格生成完美迷宫,A*算法获得从出口到入口的最优路径 6 | """ 7 | import Path_For_Cell_AnFany as p_c # A*算法 8 | import matplotlib.patches as mpatches # 图例的设置 9 | import matplotlib.pyplot as plt 10 | import numpy as np 11 | import matplotlib.colors as col 12 | from pylab import mpl 13 | 14 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 显示中文 15 | mpl.rcParams['axes.unicode_minus'] = False # 显示负号 16 | 17 | 18 | # 因为迷宫采用网格的形式,也就是可以利用数组形式绘图,需要根据数值的大小来区分颜色 19 | # 数字最好是连续的,否则颜色容易不对 20 | Wall_Color = 'k' # 保留的墙 21 | Wall_Number = 1 22 | 23 | Path_Color = 'lightcyan' # 路 24 | Path_Number = 0 25 | 26 | # 定义出口和入口的表示, 27 | Enter_Color = 'brown' 28 | Enter_Number = 2 29 | Outer_Color = 'g' 30 | Outer_Number = 3 31 | 32 | # 迷宫的行数和列数 33 | Row = 28 34 | Column = 39 35 | 36 | # 出口和入口的索引, 设置时不要超出范围,绘图时,真正的索引就是2倍加1 37 | Enter_Coordinate = [0, 0] # 默认[0,0] 38 | Outer_Coordinate = [Row-1, Column-1] # 默认[Row-1, Column-1] 39 | 40 | 41 | # 路径的颜色 42 | Road_Color = 'purple' 43 | 44 | 45 | def prim_generate_maze_cell(a, b, path=False): 46 | """ 47 | 根据Prim算法,遍历网格生成迷宫,并且动态展示迷宫的生成过程 48 | 开始时所有的网格(表示路的,和表示墙的)均看作墙, 49 | :param a: 迷宫的行数 50 | :param b: 迷宫的列数 51 | :param path: 是否添加路径,默认为Ture 52 | :return: 表示迷宫的数组 53 | """ 54 | # 因为墙和路是同等的宽度,再加上外围的墙,因此迷宫的高度和宽度会变化 55 | height = 2 * a + 1 56 | length = 2 * b + 1 57 | 58 | maze_array = [] 59 | for i in range(height): 60 | maze_array.append([Wall_Number] * length) # 初始所有网格为墙 61 | maze_array = np.array(maze_array) # 转换为np格式的数组 62 | 63 | # 绘制图 64 | fig, ax = plt.subplots() 65 | plt.axis('off') 66 | 67 | # 所有网格cell的集合 68 | cell_list = {(i, j): 0 for i in range(1, height, 2) for j in range(1, length, 2)} # 因为有外墙,所以从1,并且间隔1才是路。 69 | 70 | # 开始利用prim算法生成迷宫 71 | # 随机选取一个开始的网格 72 | key_list = list(cell_list.keys()) 73 | random_start_sign = np.random.randint(0, len(key_list), 1)[0] 74 | x, y = key_list[random_start_sign] 75 | 76 | # 将这个网格设置为路,也就是数组中的值变为代表路的数字 77 | maze_array[x, y] = Path_Number 78 | 79 | # 计算这个网格四周相邻的网格,加入到待选网格中 80 | selcted_cell_list = [s for s in [(x + 2, y), (x - 2, y), (x, y + 2), (x, y - 2)] 81 | if s in cell_list] 82 | 83 | # 当候选区中有表示路的网格时,就继续,直到所有的路遍历完 84 | while selcted_cell_list: 85 | # 在候选的网格系列中,随机选择一个网格 86 | random_sign = np.random.randint(0, len(selcted_cell_list), 1)[0] 87 | # 在选中的网格 88 | selected_x, selected_y = selcted_cell_list[random_sign] 89 | # 被选中的设置颜色 90 | maze_array[selected_x, selected_y] = Path_Number 91 | # 只要这个网格的相邻网格中,如果相邻的网格已经遍历,并且之间的墙也变为通路了 92 | # 则直接把选中的网格变为通路就可以了,然后再把这个网格周围的没有遍历过的加到候选区里 93 | # 如果虽然周围有网格已经遍历过,但是墙没有设置通路, 94 | # 就随机选择一个墙,变为通路就可以了 95 | 96 | # 也就是说如果这个网格可以直接通往别的网格,就把这个网格设置为通路,如果过不去,就在周围那些已经可以到达的网格里,随机选取一个 97 | # 把与其之间的墙打通就可以了 98 | 99 | round_cell_0 = [] # 如果不为空,说明这个网格可以直接通往别的网格, 100 | round_cell_1 = [] # 只有round_cell_0为空的前提下,才随机砸墙 101 | 102 | x, y = selected_x, selected_y 103 | for k in [(x + 2, y), (x - 2, y), (x, y + 2), (x, y - 2)]: 104 | if k in cell_list and maze_array[k[0], k[1]] == 0: 105 | if maze_array[int((k[0] + x) / 2), int((k[1] + y) / 2)] == 0: 106 | round_cell_0.append(k) 107 | else: 108 | round_cell_1.append(k) 109 | 110 | selcted_cell_list.remove((x, y)) 111 | 112 | if round_cell_0: 113 | pass 114 | else: 115 | round_cell_sign = np.random.randint(0, len(round_cell_1), 1)[0] 116 | se_x, se_y = round_cell_1[round_cell_sign] 117 | # 将这2个网格之间的网格也设为通路 118 | x_mid, y_mid = int((x + se_x) / 2), int((y + se_y) / 2) 119 | maze_array[x_mid, y_mid] = Path_Number 120 | 121 | # 设置为0 122 | maze_array[x, y] = Path_Number 123 | # 添加当前网格的周围网格 124 | for h in [(x + 2, y), (x - 2, y), (x, y + 2), (x, y - 2)]: 125 | if h in cell_list and maze_array[h[0], h[1]] == Wall_Number: 126 | selcted_cell_list.append(h) 127 | 128 | # 开始添加入口,如果使用默认入口,则显示入口2字,否则显示起点 129 | if Enter_Coordinate == [0, 0]: 130 | # 迷宫的外墙去掉一部分 131 | maze_array[1, 0] = Enter_Number 132 | enter_patch = mpatches.Patch(color=Enter_Color, label='入口') 133 | else: 134 | row, column = Enter_Coordinate 135 | maze_array[2 * row + 1, 2 * column + 1] = Enter_Number 136 | enter_patch = mpatches.Patch(color=Enter_Color, label='起点') 137 | # 开始添加出口,如果使用默认出口,则显示出口2字,否则显示终点 138 | if Outer_Coordinate == [a-1, b-1]: 139 | # 迷宫的外墙去掉一部分 140 | maze_array[-2, -1] = Outer_Number 141 | outer_patch = mpatches.Patch(color=Outer_Color, label='出口') 142 | else: 143 | row, column = Outer_Coordinate 144 | maze_array[2 * row + 1, 2 * column + 1] = Outer_Number 145 | outer_patch = mpatches.Patch(color=Outer_Color, label='终点') 146 | 147 | # 有路,有墙,有出,有入 ,有4种颜色 148 | cmap_af = col.LinearSegmentedColormap.from_list('anfany', [Path_Color, Wall_Color, Enter_Color, Outer_Color]) 149 | ax.imshow(maze_array, cmap=cmap_af) 150 | # 更新图例 151 | remove_patch = mpatches.Patch(color=Path_Color, label='路') 152 | keep_patch = mpatches.Patch(color=Wall_Color, label='墙') 153 | plt.legend(handles=[keep_patch, remove_patch, enter_patch, outer_patch], 154 | bbox_to_anchor=(0.1, -0.1, 0.8, .102), loc='lower left', 155 | ncol=4, mode="expand", borderaxespad=0.) 156 | 157 | if path: 158 | plt.title('迷宫生成完毕,添加路径…………') 159 | path_list = p_c.a_star_best_path(maze_array, Enter_Coordinate, Outer_Coordinate) 160 | if not path_list: 161 | plt.title('迷宫生成完毕,路径未找到') 162 | else: 163 | # 为了绘制路径,需要把索引变为图像中网格的中心坐标 164 | if Enter_Coordinate == [0, 0]: 165 | path_list.insert(0, [1, 0]) 166 | if Outer_Coordinate == [a - 1, b - 1]: 167 | path_list += [[2 * a - 1, 2 * b]] 168 | center_x = [p[1] for p in path_list] 169 | center_y = [p[0] for p in path_list] 170 | plt.plot(center_x, center_y, 's', c=Road_Color, mfc=Road_Color, lw=1) 171 | road_patch = mpatches.Patch(color=Road_Color, label='路径') 172 | plt.legend(handles=[keep_patch, remove_patch, enter_patch, outer_patch, road_patch], 173 | bbox_to_anchor=(0.1, -0.1, 0.8, .102), loc='lower left', 174 | ncol=5, mode="expand", borderaxespad=0.) 175 | plt.title('迷宫生成完毕,路径添加完毕') 176 | 177 | else: 178 | plt.title('%d*%d迷宫生成完毕' % (a, b)) 179 | 180 | plt.ioff() 181 | plt.show() 182 | return maze_array 183 | 184 | 185 | hh = prim_generate_maze_cell(Row, Column) 186 | 187 | -------------------------------------------------------------------------------- /Perfect Maze/Simple_Prim_Maze_Wall.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | """ 5 | Prim算法生成完美迷宫,A*算法获得从出口到入口的最优路径,并用图展示 6 | """ 7 | import Path_For_Wall_AnFany as p_w # A*算法获得路径 8 | 9 | import matplotlib.patches as mpatches # 图例的设置 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | from pylab import mpl 13 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 显示中文 14 | mpl.rcParams['axes.unicode_minus'] = False # 显示负号 15 | 16 | # 根据墙的不同状态,定义不同的颜色,便于观察迷宫是怎么形成的 17 | 18 | Keep_Color = 'k' # 固定下来的墙 19 | Remove_Color = 'whitesmoke' # 删除的墙 20 | 21 | # 根据绘制墙的线条宽度 22 | Wall_Width = 4 23 | Remove_Width = 4.3 # 需要比普通的墙的粗度稍微大点,否则会有删除的痕迹 24 | Side_Width = 5 # 最终,迷宫四周的墙稍微厚点,美观 25 | 26 | # 设置迷宫的行数和列数 27 | Row = 28 28 | Column = 39 29 | 30 | # 设置迷宫的入口和出口 31 | Enter = 0 # [0, Row*Column)区间内的整数,默认为0 32 | Outer = Row * Column - 1 # [0, Row*Column)区间内的不等于Enter的整数,默认为a*b-1 33 | 34 | # 定义出口,入口的标识颜色 35 | Enter_Color = 'tab:red' 36 | Outer_Color = 'tab:green' 37 | 38 | # 设置迷宫中的路径以及中间节点的颜色 39 | Path_Color = 'g' 40 | Node_Color = 'orange' 41 | 42 | 43 | def prim_generate_maze_wall(a, b, path=True): 44 | """ 45 | 根据Prim算法,遍历墙生成a*b大小的迷宫,动态展示迷宫的生成过程 46 | :param a: 迷宫的行数 47 | :param b: 迷宫的列数 48 | :param path: 是否在最终的迷宫中添加路径,默认添加 49 | :return: 表示迷宫内所有墙的状态的字典 50 | """ 51 | cell_number = a * b # 迷宫的网格数,迷宫的最左上角的网格编号为0 52 | 53 | # 所有墙的字典,每个网格均有4面墙,存在重复的墙 54 | wall_dict = {(i, h): 0 for i in range(cell_number) for h in ['u', 'd', 'r', 'l']} 55 | wall_direction = {'u': 'd', 'd': 'u', 'l': 'r', 'r': 'l'} # 因为存在重复的墙,删除墙的时候需要用到 56 | 57 | # 绘制图形 58 | plt.figure() 59 | plt.style.use('ggplot') 60 | # 首先设置坐标轴的刻度 61 | plt.xticks(list(range(b))) 62 | plt.yticks(list(range(a))) 63 | # 关闭坐标轴 64 | plt.axis('off') 65 | # 开始绘制初始的迷宫,为了美观, 内部的墙和迷宫外围的墙分开绘制 66 | # 为了绘图方便,存储绘制的墙 67 | save_wall_plot = {} 68 | for w in wall_dict: 69 | sign, direction = w 70 | if direction == 'd': # 下墙 71 | point1_x = sign % b 72 | point1_y = a - sign // b - 1 73 | point2_x = point1_x + 1 74 | point2_y = point1_y 75 | if point2_y != 0: # 避过下边 76 | plt.plot([point1_x, point2_x], [point1_y, point2_y], c=Keep_Color, lw=Wall_Width) 77 | save_wall_plot[(sign, 'd')] = [[point1_x, point2_x], [point1_y, point2_y]] 78 | if direction == 'r': # 右墙 79 | point1_x = sign % b + 1 80 | point1_y = a - sign // b - 1 81 | point2_x = sign % b + 1 82 | point2_y = a - sign // b 83 | if point2_x != b: # 避过右边 84 | plt.plot([point1_x, point2_x], [point1_y, point2_y], c=Keep_Color, lw=Wall_Width) 85 | save_wall_plot[(sign, 'r')] = [[point1_x, point2_x], [point1_y, point2_y]] 86 | # 开始进行Prim算法 87 | 88 | # 随机选择一个网格 89 | random_cell = np.random.randint(0, cell_number, 1)[0] 90 | # 将这个网格的所有的墙存进待选的墙中 91 | wall_list = [(random_cell, 'd'), (random_cell, 'u'), (random_cell, 'r'), (random_cell, 'l')] 92 | 93 | arrive_wall = [random_cell] # 已经处理过的网格 94 | 95 | # 只要墙的候选列表还有没有遍历过的墙,就继续 96 | while wall_list: 97 | # 在墙的候选列表中随机选择一堵墙 98 | random_wall_sign = np.random.randint(0, len(wall_list), 1)[0] 99 | selected_wall = wall_list[random_wall_sign] 100 | 101 | # 根据选择的墙, 得到另一网格的编号 102 | current_wall_sign, current_wall_direction = selected_wall 103 | if current_wall_direction == 'd': # 下面的网格 104 | other = (current_wall_sign // b + 1) * b + current_wall_sign % b 105 | 106 | elif current_wall_direction == 'u': # 上面的网格 107 | other = (current_wall_sign // b - 1) * b + current_wall_sign % b 108 | 109 | elif current_wall_direction == 'l': # 左面的网格 110 | other = current_wall_sign - 1 111 | if other % b == b - 1: 112 | other = -1 # 为了表示在迷宫外 113 | else: # 右面的网格 114 | other = current_wall_sign + 1 115 | if other % b == 0: 116 | other = -1 # 为了表示在迷宫外 117 | 118 | # 判断这个墙分割的2个网格,是否在已经到达过的网格列表中, 119 | if 0 <= other < cell_number: 120 | judge_cell = [j_c for j_c in [other, current_wall_sign] if j_c not in arrive_wall] 121 | 122 | if len(judge_cell) == 1: 123 | # 需要删除两个网格之间的墙 124 | wall_dict[selected_wall] = 1 125 | wall_dict[(other, wall_direction[current_wall_direction])] = 1 126 | 127 | # 在图像中删除墙 128 | for wall in [selected_wall, (other, wall_direction[current_wall_direction])]: 129 | if wall in save_wall_plot: 130 | point_x, point_y = save_wall_plot[wall] 131 | # 删除的墙,设置为白色,线条粗度稍微大于墙的线粗 132 | plt.plot(point_x, point_y, '-o', c=Remove_Color, lw=Remove_Width, mfc=Keep_Color) 133 | break 134 | arrive_wall.append(judge_cell[0]) 135 | # 然后将网格周围的墙加入当前的墙的列表 136 | for s in [(judge_cell[0], 'd'), (judge_cell[0], 'u'), (judge_cell[0], 'r'), (judge_cell[0], 'l')]: 137 | if wall_dict[s] == 0: 138 | wall_list.append(s) 139 | # 需要从wall_list删除这个墙 140 | wall_list.remove(selected_wall) 141 | 142 | # 为了美观,加上迷宫四周 143 | plt.plot([0, 0], [0, a], c=Keep_Color, lw=Side_Width) # 左边 144 | plt.plot([0, b], [a, a], c=Keep_Color, lw=Side_Width) # 上边 145 | plt.plot([b, b], [0, a], c=Keep_Color, lw=Side_Width) # 右边 146 | plt.plot([0, b], [0, 0], c=Keep_Color, lw=Side_Width) # 下边 147 | 148 | # 添加入口和出口的表示,根据网格编号判断坐标 149 | # 如果出口或者入口是默认值, 则相应的删除掉相应的围墙 150 | enter_x1, enter_y1 = Enter % b, a - Enter // b - 1 151 | if enter_x1 == 0 and enter_y1 == a - 1: 152 | plt.plot([enter_x1, enter_x1], [enter_y1, enter_y1+1], '-o', c=Remove_Color, 153 | lw=Side_Width, mfc=Keep_Color) 154 | plt.scatter([enter_x1 + .3], [enter_y1 + .5], marker='*', c=Enter_Color, s=29, alpha=1, label='入口') 155 | else: 156 | plt.scatter([enter_x1 + .3], [enter_y1 + .5], marker='*', c=Enter_Color, s=29, alpha=1, label='起点') 157 | 158 | outer_x1, outer_y1 = Outer % b, a - Outer // b - 1 159 | if outer_x1 == b - 1 and outer_y1 == 0: 160 | plt.plot([outer_x1+1, outer_x1+1], [outer_y1, outer_y1+1], '-o', c=Remove_Color, 161 | lw=Side_Width, mfc=Keep_Color) 162 | plt.scatter([outer_x1 + .7], [outer_y1 + .5], marker='o', c=Outer_Color, s=29, alpha=1, label='出口') 163 | else: 164 | plt.scatter([outer_x1 + .7], [outer_y1 + .5], marker='o', c=Outer_Color, s=29, alpha=1, label='终点') 165 | 166 | # 更新标题 167 | if path: 168 | plt.title('%d*%d的迷宫生成完毕,添加路径……………' % (a, b)) 169 | else: 170 | plt.title('%d*%d的迷宫已经生成完毕' % (a, b)) 171 | # 更新图例 172 | plt.legend(bbox_to_anchor=(0.1, -0.1, 0.8, .102), loc='lower left', ncol=2, mode="expand", borderaxespad=0.) 173 | 174 | # 则在迷宫中添加路径 175 | if path: 176 | path_cell_sign, path_x, path_y = p_w.a_star_best_path(a, b, wall_dict, Enter, Outer) 177 | if not path_cell_sign: 178 | plt.title('未寻找到路径') 179 | else: 180 | plt.plot(path_x, path_y, '--s', c=Path_Color, mfc=Node_Color, lw=Wall_Width, label='路径') 181 | # 路径中添加编号 182 | for p_x, p_y, tip in zip(path_x, path_y, path_cell_sign): 183 | plt.text(p_x, p_y + 0.1, '%d' % tip, ha='center', va='bottom', fontsize=10, color=Keep_Color) 184 | plt.title('%d*%d的迷宫、添加路径完毕' % (a, b)) 185 | # 更新图例 186 | plt.legend(bbox_to_anchor=(0.1, -0.1, 0.8, .102), loc='lower left', ncol=3, mode="expand", borderaxespad=0.) 187 | 188 | plt.show() 189 | return print('') 190 | 191 | 192 | # 最终的函数 193 | 194 | if __name__ == "__main__": 195 | prim_generate_maze_wall(Row, Column) 196 | 197 | 198 | 199 | -------------------------------------------------------------------------------- /Perfect Maze/c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Perfect Maze/c.png -------------------------------------------------------------------------------- /Perfect Maze/cell.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Perfect Maze/cell.jpg -------------------------------------------------------------------------------- /Perfect Maze/readme.md: -------------------------------------------------------------------------------- 1 | # Prefect Maze 程序说明 2 | 3 | 4 | * Prim按墙遍历 5 | 6 | * 动态展示迷宫生成文件:[Maze_AnFany_Wall.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Maze_AnFany_Wall.py) 7 | 8 | * 路径寻找文件:[Path_For_Wall_AnFany.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Path_For_Wall_AnFany.py) 9 | 10 | * 精简迷宫生成文件:[Simple_Prim_Maze_Wall.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Simple_Prim_Maze_Wall.py) 11 | 12 | * 示图: 13 | 14 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/w.jpg) 15 | 16 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/wall.jpg) 17 | 18 | * Prim按网格遍历 19 | 20 | * 动态展示迷宫生成文件:[Maze_AnFay_Cell.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Maze_AnFay_Cell.py) 21 | 22 | * 路径寻找文件:[Path_For_Cell_AnFany.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Path_For_Cell_AnFany.py) 23 | 24 | * 精简迷宫生成文件:[Simple_Prim_Maze_Cell.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/Simple_Prim_Maze_Cell.py) 25 | 26 | * 示图: 27 | 28 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/c.png) 29 | 30 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Perfect%20Maze/cell.jpg) 31 | -------------------------------------------------------------------------------- /Perfect Maze/w.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Perfect Maze/w.jpg -------------------------------------------------------------------------------- /Perfect Maze/wall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Perfect Maze/wall.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Funny-Math-Problem-by-Python3 2 | 基于Python3的趣味数学问题解决方案 3 | 4 | 5 | **Pro1. [数独 (Sudoku)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Sudoku)** 6 | >>>根据九宫格盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个宫(3*3)内的数字均含1—9这9个数字。 7 | 8 | **Pro2. [幻方 (Magic Square)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Magic%20Square)** 9 | >>>幻方又称为魔方,方阵或厅平方。通常幻方由从1到n2 的连续整数组成,其中n为正方形的行或列的数目。将数填在纵横格数都相等的正方形图内,使得每一行、每一列和每一条对角线上的各个数之和都相等。 10 | 11 | **Pro3. [24点 (24 Point)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/24%20Point)** 12 | >>>把4个整数通过加、减、乘、除以及括号运算,使最后的计算结果是24的一个数学游戏。 13 | 14 | **Pro4. [汉诺塔 (Tower of Hanoi)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Tower%20of%20Hanoi)** 15 | >>>法国数学家爱德华·卢卡斯曾编写过一个关于印度的古老传说:在世界中心贝拿勒斯的圣庙里,一块黄铜板上插着三根宝石针,印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。这就是汉诺塔问题。 16 | 17 | **Pro5. [N皇后 (N Queens)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/N%20Queens)** 18 | >>>八皇后问题,是一个古老而著名的问题,是利用回溯算法求解的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处同一行、同一列或同一斜线上,问有多少种摆法。之后陆续有许多数学家对其进行研究,其中包括高斯和康托,并且将其推广为N皇后问题。 19 | 20 | **Pro6. [彩票号码优选方案 (Lottery Number)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Lottery)** 21 | >>>彩票号码优选方案。双色球、大乐透号码的优选方案。 22 | 23 | **Pro7. [完美迷宫 (Perfect Maze)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Perfect%20Maze)** 24 | >>>所谓完美迷宫,就是没有回路,没有不可达区域的迷宫,并且迷宫中任意两个网格间都有唯一的路径。利用Prim算法,分别采取遍历墙和遍历网格的方法,动态展示迷宫的生成。并且利用A\*算法获得从入口到出口的最佳路径,并在迷宫中展示出来。 25 | 26 | **Pro8. [凸包 (Convex Hull)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Convex%20Hull)** 27 | >>>下面用比较通俗的方式,介绍下凸包:在一个二维坐标平面中,散列着一些点,将最外层的点连接起来构成的凸多边型,它能包含散列的所有的点,这个多边形就是这些点构成的点集的凸包。利用Graham Scan算法获得凸包(平面凸包),并动态展示凸包的形成过程。 28 | 29 | **Pro9. [一笔画完 (One Stroke)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/One_Stroke)** 30 | >>>从起始网格开始,用一笔划过所有可以走的节点,不能遗漏,也不能重复。利用DFS(深度优先搜索)和BFS(广度优先搜索)算法找到所有的路径,在寻找路径过程中添加了优化选择的函数,加速了计算过程。最总图示所有的解。涉及到的点有Python的尾递归优化以及基于多线程的计时器。 31 | 32 | **Pro10. [七桥 (Seven Bridge)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Seven%20Bridge)** 33 | >>>一笔划过图形中所有的边,边不能遗漏,同时也不能重复。利用欧拉定理以及Fleury(弗洛莱)算法解决。 34 | 35 | **Pro11. [旅行商 (Traveling Salesman)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Traveling%20Salesman)** 36 | >>>旅行商问题(TSP),一个旅行商要拜访N个城市,每个城市只能拜访一次,最后要回到原来出发的城市。选择的路径的路程必须是所有路径中值最小的。以全国34城市为例。城市之间的距离定义为经纬度之间的地球表面的距离。利用遗传算法(Genetic Algorithm)获得最终的方案。 37 | 38 | **Pro12. [变态曲线 (Abnormal Curve)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Abnormal%20Curve)** 39 | >>>由一簇具有某种规律的直线的交点构成的变态曲线,探索这条变态曲线的表达式,以及计算曲线下的面积和直线簇构成的图形的面积的误差的范围。 40 | 41 | **Pro13. [爱因斯坦问题 (Einstein's Puzzle)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Einstein's%20Puzzle)** 42 | >>>利用回溯算法解决爱因斯坦问题。在一条街上,有5座房子,喷了不同的5种颜色。每个房子里住着不同国籍的人。每个人喝着不同的饮料,抽不同品牌的香烟,养不同的宠物。问:谁养鱼? 43 | 44 | **Pro14. [分形 (Fractal)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Fractal)** 45 | >>>分形(Fractal)一词,是由美国数学家曼德勃罗先生(Mandelbrot)创造出来的。分形几何学是一门以非规则几何形态为研究对象的几何学。按照分形几何学的观点,一切复杂的对象虽然看似杂乱无章,但他们具有相似性。简单地说,就是把复杂对象的某个局部进行放大,其形态和复杂程度与整体相似。本文给出基于复动力系统,例如Mandelbrot集合、Julia集合;基于迭代函数系统,例如Koch雪花、谢尔宾斯基三角形。 46 | 47 | **Pro15. [八人过河(Cross River)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Cross%20River)** 48 | >>>现在有8个人分别为:1个父亲,带着他的2个儿子。1个母亲,带着她的2个女儿;1个警察,带着1个犯人;开始时,8个人都是在河的左岸。现在需要过河,过河时需要注意下面5条说明:1,只有警察、父亲和母亲可以划船;2,警察如果离开犯人,犯人就会伤害其他人;3,母亲不在时,这个父亲会伤害她的女儿。4,父亲不在时,这个母亲也会伤害他的儿子;5,船上一次最多只能坐两个人。求出过河方案。利用状态空间BFS搜索算法解决,并以绘图形式给出解决方案。 49 | 50 | **Pro16. [十五谜题(15 Puzzle)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/15%20Puzzle)** 51 | >>>15谜题是由纽约卡纳斯托塔市的邮政局长诺伊斯·查普曼发明的。15谜题就是将编号从1到15的15个方块,放在一个有16个格子的4×4的的盒子中,其中一个格子是没有方块的。通过移动方块,使得方块的编号从左上方到右下方正好是连续的,并且右下角的格子正好没有方块。利用IDA\*算法获得移动方案。 52 | 53 | **Pro17. [华容道(Klotski)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/Klotski)** 54 | >>>华容道是古老的中国民间益智游戏,据《资治通鉴》注释中说“从此道可至华容也”。华容道原是中国古代的一个地名,相传当年曹操曾经败走此地。通过移动各个棋子,帮助曹操从初始位置移到棋盘最下方中部。不允许跨越棋子,还要设法用最少的步数把曹操移到出口。本文利用BFS算法给出24局华容道最佳的移动方案。 55 | 56 | **Pro18. [生命游戏(Game of Life)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/lifegame)** 57 | >>>生命游戏是英国数学家约翰·何顿·康威(John Horton Conway)在1970年发明的,由3条规则构成的二维细胞自动机。该游戏号称“零玩家且永不结束”。令人感到惋惜的是,2020年4月11日他因感染新冠肺炎(COVID-19)去世,数学“老顽童”就此陨落。 58 | 59 | **Pro19. [贝塞尔曲线(Bezier Curve)](https://github.com/Anfany/Funny-Math-Problem-by-Python3/tree/master/bezier)** 60 | >>>贝塞尔曲线(Bezier Curve)是经起始点开始,在锚点结束,中间由多个点控制的一种平滑曲线。本文给出基于de Casteljau算法和直接法的绘制曲线的程序以及贝塞尔曲线的应用。 61 | 62 | ###### 扫描二维码,关注订阅号,可获取以上谜题的详细解答,以及关于编程、机器学习等方面的文章。 63 | ![image](https://github.com/Anfany/Machine-Learning-for-Beginner-by-Python3/blob/master/pythonfan_anfany.jpg) 64 | -------------------------------------------------------------------------------- /Seven Bridge/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/0.png -------------------------------------------------------------------------------- /Seven Bridge/00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/00.png -------------------------------------------------------------------------------- /Seven Bridge/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/1.png -------------------------------------------------------------------------------- /Seven Bridge/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/2.png -------------------------------------------------------------------------------- /Seven Bridge/Seven_Bridge.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 需要用户自己在网站https://www.geogebra.org/graphing绘制出谜题,绘制完成后导出作图过程的html文件 5 | # 程序读取作图过程,然后展示谜题,以及利用Fleury算法求解路径 6 | 7 | import read_fig_html as r_f # 读取作图过程html文件的程序 8 | import matplotlib.pyplot as plt 9 | from pylab import mpl 10 | 11 | mpl.rcParams['font.sans-serif'] = ['FangSong'] # 显示中文 12 | mpl.rcParams['axes.unicode_minus'] = False # 显示负号 13 | 14 | 15 | # 欧拉通路又称为欧拉开迹• 欧拉回路又称为欧拉闭迹 16 | def judge_euler(line): 17 | """ 18 | 如果所有的节点均出现了偶数次,也就是节点的度为偶数,说明是闭欧闭迹,则起点和终点是同一个 19 | 如果仅有2个节点出现了奇数次,也就是仅有2个节点的度为奇数,说明是欧拉开迹,则其中一个是起点,另一个是终点 20 | 其他情况均不能一笔画出 21 | :param line: 边的列表 22 | :return: 起点,终点,度为奇数的点的集合 23 | """ 24 | node = sum(line, []) 25 | node_list = [i for i in list(set(node)) if node.count(i) % 2 == 1] 26 | if not node_list: 27 | return node[0], node[0], node_list # 起始点,终点, 奇数次的节点 28 | else: 29 | if len(node_list) == 2: 30 | return node_list[0], node_list[1], node_list # 起始点,终点, 奇数次的节点 31 | else: 32 | return "None", 0, node_list 33 | 34 | 35 | def get_dict(line): 36 | """ 37 | 以每个节点为键,可以去的节点为值的字典 38 | :param line: 边的列表 39 | :return: 字典 40 | """ 41 | node_dict = {} 42 | for j in line: 43 | if j[0] in node_dict: 44 | node_dict[j[0]].append(j[1]) 45 | else: 46 | node_dict[j[0]] = [j[1]] 47 | if j[1] in node_dict: 48 | node_dict[j[1]].append(j[0]) 49 | else: 50 | node_dict[j[1]] = [j[0]] 51 | return node_dict 52 | 53 | 54 | def select_line(walk_line, current_node, next_node, line): 55 | """ 56 | # 判断当前节点current_node 和next_node组成的边是否是桥。如果去除这条边以后,剩下的图不是连通的, 57 | 也就是存在没有线可以连接的两点,说明这是桥。如果都是桥,则任意选取节点作为next_node。否则先选择不是桥的节点 58 | :param walk_line: 已经走过的边 59 | :param current_node: 当前的节点 60 | :param next_node: 下一个节点 61 | :param line: 全部的边 62 | :return: 是桥,返回True,不是返回False 63 | """ 64 | # 已经走过的边添加上要判断的边 65 | min_node, max_node = sorted([current_node, next_node]) 66 | copy_walk_line = walk_line.copy() 67 | copy_walk_line.append([min_node, max_node]) 68 | # 没有走过的边 69 | no_walk_line = [h for h in line if h not in copy_walk_line] 70 | 71 | # 剩下的所有的节点 72 | all_nodes = list(set(sum(no_walk_line, []))) 73 | 74 | # 首先判断是不是桥 75 | # 首先将边变为字典 76 | line_dict = {} 77 | for i in no_walk_line: 78 | if i[0] in line_dict: 79 | line_dict[i[0]].append(i[1]) 80 | else: 81 | line_dict[i[0]] = [i[1]] 82 | if i[1] in line_dict: 83 | line_dict[i[1]].append(i[0]) 84 | else: 85 | line_dict[i[1]] = [i[0]] 86 | 87 | # 选取next_node。开始扩展 88 | need_borden = [next_node] 89 | 90 | have_node = [need_borden[-1]] # 可以去的节点 91 | 92 | while need_borden: 93 | for p in need_borden: 94 | if p in line_dict: 95 | for t in line_dict[p]: 96 | if t not in have_node: 97 | have_node.append(t) 98 | need_borden.append(t) 99 | need_borden.remove(p) 100 | 101 | return len(have_node) != len(all_nodes) # 不相等说明剩余的部分不是连通的,说明当前节点和下一个节点构成的边是桥 102 | 103 | 104 | def solve(line): 105 | """ 106 | 对于可以一笔画出的问题,给出节点走的顺序 107 | :param line: 边的列表 108 | :return: 经过节点的顺序,也就是一笔画出的路径 109 | """ 110 | start_node, end_node, prime_node = judge_euler(line) 111 | node_dict = get_dict(line) 112 | 113 | if start_node == 'None': # 不能一笔画出 114 | return [], prime_node 115 | 116 | # 下面利用 117 | # 当前的节点 118 | current_node = start_node 119 | # 所有边的字典 120 | line_dict = {} 121 | for l in line: 122 | line_dict[tuple(l)] = 1 123 | # 走过的节点 124 | walk_node = [current_node] 125 | # 走过的边 126 | walk_line = [] 127 | 128 | # 利用Fleury算法求解路径 129 | while len(line_dict) != 0: 130 | # 下一个要去的节点,和当前的节点构成的边不能是桥 131 | can_go_node = [] 132 | bridge = 0 133 | for n in node_dict[current_node]: 134 | # 节点next和current_node构成的边没有走过 135 | min_node, max_node = sorted([n, current_node]) 136 | if (min_node, max_node) in line_dict: 137 | can_go_node.append(n) 138 | if not select_line(walk_line, current_node, n, line): # 优先选择不是桥的, 139 | current_node = n 140 | bridge = 1 141 | break 142 | # 都是桥。只好随便选择一个是桥的边 143 | if not bridge: 144 | for ee in can_go_node: 145 | current_node = ee 146 | # 要把这个边标记为走过 147 | min_node, max_node = sorted([walk_node[-1], current_node]) 148 | 149 | del line_dict[(min_node, max_node)] 150 | walk_line.append([min_node, max_node]) 151 | walk_node.append(current_node) 152 | 153 | return walk_node, prime_node 154 | 155 | 156 | def plot_solution(line, node): 157 | """ 158 | 根据点的位置以及边的连接情况,绘制谜题并给出解 159 | :param line: 点的位置信息 160 | :param node: 边的连接情况 161 | :return: 问题的解 162 | """ 163 | plt.ion() 164 | fig, (ax0, ax1) = plt.subplots(ncols=2) 165 | ax0.axis('off') 166 | ax1.axis('off') 167 | # 绘制谜题 168 | for n in line: 169 | o, s = n 170 | ax0.plot([node[o][0], node[s][0]], [node[o][1], node[s][1]], '-o', lw=2, c='#75664d', ms=8, mfc='#0c8918') 171 | for t in node: 172 | ax0.text(node[t][0], node[t][1], '$%d$' % t, fontsize=14, color='#bf3553') 173 | 174 | ax0.set_title('谜题,路径计算中') 175 | plt.pause(2) 176 | solution, prime_node = solve(line) 177 | 178 | if not solution: 179 | ax0.set_title('不能一笔画出') 180 | ax1.text(0.3, 0.5, '节点的连线个数是奇数的有\n%s' % prime_node, fontsize=13) 181 | else: 182 | # 开始绘制解 183 | ax0.set_title('谜题,路径添加中') 184 | ax1.set_title('点的经过顺序') 185 | for p in range(len(solution) - 1): 186 | o, s = solution[p], solution[p + 1] 187 | ax0.plot([node[o][0], node[s][0]], [node[o][1], node[s][1]], '-', lw=5, c='#1a94bc') 188 | # 显示具体的步骤 189 | grid = int(len(line) ** 0.5) + 1 190 | x = p % grid * (1 / grid) 191 | y = 0.9 - p // grid * (1 / grid) 192 | if p == 0: 193 | ax1.text(x, y, '始$%d->%d$' % (o, s), fontsize=10, color='#2d0c13') 194 | elif p == len(solution) - 2: 195 | ax1.text(x, y, '$->%d$终' % s, fontsize=10, color='#2d0c13') 196 | else: 197 | ax1.text(x, y, '$-->%d$' % s, fontsize=10, color='#2d0c13') 198 | plt.pause(0.6) 199 | ax0.set_title('谜题,路径添加完毕') 200 | plt.ioff() 201 | plt.show() 202 | 203 | 204 | # 主函数 205 | if __name__ == "__main__": 206 | # 在网站绘图导出的作图过程的html文件的绝对路径 207 | fig_html = r'C:\Users\GWT9\Desktop\9.html' 208 | line, node = r_f.decode_fig(fig_html) 209 | plot_solution(line, node) 210 | -------------------------------------------------------------------------------- /Seven Bridge/fig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/fig.png -------------------------------------------------------------------------------- /Seven Bridge/fig_progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/fig_progress.png -------------------------------------------------------------------------------- /Seven Bridge/read_fig_html.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 用户自己在网站https://www.geogebra.org/graphing绘制出谜题, 5 | # 绘制谜题时,不要自定义点的标识,用网站的默认值即可 6 | # 绘制完成后导出作图过程的html文件 7 | # 本程序实现读取html文件 8 | 9 | from bs4 import BeautifulSoup 10 | 11 | # 解析绘图过程的函数 12 | def decode_fig(html_file): 13 | """ 14 | 根据作图过程的html文件,获取解决谜题需要的信息 15 | :param html_file: 作图过程的html文件 16 | :return: 用于绘图的点的位置信息以及计算路径的边的信息 17 | """ 18 | node_dict = {} # 作图时的顶点为大写字母,此时利用数字, 键为顶点编号,值为坐标的位置 19 | line_list = [] # 存储连接的边,注意数字较小的在前面 20 | 21 | # 主要获取点的坐标信息以及边的连接信息 22 | with open(html_file, 'rb') as f: 23 | soup = BeautifulSoup(f.read(), 'html5lib') 24 | str_text = soup.select('td') 25 | 26 | for t in str_text: 27 | row_text = t.text.replace(' ', '') # 替换掉空格 28 | if 'Segment' in row_text: # 判断边 29 | # 因为Segment是固定的 30 | line_info = row_text[8:-1].split(',') # 获取边的2个顶点 31 | line_list.append(line_info) 32 | 33 | if '=' in row_text and '(' in row_text: # 判断点的位置 34 | equal_sign = row_text.index('=') # 首先获取等号的位置 35 | line_info = row_text[equal_sign+2: -1].split(',') # 获取点的坐标信息 36 | node_dict[row_text[:equal_sign]] = [float(x) for x in line_info] # 转变为小数 37 | 38 | all_nodes = sorted(list(set(sum(line_list, [])))) # 获取所有的不重复的节点 39 | alpha_digit_dict = {value: index + 1 for index, value in enumerate(all_nodes)} 40 | 41 | # 开始将边中顶点的字母标识变为数字 42 | digit_line_list = [] 43 | for l in line_list: 44 | c, d = l 45 | c_n, d_n = alpha_digit_dict[c], alpha_digit_dict[d] 46 | if c_n > d_n: 47 | digit_line_list.append([d_n, c_n]) 48 | else: 49 | digit_line_list.append([c_n, d_n]) 50 | 51 | # 将点的位置的字母标识同样变为数字标识 52 | digit_node_dict = {alpha_digit_dict[h]: node_dict[h] for h in node_dict} 53 | 54 | return digit_line_list, digit_node_dict 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Seven Bridge/readme.md: -------------------------------------------------------------------------------- 1 | # Seven Bridge 2 | 3 | 4 | * **构建谜题** 5 | 6 | + **在[网站](https://www.geogebra.org/graphing)绘出谜题** 7 | 8 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/fig.png) 9 | 10 | + **导出作图过程的html文件** 11 | 12 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/fig_progress.png) 13 | 14 | + **读取html文件的程序:[read_fig_html.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/read_fig_html.py)** 15 | 16 | * **程序** 17 | 18 | * **根据读取的信息,转变为谜题,并解决谜题的程序:[Seven_Bridge.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/Seven_Bridge.py)** 19 | 20 | 21 | * **结果图示** 22 | 23 | + **1. 欧拉通路,欧拉开迹,起始点和终点是连线数为奇数的2个点** 24 | 25 | + **网站绘制的图形** 26 | 27 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/y2.png) 28 | 29 | + **得到的解** 30 | 31 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/2.png) 32 | 33 | + **2. 欧拉回路,欧拉闭迹,所有点的连线个数都是偶数,起始点和终点是同一个点** 34 | 35 | + **网站绘制的图形** 36 | 37 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/y1.png) 38 | 39 | + **得到的解** 40 | 41 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/1.png) 42 | 43 | 44 | + **3. 不能一笔画出,连线为奇数的节点的个数不为0也不为2** 45 | 46 | + **网站绘制的图形** 47 | 48 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/0.png) 49 | 50 | + **得到的解** 51 | 52 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Seven%20Bridge/00.png) 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Seven Bridge/y1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/y1.png -------------------------------------------------------------------------------- /Seven Bridge/y2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Seven Bridge/y2.png -------------------------------------------------------------------------------- /Sudoku/Sudoku.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 引入库 5 | import pandas as pd 6 | import numpy as np 7 | import os 8 | 9 | # 存储数独题目的Excel文件路径 10 | DataPath = r'C:\Users\GWT9\Desktop\Sudoku' 11 | os.chdir(DataPath) 12 | # 文件名 13 | FileName = 'Sudoku.xlsx' 14 | # 宫数设置,根据题目宫数的不同可选择9,16,25(数字越大,解题速度越慢) 15 | sukoducount = 9 16 | # 读取文件 17 | ReadData = pd.read_excel(r'./%s' % FileName) 18 | # 数独题目 19 | NumData = ReadData.values 20 | # 打印数独题目 21 | print('号称最难的数独题目:\n', NumData) 22 | 23 | # 判断数独题目的完整性 24 | while len(NumData) < sukoducount: 25 | NumData = np.row_stack((NumData, [np.nan] * sukoducount)) 26 | 27 | 28 | # 根据格子的位置,计算该位置可以填写的数字集合 29 | def ProbNumber(hang, lie, data): 30 | # 行数据 31 | H = list(data[hang]) 32 | # 列数据 33 | L = list(data[:, lie]) 34 | # 宫数据 35 | G = [] 36 | sfang = int(len(data) ** 0.5) 37 | hh = hang // sfang 38 | ll = lie // sfang 39 | for ig in range(sfang): 40 | for gi in range(sfang): 41 | G.append(data[hh * sfang + ig, ll * sfang + gi]) 42 | # 行,列,宫已经包含的数字集合 43 | lal = list(H) + list(L) + G 44 | # 该空格可能选择的数字集合 45 | prob = [ip for ip in list(range(1, len(data) + 1)) if ip not in lal] 46 | return prob 47 | 48 | 49 | # 为题目中的空格计算填写数字的可能性,输出字典形式 50 | def ForK(data): 51 | Kdict = {} 52 | for ik in range(len(data)): 53 | for ki in range(len(data)): 54 | if np.isnan(data[ik, ki]): # 判断空格 55 | # 计算可填写数字的集合 56 | trans = ProbNumber(ik, ki, data) 57 | # 转换是为了让所有空格的jieti值中,只有唯一的一个最小值 58 | jieti = len(trans) * 10000000 + ik * 10000 + ki * 10 59 | Kdict['%s-%s' % (ik, ki)] = [jieti, len(trans), trans] 60 | return Kdict 61 | 62 | 63 | # 在字典中,寻找最小jieti值的空格,返回其位置与可以选取的数字集合 64 | def SeleM(ddict): 65 | Small = min(ddict.items(), key=lambda x: (x[1][0]))[0] 66 | # 空格位置 67 | weizhi = Small.split('-') 68 | # 行 69 | Ha = int(weizhi[0]) 70 | # 列 71 | Li = int(weizhi[1]) 72 | # 数字集合 73 | SE = ddict[Small][2] 74 | return Ha, Li, SE 75 | 76 | 77 | # 初始状态 78 | InitialState = {} 79 | InitialState[0] = NumData 80 | 81 | # 取值字典 82 | NumDict = {} 83 | 84 | # 定义全局变量 85 | global NU 86 | NU = 1 87 | 88 | # 状态转移 89 | # 记录栈中调用函数的次数 90 | minzhai = 0 91 | 92 | 93 | def TransFer(insta, numdi, n=0, c=minzhai): 94 | # 判断是否满足条件 95 | if len(ForK(insta[n])) == 0: 96 | global NU 97 | NU = 0 98 | return insta, numdi, n 99 | # 选择最小的 100 | mmi = SeleM(ForK(insta[n])) 101 | if c > 900: 102 | return insta, numdi, n 103 | 104 | if len(mmi[2]) == 0: 105 | del insta[n] 106 | c += 1 107 | return TransFer(insta, numdi, n - 1, c) 108 | else: 109 | middle = insta[n].copy() 110 | if n in numdi: 111 | if numdi[n] + 1 < len(mmi[2]): 112 | numdi[n] += 1 113 | middle[mmi[0], mmi[1]] = mmi[2][numdi[n]] 114 | n += 1 115 | insta[n] = middle.copy() 116 | c += 1 117 | return TransFer(insta, numdi, n, c) 118 | else: 119 | del numdi[n] 120 | del insta[n] 121 | c += 1 122 | return TransFer(insta, numdi, n - 1, c) 123 | else: 124 | numdi[n] = 0 125 | middle[mmi[0], mmi[1]] = mmi[2][0] 126 | n += 1 127 | insta[n] = middle.copy() 128 | c += 1 129 | return TransFer(insta, numdi, n, c) 130 | 131 | 132 | print('Working…') 133 | c_0 = TransFer(InitialState, NumDict) 134 | 135 | VAR_NAME = locals() 136 | 137 | 138 | # 最终的函数 139 | def Sudoku(): 140 | count = 1 141 | 142 | while NU != 0: 143 | VAR_NAME['c_%s' % count] = TransFer(eval('c_%s' % (count - 1))[0], eval('c_%s' % (count - 1))[1], 144 | eval('c_%s' % (count - 1))[2]) 145 | count += 1 146 | print('…') 147 | print('问题答案:\n', eval('c_%s' % (count - 1))[0][eval('c_%s' % (count - 1))[2]]) 148 | 149 | 150 | import time 151 | 152 | start = time.clock() 153 | Sudoku() 154 | print('用时%s秒' % (time.clock() - start)) -------------------------------------------------------------------------------- /Sudoku/Sudoku.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Sudoku/Sudoku.xlsx -------------------------------------------------------------------------------- /Sudoku/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Sudoku/a.png -------------------------------------------------------------------------------- /Sudoku/readme.md: -------------------------------------------------------------------------------- 1 | # Sudoku 2 | 3 | 4 | * **程序文件**:[Sudoku.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Sudoku/Sudoku.py) 5 | 6 | 7 | * **题目**:[Sudoku.xlsx](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Sudoku/Sudoku.xlsx) 8 | 9 | 10 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Sudoku/s.png) 11 | 12 | 13 | * **求解结果** 14 | 15 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Sudoku/a.png) 16 | -------------------------------------------------------------------------------- /Sudoku/s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Sudoku/s.png -------------------------------------------------------------------------------- /Tower of Hanoi/Hanoi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Tower of Hanoi/Hanoi.gif -------------------------------------------------------------------------------- /Tower of Hanoi/readme.md: -------------------------------------------------------------------------------- 1 | # Tower of Hanoi 2 | 3 | 4 | * **程序文件**:[Hanoi.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Tower%20of%20Hanoi/Hanoi.py) 5 | 6 | 7 | * **示意图**: 8 | 9 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Tower%20of%20Hanoi/Hanoi.gif) 10 | 11 | -------------------------------------------------------------------------------- /Traveling Salesman/34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/34.png -------------------------------------------------------------------------------- /Traveling Salesman/city_distance.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/city_distance.csv -------------------------------------------------------------------------------- /Traveling Salesman/city_sign.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/city_sign.csv -------------------------------------------------------------------------------- /Traveling Salesman/get_distance.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 读取城市的经纬度excel表格,然后利用公式计算得到经纬度之间的地球表面距离。 5 | # 并将城市的对应编号以及城市间的距离存储在文件中, 6 | 7 | from math import pi, cos, sin, asin 8 | import pandas as pd # 将结果存储到表格中 9 | 10 | # 城市的经纬度的文件 11 | city_lng_lat_file = r'C:\Users\GWT9\Desktop\城市经纬度.csv' 12 | # 存储距离的csv文件 13 | distance_csv = r'C:\Users\GWT9\Desktop\city_distance.csv' 14 | # 存储地址对应编号的csv文件 15 | sign_csv = r'C:\Users\GWT9\Desktop\city_sign.csv' 16 | 17 | 18 | # 读取文件,获取相应的经纬度 19 | def read_latlon(file=city_lng_lat_file): 20 | data = pd.read_csv(file, encoding='gbk') 21 | city_dict = {c: [lng, lat] for c, lng, lat in data.values} 22 | return city_dict 23 | 24 | 25 | # 根据经纬度获得直线距离 26 | def distance_lng_lat(add1, add2, r_earth=6378137): 27 | """ 28 | 根据两个地址的经纬度获取这2个地址之间的地球表面距离 29 | :param add1: 地址1的经纬度 30 | :param add2: 地址2的经纬度 31 | :param r_earth: 地球的平均半径米 32 | :return: 直线距离 33 | """ 34 | # 转为弧度 35 | add1_radian = [float(a) * pi / 180 for a in add1] 36 | add2_radian = [float(b) * pi / 180 for b in add2] 37 | 38 | # 计算经纬度之差 39 | d_lng = add1_radian[0] - add2_radian[0] 40 | d_lat = add1_radian[1] - add2_radian[1] 41 | 42 | # 计算距离 43 | sanj = sin(d_lat / 2) ** 2 + cos(add1_radian[1]) * cos(add2_radian[1]) * sin(d_lng / 2) ** 2 44 | dis = 2 * asin(sanj ** 0.5) 45 | return dis * r_earth 46 | 47 | 48 | # 获取城市之间距离,以及城市的编号信息,并存储到表格 49 | def save_distance(d_csv=distance_csv, s_csv=sign_csv): 50 | """ 51 | 获取地址列表中的任意2个地址之间的驾车距离,以及地址的对应的编号,并存储 52 | :param d_csv: 存储距离的csv文件 53 | :param s_csv: 存储地址编号的csv文件 54 | :return: 存到到csv文件中 55 | """ 56 | # 地址的经纬度字典 57 | add_dict = read_latlon() 58 | 59 | # 地址列表 60 | add_list = list(add_dict.keys()) 61 | 62 | # 便于后面的计算,将中文地址变为数字标识 63 | sorted_city_list = sorted(add_list) 64 | 65 | # 编号和城市的对应字典 66 | sign_city = pd.DataFrame() 67 | sign_city['中文'] = [s for s in sorted_city_list] 68 | sign_city['编号'] = list(range(len(sorted_city_list))) 69 | 70 | # 防止调用次数的限制,将得到距离存储到表格中 71 | city_distance = pd.DataFrame() 72 | city_distance['城市编号'] = list(range(len(sorted_city_list))) 73 | for i, j in enumerate(sorted_city_list): 74 | distance = [] 75 | for a, b in enumerate(sorted_city_list): 76 | if i >= a: 77 | distance.append(0) 78 | else: 79 | distance.append(distance_lng_lat(add_dict[j], add_dict[b])) 80 | city_distance[i] = distance 81 | 82 | city_distance.to_csv(d_csv, index=False, encoding="gb2312") 83 | sign_city.to_csv(s_csv, index=False, encoding="gb2312") 84 | return print('写入完毕') 85 | 86 | 87 | # 主函数 88 | if __name__ == "__main__": 89 | save_distance() 90 | 91 | -------------------------------------------------------------------------------- /Traveling Salesman/iter_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/iter_path.png -------------------------------------------------------------------------------- /Traveling Salesman/read_distance.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 读取存储的城市之间的距离以及城市对应的代码 5 | import pandas as pd 6 | 7 | # 存储距离的csv文件 8 | distance_csv = r'C:\Users\GWT9\Desktop\city_distance.csv' 9 | 10 | # 存储地址对应编号的csv文件 11 | sign_csv = r'C:\Users\GWT9\Desktop\city_sign.csv' 12 | 13 | 14 | # 读取距离的文件,并且用字典存储 15 | def read_distance(d_csv=distance_csv): 16 | """ 17 | 地址编号小的在前面,例如(2. 9):38283。编号为2的与编号为9的距离为38283米 18 | :param d_csv: 存储距离的文件 19 | :return: 地址编号对为键,距离为值的字典 20 | """ 21 | d_data = pd.read_csv(d_csv, encoding='gbk') # 因为有中文,需要设置encoding='gbk' 22 | d_dict = {} 23 | # 数据的列 24 | column = d_data.keys() 25 | for c in column[1:]: 26 | for s in d_data[column[0]]: 27 | dis = d_data[c][s] 28 | if dis != 0: 29 | d_dict[(int(c), s)] = dis 30 | return d_dict 31 | 32 | 33 | # 读取地址对应的城市,用于结果的展示 34 | def read_sign(d_csv=sign_csv): 35 | """ 36 | 获得中文地址和数字编号的对应字典,数字编号为键,中文地址为值 37 | :param d_csv: 存储对应关系的文件 38 | :return: 数字编号为键,中文地址为值的字典 39 | """ 40 | s_data = pd.read_csv(d_csv, encoding='gbk') # 因为有中文,需要设置encoding='gbk' 41 | s_dict = {sign: address for address, sign in s_data.values} 42 | return s_dict 43 | 44 | 45 | -------------------------------------------------------------------------------- /Traveling Salesman/readme.md: -------------------------------------------------------------------------------- 1 | # Traveling Salesman 2 | 3 | 4 | ### 文件说明 5 | 6 | * **1,读取城市的经纬度文件,根据公式计算城市间的距离** 7 | 8 | + **34城市的经纬度文件:[城市经纬度.csv](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/城市经纬度.csv)** 9 | 10 | + **城市之间的距离csv文件:[city_distance.csv](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/city_distance.csv)** 11 | 12 | + **城市的数字对应csv文件:[city_sign.csv](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/city_sign.csv)** 13 | 14 | + **获得城市间距离以及城市编号的程序:[get_distance.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/get_distance.py)** 15 | 16 | + **读取距离以及城市编号文件的程序:[read_distance.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/read_distance.py)** 17 | 18 | 19 | * **2,在地图上展示结果的程序** 20 | 21 | + **地图展示的程序:[show_result.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/show_result.py)** 22 | 23 | 24 | * **3,遗传函数以及最终结果展示的程序** 25 | 26 | + **主程序:[genetic_algorithm_tsp_greedy.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/genetic_algorithm_tsp_greedy.py)** 27 | 28 | 29 | * **4,结果展示** 30 | 31 | + **迭代结果** 32 | 33 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/iter_path.png) 34 | 35 | + **路径动态展示** 36 | 37 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/tsp.gif) 38 | 39 | 40 | + **最终的路径** 41 | 42 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/Traveling%20Salesman/34.png) 43 | 44 | -------------------------------------------------------------------------------- /Traveling Salesman/show_result.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | 4 | # 根据利用遗传算法得到的结果,进行展示 5 | 6 | 7 | from pyecharts import GeoLines, Style 8 | from pyecharts_snapshot.main import make_a_snapshot 9 | 10 | 11 | style = Style( 12 | title_pos="center", 13 | width=600, 14 | height=480, 15 | background_color="#d8e3e7", 16 | title_text_size=15, 17 | subtitle_text_size=12, 18 | title_color='#134567', 19 | subtitle_color='#134567', 20 | ) 21 | 22 | style_geo = style.add( 23 | is_label_show=True, 24 | label_formatter="{b}", 25 | is_legend_show=True, 26 | label_text_size=8, 27 | label_text_color='#000000', 28 | line_width=2, 29 | label_pos="inside", 30 | label_color=['#2474b5', '#e26674'], 31 | geo_effect_symbolsize=0, 32 | line_opacity=1, 33 | geo_normal_color="#e2e1e4", 34 | symbol_size=10, 35 | border_color='#7a7374', 36 | ) 37 | 38 | 39 | def create_charts(data_path, path_html, path_png, length): 40 | charts = GeoLines("TSP问题:全国34城市为例", '路径:%.3fkm' % (length / 1000), **style.init_style) 41 | charts.add('', data_path, **style_geo) 42 | charts.render(path_html) 43 | make_a_snapshot(path_html, path_png) 44 | return print('绘图完毕') 45 | -------------------------------------------------------------------------------- /Traveling Salesman/tsp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/tsp.gif -------------------------------------------------------------------------------- /Traveling Salesman/城市经纬度.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/Traveling Salesman/城市经纬度.csv -------------------------------------------------------------------------------- /bezier/Bezier_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_2.gif -------------------------------------------------------------------------------- /bezier/Bezier_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_3.gif -------------------------------------------------------------------------------- /bezier/Bezier_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_4.gif -------------------------------------------------------------------------------- /bezier/Bezier_false.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_false.gif -------------------------------------------------------------------------------- /bezier/Bezier_more_false.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_more_false.gif -------------------------------------------------------------------------------- /bezier/Bezier_more_true.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_more_true.gif -------------------------------------------------------------------------------- /bezier/Bezier_n.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_n.gif -------------------------------------------------------------------------------- /bezier/Bezier_true.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anfany/Funny-Math-Problem-by-Python3/fd74551209b1fad0113bf018c35f5e6068cc0e5f/bezier/Bezier_true.gif -------------------------------------------------------------------------------- /bezier/bezier_curve.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3.8.8 2 | # author:Anfany 3 | # datetime:2021/4/2 16:15 4 | 5 | # N个控制点的贝塞尔曲线的绘制:递归法和直接法。曲线只经过初始点和锚点 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | import matplotlib.animation as animation 10 | import matplotlib.cm as cm 11 | from scipy.special import comb # 直接法 12 | # 显示中文 13 | plt.rcParams['font.sans-serif'] = ['SimHei'] 14 | 15 | 16 | class BEZIER: 17 | 18 | def __init__(self, N, pointlist=None): 19 | self.n = N # 最小值为2 20 | self.pl = pointlist # 如果为None,则随机选择N个点。如果不为空,则以此列表中的个数为准 21 | 22 | self.t_tap = 0.008 23 | self.t_list = np.arange(0, 1, self.t_tap) 24 | 25 | self.generate_point() 26 | 27 | # 贝塞尔曲线的点 28 | self.bezier_list = [[], []] 29 | 30 | self.fig, self.ax = plt.subplots(figsize=(8, 6)) 31 | self.fig.subplots_adjust(bottom=0.2) 32 | self.clist = self.get_color_list() 33 | 34 | # 不同阶的颜色 35 | def get_color_list(self): 36 | color_list = [] 37 | for i in range(self.n): 38 | color_list.append(cm.rainbow(i / self.n)) 39 | return color_list[::-1] 40 | 41 | # 产生随机点:横纵坐标在-5到5 42 | def generate_point(self): 43 | def gp(tap=10): 44 | xp = tap * np.random.random(self.n) - tap / 2 45 | yp = tap * np.random.random(self.n) - tap / 2 46 | return [np.array([i, j]) for i, j in zip(xp, yp)] 47 | 48 | if self.pl is None: 49 | self.pl = gp() 50 | else: 51 | self.pl = [np.array(h) for h in self.pl] 52 | self.n = len(self.pl) 53 | 54 | # 贝塞尔曲线方程:根据t的变化展示不同的图像状态 55 | def b(self, t): 56 | self.ax.clear() # 清空已存在的图像 57 | # 隐藏边 58 | self.ax.axis('off') 59 | self.ax.set_title('t=%.4ss' % str(t), fontsize=15) 60 | # 绘制原始点 61 | for din, p in enumerate(self.pl): 62 | if din == 0: 63 | self.ax.text(p[0], p[1], '$P_{%s}$' % din, fontsize=13) 64 | self.ax.scatter(p[0], p[1], label='$P_{0}$初始点', s=50, color='tab:green') 65 | elif din == self.n - 1: 66 | self.ax.text(p[0], p[1], '$P_{%s}$' % din, fontsize=13) 67 | self.ax.scatter(p[0], p[1], label='$P_{%s}$锚点' % din, s=50, color='tab:red') 68 | else: 69 | self.ax.text(p[0], p[1], '$P_{%s}$' % din, fontsize=13) 70 | if din == self.n - 2: 71 | self.ax.scatter(p[0], p[1], label='$P_{1}$至$P_{%s}$控制点' % (self.n - 2), s=45, 72 | color='gray') 73 | else: 74 | self.ax.scatter(p[0], p[1], color='gray', s=45) 75 | # 绘制原始点之间的连接线 76 | xp = [op[0] for op in self.pl] 77 | yp = [op[1] for op in self.pl] 78 | self.ax.plot(xp, yp, '-', lw=2, color=self.clist[0]) 79 | 80 | # 开始绘制多阶直线 81 | line_list = self.pl 82 | while len(line_list) > 2: 83 | new_list = [] 84 | for kp, kz in zip(line_list[:-1], line_list[1:]): 85 | ss = np.float64(kp + t * (kz - kp)) 86 | new_list.append(ss) 87 | 88 | xp = [op[0] for op in new_list] 89 | yp = [op[1] for op in new_list] 90 | self.ax.plot(xp, yp, '-', lw=2, marker='.', color=self.clist[self.n - len(new_list)], 91 | markerfacecolor=self.clist[self.n - len(new_list)], markersize=15) 92 | line_list = new_list 93 | 94 | # 添加点 95 | x, y = np.float64(line_list[0] + t * (line_list[1] - line_list[0])) 96 | self.bezier_list[0].append(x) 97 | self.bezier_list[1].append(y) 98 | self.ax.plot(self.bezier_list[0], self.bezier_list[1], lw=4, color=self.clist[-1], 99 | label=r'$de Casteljau$算法-$B\acute{e}zierCurve$') 100 | self.ax.scatter(x, y, s=50, color=self.clist[-1]) 101 | 102 | # 根据直接法绘制的 103 | forward_point = [] 104 | for t in self.t_list: 105 | sum_p = np.array([0., 0.]) 106 | for plin, plva in enumerate(self.pl): 107 | sum_p += comb(self.n-1, plin) * plva * np.power(1-t, self.n-1-plin) * np.power(t, plin) 108 | 109 | forward_point.append(sum_p) 110 | xpll = [op[0] for op in forward_point] 111 | ypll = [op[1] for op in forward_point] 112 | self.ax.plot(xpll, ypll, '--', lw=2, label=r'直接法-$B\acute{e}zierCurve$', color='gray') 113 | 114 | # 显示图例 115 | self.ax.legend(fontsize=13, ncol=2, framealpha=0.1, loc=2, bbox_to_anchor=(0.0, 0.0)) 116 | 117 | # 动态图实现 118 | def auto_fig(self): 119 | animator = animation.FuncAnimation(self.fig, self.b, self.t_list, interval=90) 120 | # 可将动图输出为gif或者视频mp4 121 | animator.save('Bezier_3.gif') 122 | 123 | 124 | # 实例1:陀螺 125 | Example1 = [[0.82, 5.88], [4.76, 6.94], [8.94, 6.32], [12.46, 3.74], 126 | [13.84, -1.52], [11.04, -4.76], 127 | [7.34, -5.74], [1.24, -4.12], [0.38, -0.26], [1.56, 4.84], 128 | [7.34, 4.98], [11.86, 1.24], 129 | [10.96, -2.84], [5.56, -3.8], [2, -1], [3.46, 3.74]] 130 | 131 | if __name__ == '__main__': 132 | 133 | bezier = BEZIER(4, [[-6.7,1.4],[-3.92,2.52],[-5.34,-1.52],[-1.34,-0.1]]) 134 | bezier.auto_fig() 135 | -------------------------------------------------------------------------------- /bezier/bezier_point.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python3.8.8 2 | # author:Anfany 3 | # datetime:2021/4/8 15:31 4 | 5 | # 经过N个控制点的贝塞尔曲线的绘制 6 | 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | import matplotlib.animation as animation 10 | import matplotlib.cm as cm 11 | from scipy.special import comb # 直接法 12 | 13 | # 显示中文 14 | plt.rcParams['font.sans-serif'] = ['SimHei'] 15 | 16 | 17 | class BEZIERPRO: 18 | 19 | def __init__(self, N, pointlist=None, closed=True): 20 | self.n = N # 最小值为2 21 | self.pl = pointlist # 如果为None,则随机选择N个点。如果不为空,则以此列表中的个数为准 22 | self.c = closed # 曲线是否封闭 23 | 24 | self.t_tap = 0.008 25 | self.t_list = np.arange(0, 1, self.t_tap) 26 | self.generate_point() 27 | 28 | # 新的控制点 29 | self.control_p, self.new_pl = self.get_point() 30 | self.n_list = [len(k) for k in self.new_pl] 31 | # 贝塞尔曲线的点 32 | self.bezier_list = {} 33 | 34 | self.fig, self.ax = plt.subplots(figsize=(8, 6)) 35 | self.fig.subplots_adjust(bottom=0.2) 36 | self.clist = self.get_color_list() 37 | 38 | # 不同阶的颜色 39 | def get_color_list(self): 40 | colorlist = {} 41 | for j in range(len(self.n_list)): 42 | color_list = [] 43 | for i in range(self.n_list[j]): 44 | color_list.append(cm.rainbow(i / self.n_list[j])) 45 | colorlist[j] = color_list[::-1] 46 | return colorlist 47 | 48 | # 产生随机点:横纵坐标在-5到5 49 | def generate_point(self): 50 | def gp(tap=10): 51 | xp = tap * np.random.random(self.n) - tap / 2 52 | yp = tap * np.random.random(self.n) - tap / 2 53 | pointlist = [np.array([i, j]) for i, j in zip(xp, yp)] 54 | return pointlist 55 | 56 | if self.pl is None: 57 | self.pl = gp() 58 | else: 59 | self.pl = [np.array(h) for h in self.pl] 60 | self.n = len(self.pl) 61 | 62 | # 根据给定的点生成虚拟的控制点 63 | def get_point(self): 64 | if list(self.pl[0]) != list(self.pl[-1]): 65 | self.pl += list(self.pl[:2]) 66 | control_point = [] 67 | for pin, pva in enumerate(self.pl[:-2]): 68 | middle_1 = (pva + self.pl[pin + 1]) / 2 69 | middle_2 = (self.pl[pin + 1] + self.pl[pin + 2]) / 2 70 | h1 = (pva[0] - self.pl[pin + 1][0]) ** 2 + (pva[1] - self.pl[pin + 1][1]) ** 2 71 | h2 = (self.pl[pin + 1][0] - self.pl[pin + 2][0]) ** 2 + (self.pl[pin + 1][1] - self.pl[pin + 2][1]) ** 2 72 | h = (h1 / h2) ** 0.5 73 | middle_d = (middle_1 + h * middle_2) / (1 + h) 74 | # 根据平行四边形对角线互相平分 75 | no_1 = self.pl[pin + 1] + middle_1 - middle_d 76 | no_2 = self.pl[pin + 1] + middle_2 - middle_d 77 | 78 | control_point.append(no_1) 79 | control_point.append(no_2) 80 | 81 | # 根据控制点 形成多条贝塞尔曲线 82 | if self.c: 83 | new_control = [control_point[-1]] + control_point[:-1] 84 | sign = 0 85 | else: 86 | new_control = [control_point[-1]] + control_point[:-3] 87 | sign = 1 88 | new_pl = [] 89 | for kinp, kvap in enumerate(self.pl[:(-2 - sign)]): 90 | cc = [kvap, new_control[2 * kinp], new_control[2 * kinp + 1], self.pl[kinp + 1]] 91 | new_pl.append(cc) 92 | 93 | return new_control, new_pl 94 | 95 | def b_m(self, t): 96 | self.ax.clear() # 清空已存在的图像 97 | # 隐藏边 98 | self.ax.axis('off') 99 | self.ax.set_title('t=%.4ss' % str(t), fontsize=15) 100 | # 绘制顶点 101 | for pdin, pp in enumerate(self.pl[:-1]): 102 | self.ax.text(pp[0], pp[1], '$P_{%s}$' % pdin, fontsize=13) 103 | if pdin == 0: 104 | self.ax.scatter(pp[0], pp[1], label='$P$顶点', s=50, color='tab:green') 105 | else: 106 | self.ax.scatter(pp[0], pp[1], s=50, color='tab:green') 107 | # 绘制新添加的控制点 108 | for pdin, pp in enumerate(self.control_p): 109 | self.ax.text(pp[0], pp[1], '$N_{%s}$' % pdin, fontsize=13) 110 | if pdin == 0: 111 | self.ax.scatter(pp[0], pp[1], marker='^', label='$N$控制点', s=30, color='tab:red') 112 | else: 113 | self.ax.scatter(pp[0], pp[1], marker='^', s=30, color='tab:red') 114 | 115 | # 绘制多个控制组的原始点 116 | for pdin, pp in enumerate(self.new_pl): 117 | # 开始绘制多阶直线 118 | line_list = pp 119 | while len(line_list) > 2: 120 | new_list = [] 121 | for kp, kz in zip(line_list[:-1], line_list[1:]): 122 | ss = np.float64(kp + t * (kz - kp)) 123 | new_list.append(ss) 124 | # 中间的线 125 | xp = [op[0] for op in new_list] 126 | yp = [op[1] for op in new_list] 127 | self.ax.plot(xp, yp, '-', lw=2, marker='.', color=self.clist[pdin][self.n_list[pdin] - len(new_list)], 128 | markerfacecolor=self.clist[pdin][self.n_list[pdin] - len(new_list)], markersize=15) 129 | line_list = new_list 130 | 131 | # 添加点 132 | x, y = np.float64(line_list[0] + t * (line_list[1] - line_list[0])) 133 | 134 | if pdin in self.bezier_list: 135 | self.bezier_list[pdin][0].append(x) 136 | self.bezier_list[pdin][1].append(y) 137 | else: 138 | self.bezier_list[pdin] = [[x], [y]] 139 | if pdin == 0: 140 | self.ax.plot(self.bezier_list[pdin][0], self.bezier_list[pdin][1], lw=4, color=self.clist[pdin][-1], 141 | label=r'$de Casteljau$算法-$B\acute{e}zierCurve$') 142 | else: 143 | self.ax.plot(self.bezier_list[pdin][0], self.bezier_list[pdin][1], lw=4, color=self.clist[pdin][-1]) 144 | 145 | self.ax.scatter(x, y, s=50, color=self.clist[pdin][-1]) 146 | 147 | # 根据直接法绘制的 148 | for pdin, pp in enumerate(self.new_pl): 149 | forward_point = [] 150 | for t in self.t_list: 151 | sum_p = np.array([0., 0.]) 152 | for plin, plva in enumerate(pp): 153 | sum_p += comb(3, plin) * plva * np.power(1 - t, 3 - plin) * np.power(t, plin) 154 | forward_point.append(sum_p) 155 | xpll = [op[0] for op in forward_point] 156 | ypll = [op[1] for op in forward_point] 157 | if pdin == 0: 158 | self.ax.plot(xpll, ypll, '--', lw=2, label=r'直接法-$B\acute{e}zierCurve$', color='gray') 159 | else: 160 | self.ax.plot(xpll, ypll, '--', lw=2, color='gray') 161 | 162 | self.ax.legend(fontsize=13, ncol=2, framealpha=0.1, loc=2, bbox_to_anchor=(0.0, 0.0)) 163 | 164 | # 动态图实现 165 | def auto_fig(self): 166 | animator = animation.FuncAnimation(self.fig, self.b_m, self.t_list, interval=90) 167 | # 可将动图输出为gif或者视频mp4 168 | animator.save('Bezier_IU.gif') 169 | 170 | 171 | # 实例1:AF 172 | AF = [[-7.88, -0.26], [-6.16, 4.2], [-4.76, -0.06], [-6.08, 0.46], 173 | [-6.16, 1.2], [-3.42, 3.98], [-2, 4], [-1.18, 4], 174 | [-3.36, 4.28], [-3.32, -2.62], [-3.26, 1.36], [-1.1, 1.42]] 175 | 176 | # 实例2:IU 177 | IU = [[5, -7], [5, -3], [5.6, -2.9], [5.6, -6.5], [8.4, -6.5], [7.58, -6.18], [6.78, -5.59], 178 | [6.42, -4.8], [6.6, -4], [7.21, -3.42], [7.78, -3.62], [8.36, -4], [8.8, -3.62], [9.36, -3.4], 179 | [10, -4], [10.2, -4.79], [9.8, -5.6], [9.2, -6.17], [8.4, -6.5], [10.8, -6.57], [11.01, -6], 180 | [11, -4.77], [11, -3], [11.38, -3], [11.38, -4.77], [11.42, -6], [11.41, -6.6], [12.6, -6.6], 181 | [12.6, -3], [13, -3], [13, -6.62], [13, -7], [11, -7], [9, -7], [7, -7]] 182 | 183 | if __name__ == '__main__': 184 | bezier = BEZIERPRO(4, [[-0.56,1.96],[-6.7,0.2],[-5.02,-4.36],[-2.2,-3.18]], False) 185 | bezier.auto_fig() 186 | -------------------------------------------------------------------------------- /bezier/readme.md: -------------------------------------------------------------------------------- 1 | ### 贝塞尔曲线 2 | 3 | 4 | ### 一、根据控制点数或者给定的控制点:[bezier_curve.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/bezier_curve.py) 5 | 6 | 7 | + 两个点 8 | 9 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_2.gif) 10 | 11 | + 三个点 12 | 13 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_3.gif) 14 | 15 | 16 | + 四个点 17 | 18 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_4.gif) 19 | 20 | + 更多点 21 | 22 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_n.gif) 23 | 24 | ### 二、贝塞尔曲线应用:[bezier_point.py](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/bezier_point.py) 25 | 26 | + 封闭 27 | 28 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_true.gif) 29 | 30 | 31 | + 不封闭 32 | 33 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_false.gif) 34 | 35 | + 更多示例 36 | 37 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_more_false.gif) 38 | 39 | 40 | ![image](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/bezier/Bezier_more_true.gif) 41 | -------------------------------------------------------------------------------- /lifegame/example_lifegame.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | # 制作生命游戏震荡态的代码 6 | from pylab import * 7 | from matplotlib.colors import LinearSegmentedColormap 8 | # 制作gif 9 | import imageio # 引入合成gif的库 10 | mpl.rcParams['font.sans-serif'] = ['SimHei'] 11 | 12 | 13 | class LifeGame: 14 | def __init__(self, n, m, start_life_list): 15 | self.n = n 16 | self.m = m 17 | self.life_c = '#1a6840' # 活细胞的颜色 18 | self.dead_c = '#f3f5e7' # 死细胞的颜色 19 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 20 | self.dead_n = 1 21 | 22 | # 开始的活细胞位置列表 23 | self.start_life_list = start_life_list 24 | # 开始局面 25 | self.initial_matrix = self.create_init_life() 26 | 27 | # 创建初始的情况 28 | def create_init_life(self): 29 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 30 | for jj in self.start_life_list: 31 | cow = jj // self.m 32 | col = jj % self.m 33 | init_matrix[cow][col] = self.life_n 34 | return init_matrix 35 | 36 | # 获取相邻的细胞 37 | def get_round(self, r, c, lifematrix): 38 | number_list = [] 39 | for i in range(max(0, r - 1), min(self.n, r + 2)): 40 | for j in range(max(0, c - 1), min(self.m, c + 2)): 41 | if i != r or j != c: 42 | number_list.append(lifematrix[i][j]) 43 | return number_list 44 | 45 | # 根据规则进行一代代的变化 46 | def create_by_rule(self): 47 | copy_matrix = self.initial_matrix.copy() 48 | for row in range(self.n): 49 | for column in range(self.m): 50 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 51 | if self.initial_matrix[row][column] == self.life_n: 52 | if l_count < 2 or l_count >= 4: 53 | copy_matrix[row][column] = self.dead_n 54 | else: 55 | if l_count == 3: 56 | copy_matrix[row][column] = self.life_n 57 | self.initial_matrix = copy_matrix.copy() 58 | return self.initial_matrix 59 | 60 | 61 | # 生成随机开局的活细胞位置列表 62 | def start_random_life(n, m, p=0.375): 63 | sign_list = np.random.choice(np.arange(n * m), 64 | int(n * m * p), replace=False) 65 | return sign_list 66 | 67 | 68 | # 周期为10 69 | # start_life_list, n, m, t, sign = ([51, 52, 58, 59, 88, 89, 95, 96, 237, 238, 242, 243, 273, 274, 276, 278, 280, 281, 312, 313, 315, 316, 347, 348, 350, 352, 354, 355, 385, 386, 390, 391, 422, 428, 494, 495, 503, 504, 519, 520, 525, 527, 531, 532, 540, 541, 545, 547, 552, 553, 556, 557, 561, 562, 564, 565, 566, 580, 581, 582, 584, 585, 589, 590, 598, 600, 602, 618, 620, 622, 636, 637, 638, 656, 657, 658, 710, 711, 712, 730, 731, 732, 746, 748, 750, 766, 768, 770, 778, 779, 783, 784, 786, 787, 788, 802, 803, 804, 806, 807, 811, 812, 815, 816, 821, 823, 827, 828, 836, 837, 841, 843, 848, 849, 864, 865, 873, 874, 940, 946, 977, 978, 982, 983, 1013, 1014, 1016, 1018, 1020, 1021, 1052, 1053, 1055, 1056, 1087, 1088, 1090, 1092, 1094, 1095, 1125, 1126, 1130, 1131, 1272, 1273, 1279, 1280, 1309, 1310, 1316, 1317], 37, 37, 10, 1) 70 | 71 | # # 周期为15 72 | # start_life_list, n, m, t, sign = ([95, 97, 105, 107, 121, 122, 123, 125, 126, 134, 135, 137, 138, 139, 149, 151, 152, 154, 164, 166, 167, 169, 178, 179, 197, 198, 207, 208, 226, 227, 235, 244, 245, 247, 248, 257, 265, 266, 274, 276, 284, 285, 293, 294, 301, 303, 305, 307, 314, 315, 329, 331, 335, 337, 356, 359, 365, 368, 385, 386, 387, 395, 396, 397, 443, 444, 445, 453, 454, 455, 472, 475, 481, 484, 503, 505, 509, 511, 525, 526, 533, 535, 537, 539, 546, 547, 555, 556, 564, 566, 574, 575, 583, 592, 593, 595, 596, 605, 613, 614, 632, 633, 642, 643, 661, 662, 671, 673, 674, 676, 686, 688, 689, 691, 701, 702, 703, 705, 706, 714, 715, 717, 718, 719, 733, 735, 743, 745], 29, 29, 15, 1) 73 | 74 | # # 周期为37 75 | # start_life_list, n, m, t, sign = ([68, 117, 118, 119, 169, 217, 218, 267, 268, 269, 270, 271, 317, 318, 319, 320, 321, 327, 328, 365, 370, 376, 377, 509, 517, 519, 557, 558, 564, 565, 566, 567, 568, 604, 612, 615, 617, 618, 619, 653, 655, 661, 662, 663, 667, 669, 692, 693, 711, 712, 713, 719, 741, 742, 749, 762, 764, 767, 797, 799, 803, 804, 810, 811, 813, 815, 819, 820, 845, 849, 852, 853, 855, 856, 860, 861, 894, 895, 901, 902, 917, 919, 941, 942, 943, 946, 947, 954, 955, 961, 962, 963, 968, 969, 977, 978, 991, 997, 1003, 1005, 1010, 1011, 1012, 1026, 1035, 1036, 1039, 1040, 1041, 1043, 1044, 1045, 1046, 1073, 1075, 1083, 1084, 1089, 1091, 1092, 1094, 1101, 1103, 1109, 1119, 1121, 1122, 1123, 1132, 1133, 1138, 1140, 1141, 1147, 1149, 1150, 1152, 1153, 1155, 1156, 1158, 1169, 1170, 1181, 1182, 1188, 1189, 1195, 1205, 1211, 1212, 1218, 1219, 1230, 1231, 1242, 1244, 1245, 1247, 1248, 1250, 1251, 1253, 1259, 1260, 1262, 1267, 1268, 1277, 1278, 1279, 1281, 1291, 1297, 1299, 1306, 1308, 1309, 1311, 1316, 1317, 1325, 1327, 1354, 1355, 1356, 1357, 1359, 1360, 1361, 1364, 1365, 1374, 1388, 1389, 1390, 1395, 1397, 1403, 1409, 1422, 1423, 1431, 1432, 1437, 1438, 1439, 1445, 1446, 1453, 1454, 1457, 1458, 1459, 1481, 1483, 1498, 1499, 1505, 1506, 1539, 1540, 1544, 1545, 1547, 1548, 1551, 1555, 1580, 1581, 1585, 1587, 1589, 1590, 1596, 1597, 1601, 1603, 1633, 1636, 1638, 1651, 1658, 1659, 1681, 1687, 1688, 1689, 1707, 1708, 1731, 1733, 1737, 1738, 1739, 1745, 1747, 1781, 1782, 1783, 1785, 1788, 1796, 1832, 1833, 1834, 1835, 1836, 1842, 1843, 1881, 1883, 1891, 2023, 2024, 2030, 2035, 2072, 2073, 2079, 2080, 2081, 2082, 2083, 2129, 2130, 2131, 2132, 2133, 2182, 2183, 2231, 2281, 2282, 2283, 2332], 49, 49, 37, 1) 76 | 77 | 78 | # 初始对角线活细胞 79 | n, m = 43, 43 80 | start_life_list, n, m, t, sign = ([i * n + j for i, j in zip(range(n), range(m))] + 81 | [i * m + j for i, j in zip(range(n-1, -1, -1), range(m))], n, m, 75, 0) 82 | 83 | 84 | lg = LifeGame(n, m, start_life_list) 85 | 86 | 87 | def plot_life_game(data, figname, t, sign): 88 | m, n = data.shape 89 | # 绘图 90 | fig, ax = plt.subplots() 91 | # 设置主刻度 92 | ax.xaxis.set_major_locator(MultipleLocator(1)) 93 | ax.yaxis.set_major_locator(MultipleLocator(1)) 94 | # 设置网格线 95 | ax.xaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 96 | ax.yaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 97 | # 设置刻度,保证对齐 98 | ax.set_xticks(list(np.linspace(-0.5, lg.m - 1.5, lg.m))) 99 | ax.set_yticks(list(np.linspace(-0.5, lg.n - 1.5, lg.n))) 100 | # 设置热力图数值对应的颜色 101 | my_colormap = LinearSegmentedColormap.from_list("颜色匹配", [lg.life_c, lg.dead_c] if 102 | lg.life_n < lg.dead_n else[lg.dead_c, lg.life_c]) 103 | # 热力图 104 | ax.imshow(data, cmap=my_colormap) 105 | # 不显示刻度标签 106 | plt.setp(ax.get_xticklabels(), visible=False) 107 | plt.setp(ax.get_yticklabels(), visible=False) 108 | # 设置主刻度线 109 | tick_params(which='major', length=0) 110 | # 图形四个边的颜色和粗度 111 | for a in ['bottom', 'top', 'left', 'right']: 112 | ax.spines[a].set_linewidth(1.1) 113 | ax.spines[a].set_color('#ccccd6') 114 | 115 | alignment = {'horizontalalignment': 'center', 'verticalalignment': 'baseline'} 116 | if sign: 117 | plt.title('周期为%d' % t) 118 | else: 119 | plt.title('%d*%d的网格:%d步趋于稳定, 当前%d步' % (m, n, t, figname+1)) 120 | 121 | print('图片保存完成', figname) 122 | plt.savefig('%s.jpg' % figname, bbox_inches='tight') 123 | plt.close() 124 | 125 | 126 | # 制作震荡态gif的代码 127 | namelist = [] 128 | for i in range(t): 129 | plot_life_game(lg.initial_matrix, i, t, sign) 130 | lg.create_by_rule() 131 | namelist.append('%d.jpg' % i) 132 | 133 | 134 | # 合成一个gif图片 135 | def create_gif(image_list, gif_name=r'C:\Users\GWT9\Desktop\anfany.gif'): 136 | frames = [] 137 | for image_name in image_list: 138 | frames.append(imageio.imread(image_name)) 139 | imageio.mimsave(gif_name, frames, 'GIF', duration=0.9) # duration控制动态图中每张图片的显示时间 140 | 141 | 142 | create_gif(namelist) 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /lifegame/find_relation.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | import numpy as np 6 | import pandas as pd 7 | 8 | class LifeGame: 9 | def __init__(self, n, m, start_life_list): 10 | self.n = n 11 | self.m = m 12 | self.life_c = '#1a6840' # 活细胞的颜色 13 | self.dead_c = '#f3f5e7' # 死细胞的颜色 14 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 15 | self.dead_n = 1 16 | 17 | # 开始的活细胞位置列表 18 | self.start_life_list = start_life_list 19 | # 开始局面 20 | self.initial_matrix = self.create_init_life() 21 | 22 | # 创建初始的情况 23 | def create_init_life(self): 24 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 25 | for jj in self.start_life_list: 26 | cow = jj // self.m 27 | col = jj % self.m 28 | init_matrix[cow][col] = self.life_n 29 | return init_matrix 30 | 31 | # 获取相邻的细胞 32 | def get_round(self, r, c, lifematrix): 33 | number_list = [] 34 | for i in range(max(0, r - 1), min(self.n, r + 2)): 35 | for j in range(max(0, c - 1), min(self.m, c + 2)): 36 | if i != r or j != c: 37 | number_list.append(lifematrix[i][j]) 38 | return number_list 39 | 40 | # 根据规则进行一代代的变化 41 | def create_by_rule(self): 42 | copy_matrix = self.initial_matrix.copy() 43 | for row in range(self.n): 44 | for column in range(self.m): 45 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 46 | if self.initial_matrix[row][column] == self.life_n: 47 | if l_count < 2 or l_count >= 4: 48 | copy_matrix[row][column] = self.dead_n 49 | else: 50 | if l_count == 3: 51 | copy_matrix[row][column] = self.life_n 52 | self.initial_matrix = copy_matrix.copy() 53 | return self.initial_matrix 54 | 55 | 56 | # 初始的局面为对角线活细胞,不同的正边形网格数和趋于稳定的步数的对应关系 57 | # 最终趋于稳定的 58 | still_grid = [] 59 | still_steps = [] 60 | # 经过一定步数变为周期的 61 | period_grid = [] 62 | period_steps = [] 63 | period_counts = [] 64 | 65 | for k in range(3, 101): 66 | start_life_list = [i * k + j for i, j in zip(range(k), range(k))] + \ 67 | [i * k + j for i, j in zip(range(k - 1, -1, -1), range(k))] 68 | 69 | lg = LifeGame(k, k, start_life_list) 70 | sign_s = 0 71 | sign_p = 0 72 | gu = [] 73 | num = '1' 74 | while 1: 75 | first_matrix = list(lg.initial_matrix.copy().flatten()) 76 | gu.append(first_matrix) 77 | 78 | lg.create_by_rule() 79 | sign_s += 1 80 | 81 | two_matrix = list(lg.initial_matrix.copy().flatten()) 82 | 83 | if two_matrix in gu: 84 | if two_matrix == first_matrix: 85 | break 86 | else: 87 | sign_p = 1 88 | num = gu.index(two_matrix) 89 | break 90 | 91 | if not sign_p: 92 | print('网格为%d, 趋于稳定,%s' % (k, sign_s)) 93 | else: 94 | print('网格为%d, 经过%s步变为,周期性,%s' % (k, num, sign_s - num)) 95 | 96 | # 将结果存储 97 | if sign_p: 98 | # 经过一定步数变为周期的 99 | period_grid.append(k) 100 | period_steps.append(num) 101 | period_counts.append(sign_s - num) 102 | else: 103 | still_grid.append(k) 104 | still_steps.append(sign_s) 105 | 106 | # 将结果写入excel表格中 107 | 108 | still_data = pd.DataFrame({'网格数m,n': still_grid, '趋于稳定的步数': still_steps}, 109 | columns=['网格数m,n', '趋于稳定的步数']) 110 | period_data = pd.DataFrame({'网格数m,n': period_grid, '变为周期性的步数': period_steps, 111 | '周期': period_counts}, columns=['网格数m,n', '变为周期性的步数', '周期']) 112 | 113 | 114 | still_data.to_excel('data.xlsx', sheet_name='still', index=False) 115 | period_data.to_excel('data1.xlsx', sheet_name='period', index=False) 116 | 117 | print('完成') -------------------------------------------------------------------------------- /lifegame/life_game.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | import matplotlib.animation as animation 6 | from pylab import * 7 | from matplotlib.colors import LinearSegmentedColormap 8 | 9 | 10 | class LifeGame: 11 | def __init__(self, n, m, start_life_list): 12 | self.n = n 13 | self.m = m 14 | self.life_c = '#1a6840' # 活细胞的颜色 15 | self.dead_c = '#f3f5e7' # 死细胞的颜色 16 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 17 | self.dead_n = 1 18 | 19 | # 开始的活细胞位置列表 20 | self.start_life_list = start_life_list 21 | # 开始局面 22 | self.initial_matrix = self.create_init_life() 23 | 24 | # 创建初始的情况 25 | def create_init_life(self): 26 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 27 | for jj in self.start_life_list: 28 | cow = jj // self.m 29 | col = jj % self.m 30 | init_matrix[cow][col] = self.life_n 31 | return init_matrix 32 | 33 | # 获取相邻的细胞 34 | def get_round(self, r, c, lifematrix): 35 | number_list = [] 36 | for i in range(max(0, r - 1), min(self.n, r + 2)): 37 | for j in range(max(0, c - 1), min(self.m, c + 2)): 38 | if i != r or j != c: 39 | number_list.append(lifematrix[i][j]) 40 | return number_list 41 | 42 | # 根据规则进行一代代的变化 43 | def create_by_rule(self): 44 | copy_matrix = self.initial_matrix.copy() 45 | for row in range(self.n): 46 | for column in range(self.m): 47 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 48 | if self.initial_matrix[row][column] == self.life_n: 49 | if l_count < 2 or l_count >= 4: 50 | copy_matrix[row][column] = self.dead_n 51 | else: 52 | if l_count == 3: 53 | copy_matrix[row][column] = self.life_n 54 | self.initial_matrix = copy_matrix.copy() 55 | return self.initial_matrix 56 | 57 | 58 | # 生成随机开局的活细胞位置列表 59 | def start_random_life(n, m, p=0.45): 60 | sign_list = np.random.choice(np.arange(n * m), 61 | int(n * m * p), replace=False) 62 | return sign_list 63 | 64 | 65 | 66 | lg = LifeGame(80, 80, start_random_life(80, 80)) 67 | 68 | # 绘图 69 | fig, ax = plt.subplots() 70 | # 设置主刻度 71 | ax.xaxis.set_major_locator(MultipleLocator(1)) 72 | ax.yaxis.set_major_locator(MultipleLocator(1)) 73 | # 设置网格线 74 | ax.xaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 75 | ax.yaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 76 | # 设置刻度,保证对齐 77 | ax.set_xticks(list(np.linspace(-0.5, lg.m - 1.5, lg.m))) 78 | ax.set_yticks(list(np.linspace(-0.5, lg.n - 1.5, lg.n))) 79 | # 设置热力图数值对应的颜色 80 | my_colormap = LinearSegmentedColormap.from_list("颜色匹配", [lg.life_c, lg.dead_c] if 81 | lg.life_n < lg.dead_n else[lg.dead_c, lg.life_c]) 82 | # 热力图 83 | im = ax.imshow(lg.initial_matrix, cmap=my_colormap) 84 | # 不显示刻度标签 85 | plt.setp(ax.get_xticklabels(), visible=False) 86 | plt.setp(ax.get_yticklabels(), visible=False) 87 | # 设置主刻度线 88 | tick_params(which='major', length=0) 89 | # 图形四个边的颜色和粗度 90 | for a in ['bottom', 'top', 'left', 'right']: 91 | ax.spines[a].set_linewidth(1.1) 92 | ax.spines[a].set_color('#ccccd6') 93 | 94 | 95 | # 动画函数 96 | def animate(frames): 97 | im.set_data(lg.create_by_rule()) 98 | return im, 99 | 100 | 101 | # 合成动画 102 | anim = animation.FuncAnimation(fig, animate, frames=8, interval=10) 103 | # 显示 104 | plt.show() 105 | -------------------------------------------------------------------------------- /lifegame/life_game_move_shake.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | # 制作生命游戏移动震荡态的代码 6 | from pylab import * 7 | from matplotlib.colors import LinearSegmentedColormap 8 | # 制作gif 9 | import imageio # 引入合成gif的库 10 | mpl.rcParams['font.sans-serif'] = ['SimHei'] 11 | 12 | 13 | class LifeGame: 14 | def __init__(self, n, m, start_life_list): 15 | self.n = n 16 | self.m = m 17 | self.life_c = '#1a6840' # 活细胞的颜色 18 | self.dead_c = '#f3f5e7' # 死细胞的颜色 19 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 20 | self.dead_n = 1 21 | 22 | # 开始的活细胞位置列表 23 | self.start_life_list = start_life_list 24 | # 开始局面 25 | self.initial_matrix = self.create_init_life() 26 | 27 | # 创建初始的情况 28 | def create_init_life(self): 29 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 30 | for jj in self.start_life_list: 31 | cow = jj // self.m 32 | col = jj % self.m 33 | init_matrix[cow][col] = self.life_n 34 | return init_matrix 35 | 36 | # 获取相邻的细胞 37 | def get_round(self, r, c, lifematrix): 38 | number_list = [] 39 | for i in range(max(0, r - 1), min(self.n, r + 2)): 40 | for j in range(max(0, c - 1), min(self.m, c + 2)): 41 | if i != r or j != c: 42 | number_list.append(lifematrix[i][j]) 43 | return number_list 44 | 45 | # 根据规则进行一代代的变化 46 | def create_by_rule(self): 47 | copy_matrix = self.initial_matrix.copy() 48 | for row in range(self.n): 49 | for column in range(self.m): 50 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 51 | if self.initial_matrix[row][column] == self.life_n: 52 | if l_count < 2 or l_count >= 4: 53 | copy_matrix[row][column] = self.dead_n 54 | else: 55 | if l_count == 3: 56 | copy_matrix[row][column] = self.life_n 57 | self.initial_matrix = copy_matrix.copy() 58 | return self.initial_matrix 59 | 60 | 61 | # 生成随机开局的活细胞位置列表 62 | def start_random_life(n, m, p=0.375): 63 | sign_list = np.random.choice(np.arange(n * m), 64 | int(n * m * p), replace=False) 65 | return sign_list 66 | 67 | 68 | # 震荡态 69 | start_life_list, n, m = ([291, 292, 339, 340, 207, 208, 254, 258, 301, 307, 349, 353, 355, 356, 397, 403, 446, 70 | 450, 495, 496, 215, 263, 311, 216, 264, 312, 169, 361, 123, 171, 363, 411, 277, 278, 71 | 229, 230], 32, 48) 72 | 73 | lg = LifeGame(n, m, start_life_list) 74 | 75 | 76 | def plot_life_game(data, figname): 77 | # 绘图 78 | fig, ax = plt.subplots() 79 | # 设置主刻度 80 | ax.xaxis.set_major_locator(MultipleLocator(1)) 81 | ax.yaxis.set_major_locator(MultipleLocator(1)) 82 | # 设置网格线 83 | ax.xaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 84 | ax.yaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 85 | # 设置刻度,保证对齐 86 | ax.set_xticks(list(np.linspace(-0.5, lg.m - 1.5, lg.m))) 87 | ax.set_yticks(list(np.linspace(-0.5, lg.n - 1.5, lg.n))) 88 | # 设置热力图数值对应的颜色 89 | my_colormap = LinearSegmentedColormap.from_list("颜色匹配", [lg.life_c, lg.dead_c] if 90 | lg.life_n < lg.dead_n else[lg.dead_c, lg.life_c]) 91 | # 热力图 92 | ax.imshow(data, cmap=my_colormap) 93 | # 不显示刻度标签 94 | plt.setp(ax.get_xticklabels(), visible=False) 95 | plt.setp(ax.get_yticklabels(), visible=False) 96 | # 设置主刻度线 97 | tick_params(which='major', length=0) 98 | # 图形四个边的颜色和粗度 99 | for a in ['bottom', 'top', 'left', 'right']: 100 | ax.spines[a].set_linewidth(1.1) 101 | ax.spines[a].set_color('#ccccd6') 102 | 103 | alignment = {'horizontalalignment': 'center', 'verticalalignment': 'baseline'} 104 | plt.figtext(0.6, 0.43, '滑翔机', weight='bold', color='#3f48cc', size='large', rotation=-60, **alignment) 105 | plt.figtext(0.45, 0.78, '高斯帕机枪', weight='bold', color='#3f48cc', size='large', **alignment) 106 | print('图片保存完成', figname) 107 | plt.savefig('%s.jpg' % figname, bbox_inches='tight') 108 | plt.close() 109 | 110 | 111 | # 制作震荡态gif的代码 112 | for i in range(100): 113 | plot_life_game(lg.initial_matrix, str(i)) 114 | lg.create_by_rule() 115 | 116 | namelist = ['%s.jpg' % dd for dd in range(70, 100)] 117 | 118 | # 合成一个gif图片 119 | def create_gif(image_list, gif_name=r'C:\Users\GWT9\Desktop\anfany.gif'): 120 | frames = [] 121 | for image_name in image_list: 122 | frames.append(imageio.imread(image_name)) 123 | imageio.mimsave(gif_name, frames, 'GIF', duration=0.1) # duration控制动态图中每张图片的显示时间 124 | 125 | create_gif(namelist) 126 | -------------------------------------------------------------------------------- /lifegame/life_game_shake.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | # 制作生命游戏震荡态的代码 6 | from pylab import * 7 | from matplotlib.colors import LinearSegmentedColormap 8 | # 制作gif 9 | import imageio # 引入合成gif的库 10 | mpl.rcParams['font.sans-serif'] = ['SimHei'] 11 | 12 | 13 | class LifeGame: 14 | def __init__(self, n, m, start_life_list): 15 | self.n = n 16 | self.m = m 17 | self.life_c = '#1a6840' # 活细胞的颜色 18 | self.dead_c = '#f3f5e7' # 死细胞的颜色 19 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 20 | self.dead_n = 1 21 | 22 | # 开始的活细胞位置列表 23 | self.start_life_list = start_life_list 24 | # 开始局面 25 | self.initial_matrix = self.create_init_life() 26 | 27 | # 创建初始的情况 28 | def create_init_life(self): 29 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 30 | for jj in self.start_life_list: 31 | cow = jj // self.m 32 | col = jj % self.m 33 | init_matrix[cow][col] = self.life_n 34 | return init_matrix 35 | 36 | # 获取相邻的细胞 37 | def get_round(self, r, c, lifematrix): 38 | number_list = [] 39 | for i in range(max(0, r - 1), min(self.n, r + 2)): 40 | for j in range(max(0, c - 1), min(self.m, c + 2)): 41 | if i != r or j != c: 42 | number_list.append(lifematrix[i][j]) 43 | return number_list 44 | 45 | # 根据规则进行一代代的变化 46 | def create_by_rule(self): 47 | copy_matrix = self.initial_matrix.copy() 48 | for row in range(self.n): 49 | for column in range(self.m): 50 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 51 | if self.initial_matrix[row][column] == self.life_n: 52 | if l_count < 2 or l_count >= 4: 53 | copy_matrix[row][column] = self.dead_n 54 | else: 55 | if l_count == 3: 56 | copy_matrix[row][column] = self.life_n 57 | self.initial_matrix = copy_matrix.copy() 58 | return self.initial_matrix 59 | 60 | 61 | # 生成随机开局的活细胞位置列表 62 | def start_random_life(n, m, p=0.375): 63 | sign_list = np.random.choice(np.arange(n * m), 64 | int(n * m * p), replace=False) 65 | return sign_list 66 | 67 | 68 | # 震荡态 69 | start_life_list, n, m = ( 70 | [66, 67, 98, 100, 132, 133, 134, 162, 164, 194, 195, 103, 135, 167, 75, 76, 106, 108, 138, 170, 172, 203, 204, 322, 71 | 323, 324, 297, 298, 330, 359, 391, 392, 82, 83, 84, 88, 89, 90, 144, 176, 208, 149, 181, 213, 151, 183, 215, 156, 72 | 188, 220, 242, 243, 244, 248, 249, 250, 306, 307, 308, 312, 313, 314, 341, 373, 405, 343, 375, 407, 348, 380, 412, 73 | 466, 467, 468, 472, 473, 474, 336, 368, 400], 74 | 18, 32) 75 | 76 | lg = LifeGame(n, m, start_life_list) 77 | 78 | 79 | def plot_life_game(data, figname): 80 | # 绘图 81 | fig, ax = plt.subplots() 82 | # 设置主刻度 83 | ax.xaxis.set_major_locator(MultipleLocator(1)) 84 | ax.yaxis.set_major_locator(MultipleLocator(1)) 85 | # 设置网格线 86 | ax.xaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 87 | ax.yaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 88 | # 设置刻度,保证对齐 89 | ax.set_xticks(list(np.linspace(-0.5, lg.m - 1.5, lg.m))) 90 | ax.set_yticks(list(np.linspace(-0.5, lg.n - 1.5, lg.n))) 91 | # 设置热力图数值对应的颜色 92 | my_colormap = LinearSegmentedColormap.from_list("颜色匹配", [lg.life_c, lg.dead_c] if 93 | lg.life_n < lg.dead_n else[lg.dead_c, lg.life_c]) 94 | # 热力图 95 | ax.imshow(data, cmap=my_colormap) 96 | # 不显示刻度标签 97 | plt.setp(ax.get_xticklabels(), visible=False) 98 | plt.setp(ax.get_yticklabels(), visible=False) 99 | # 设置主刻度线 100 | tick_params(which='major', length=0) 101 | # 图形四个边的颜色和粗度 102 | for a in ['bottom', 'top', 'left', 'right']: 103 | ax.spines[a].set_linewidth(1.1) 104 | ax.spines[a].set_color('#ccccd6') 105 | 106 | alignment = {'horizontalalignment': 'center', 'verticalalignment': 'baseline'} 107 | plt.figtext(0.21, 0.36, '信号灯', weight='bold', color='#3f48cc', size='large', **alignment) 108 | plt.figtext(0.305, 0.71, '活塞', weight='bold', color='#3f48cc', size='large', **alignment) 109 | plt.figtext(0.345, 0.3, '灯塔', weight='bold', color='#3f48cc', size='large', **alignment) 110 | plt.figtext(0.67, 0.25, '脉冲星', weight='bold', color='#3f48cc', size='large', **alignment) 111 | print('图片保存完成') 112 | plt.savefig('%s.jpg' % figname, bbox_inches='tight') 113 | plt.close() 114 | 115 | 116 | # 制作震荡态gif的代码 117 | for i in range(6): 118 | plot_life_game(lg.initial_matrix, str(i)) 119 | lg.create_by_rule() 120 | 121 | 122 | namelist = ['%s.jpg' % dd for dd in range(6)] 123 | 124 | 125 | # 合成一个gif图片 126 | def create_gif(image_list, gif_name=r'C:\Users\GWT9\Desktop\anfany.gif'): 127 | frames = [] 128 | for image_name in image_list: 129 | frames.append(imageio.imread(image_name)) 130 | imageio.mimsave(gif_name, frames, 'GIF', duration=0.9) # duration控制动态图中每张图片的显示时间 131 | 132 | 133 | create_gif(namelist) 134 | 135 | -------------------------------------------------------------------------------- /lifegame/life_game_still.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # &Author AnFany 3 | # WeChat: PythonFan 4 | 5 | import matplotlib.animation as animation 6 | from pylab import * 7 | from matplotlib.colors import LinearSegmentedColormap 8 | 9 | 10 | class LifeGame: 11 | def __init__(self, n, m, start_life_list): 12 | self.n = n 13 | self.m = m 14 | self.life_c = '#1a6840' # 活细胞的颜色 15 | self.dead_c = '#f3f5e7' # 死细胞的颜色 16 | self.life_n = 0 # 因为用热力图绘制,所以需要给细胞数字 17 | self.dead_n = 1 18 | 19 | # 开始的活细胞位置列表 20 | self.start_life_list = start_life_list 21 | # 开始局面 22 | self.initial_matrix = self.create_init_life() 23 | 24 | # 创建初始的情况 25 | def create_init_life(self): 26 | init_matrix = np.ones((self.n, self.m)) * self.dead_n 27 | for jj in self.start_life_list: 28 | cow = jj // self.m 29 | col = jj % self.m 30 | init_matrix[cow][col] = self.life_n 31 | return init_matrix 32 | 33 | # 获取相邻的细胞 34 | def get_round(self, r, c, lifematrix): 35 | number_list = [] 36 | for i in range(max(0, r - 1), min(self.n, r + 2)): 37 | for j in range(max(0, c - 1), min(self.m, c + 2)): 38 | if i != r or j != c: 39 | number_list.append(lifematrix[i][j]) 40 | return number_list 41 | 42 | # 根据规则进行一代代的变化 43 | def create_by_rule(self): 44 | copy_matrix = self.initial_matrix.copy() 45 | for row in range(self.n): 46 | for column in range(self.m): 47 | l_count = self.get_round(row, column, self.initial_matrix).count(self.life_n) 48 | if self.initial_matrix[row][column] == self.life_n: 49 | if l_count < 2 or l_count >= 4: 50 | copy_matrix[row][column] = self.dead_n 51 | else: 52 | if l_count == 3: 53 | copy_matrix[row][column] = self.life_n 54 | self.initial_matrix = copy_matrix.copy() 55 | return self.initial_matrix 56 | 57 | 58 | # 生成随机开局的活细胞位置列表 59 | def start_random_life(n, m, p=0.375): 60 | sign_list = np.random.choice(np.arange(n * m), 61 | int(n * m * p), replace=False) 62 | return sign_list 63 | 64 | 65 | # 静止态 66 | start_life_list, n, m = ( 67 | [30, 31, 35, 36, 41, 42, 47, 48, 52, 53, 58, 59, 62, 65, 68, 71, 74, 79, 82, 91, 93, 97, 98, 102, 103, 107, 109, 110, 68 | 120, 134, 135, 137, 142, 143, 162, 165, 169, 172, 181, 182, 191, 192, 197, 200, 203, 204, 206, 209, 212, 226, 227, 231, 69 | 233, 234, 239, 240, 273, 274, 302, 310, 311, 316, 317, 321, 329, 337, 340, 344, 346, 348, 350, 356, 366, 369, 373, 377, 70 | 381, 383, 395, 396, 409, 410], 16, 28) 71 | 72 | lg = LifeGame(n, m, start_life_list) 73 | 74 | 75 | 76 | # 绘图 77 | fig, ax = plt.subplots() 78 | # 设置主刻度 79 | ax.xaxis.set_major_locator(MultipleLocator(1)) 80 | ax.yaxis.set_major_locator(MultipleLocator(1)) 81 | # 设置网格线 82 | ax.xaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 83 | ax.yaxis.grid(True, which='major', linestyle="-", linewidth=1.1, c='#ccccd6') 84 | # 设置刻度,保证对齐 85 | ax.set_xticks(list(np.linspace(-0.5, lg.m - 1.5, lg.m))) 86 | ax.set_yticks(list(np.linspace(-0.5, lg.n - 1.5, lg.n))) 87 | # 设置热力图数值对应的颜色 88 | my_colormap = LinearSegmentedColormap.from_list("颜色匹配", [lg.life_c, lg.dead_c] if 89 | lg.life_n < lg.dead_n else[lg.dead_c, lg.life_c]) 90 | # 热力图 91 | im = ax.imshow(lg.initial_matrix, cmap=my_colormap) 92 | # 不显示刻度标签 93 | plt.setp(ax.get_xticklabels(), visible=False) 94 | plt.setp(ax.get_yticklabels(), visible=False) 95 | # 设置主刻度线 96 | tick_params(which='major', length=0) 97 | # 图形四个边的颜色和粗度 98 | for a in ['bottom', 'top', 'left', 'right']: 99 | ax.spines[a].set_linewidth(1.1) 100 | ax.spines[a].set_color('#ccccd6') 101 | 102 | 103 | # 104 | # 动画函数 105 | def animate(frames): 106 | im.set_data(lg.create_by_rule()) 107 | return im, 108 | 109 | 110 | # 合成动画 111 | anim = animation.FuncAnimation(fig, animate, frames=4, interval=10) 112 | 113 | # 动画保存 114 | anim.save(r'C:\Users\GWT9\Desktop\test_an.gif', writer='pillow') 115 | print('动画保存完毕') 116 | # 动画显示 117 | plt.show() 118 | -------------------------------------------------------------------------------- /lifegame/readme.md: -------------------------------------------------------------------------------- 1 | ### 生命游戏 2 | 3 | #### **1、[生命游戏python3代码](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/life_game.py)** 4 | 5 | #### **2、稳定结构代码** 6 | 7 | + **(1)[稳定态](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/life_game_still.py)** 8 | 9 | + **(2)[震荡态](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/life_game_shake.py)** 10 | 11 | + **(3)[移动震荡态](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/life_game_move_shake.py)** 12 | 13 | #### **3,[给定初始值局面的代码](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/example_lifegame.py)** 14 | 15 | #### **4,[网格数与步数关系的代码](https://github.com/Anfany/Funny-Math-Problem-by-Python3/blob/master/lifegame/find_relation.py)** 16 | 17 | 18 | -------------------------------------------------------------------------------- /plot_puzzle.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # -*- coding:utf-8 -*- 5 | # &Author AnFany 6 | 7 | # 引入库 8 | from matplotlib import colors as mcolors 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from pylab import mpl # 作图显示中文 12 | import os 13 | os.chdir(r'C:\Users\GWT9\Desktop') 14 | 15 | 16 | # 题目和关键词对应关系字典 17 | problem_dict = {'s': '数独', 'n': '八皇后', 'h': '汉诺塔', 'd': '二十四点', 'm': '幻方', 'p': '完美迷宫', 'c': '凸包', 18 | 'b': '七桥', 'o': '一笔画完', 'a': '变态曲线', 't': '旅行商', 'e': '爱因斯坦问题', 'f': '分形', 19 | 'r': '八人过河', 'w': '十五数码', 'z': '华容道', 'l': '生命游戏'} 20 | 21 | method_dict = {'s': '回溯', 'n': '回溯', 'h': '公式', 'd': '正则', 'm': '公式', 'p': '普里姆算法', 'c': '葛立恒扫描法', 22 | 'b': '弗罗莱算法', 'o': '深度、广度优先搜索', 'a': '积分与极限', 't': '遗传算法', 'e': '逻辑与回溯', 'f': '绘图', 23 | 'r': '状态空间', 'w': '迭代加深启发', 'z': '广度优先搜索', 'l': '二维细胞自动机'} 24 | 25 | # 选择颜色中比较重的 26 | line_color = np.array([hco for hco in list(mcolors.cnames.keys()) if hco not 27 | in ['k', 'w', 'whitesmoke', 'floarwhite', 'aliceblue', 28 | 'black', 'seashell', 'ivory', 'ghostwhite', 'beige', 'snow', 29 | 'white', 'gainsboro', 'mistyrose', 'peachpuff', 'linen', 'palegreen', 30 | 'honeydew', 'lightgoldenrodyellow', 'lightyellow', 'palegoldenrod', 31 | 'khaki', 'lemonchiffon', 'cornsilk', 'floralwhite', 'oldlace', 32 | 'wheat', 'moccasin', 'papayawhip', 'blanchedalmond', 'navajowhite', 33 | 'antiquewhite', 'bisque', 'mintcream', 'aquamarine', 'azure', 'lightcyan', 34 | 'paleturquoise', 'lavender', 'thistle', 'pink', 'lightpink', 'lavenderblush', 35 | 'aliceblue', 'lightblue', 'powderblue', 'plum', 'lightgray', 'lightgrey', 36 | 'silver', 'yellow', 'gold', 'greenyellow', 'chartreuse', 'lawngreen']]) 37 | 38 | 39 | def get_y_number(p_dict): 40 | """ 41 | 根据题目的个数,得到随机的纵坐标系列。 42 | :param p_dict: 题目字典 43 | :return: 随机的纵坐标系列 44 | """ 45 | y_num_list = np.linspace(1.5, len(p_dict) + 0.5, len(p_dict)) 46 | np.random.shuffle(y_num_list) 47 | return y_num_list 48 | 49 | 50 | # 绘制图片 51 | def figure(p_dict, m_dict, c=line_color, m_n=4): 52 | """ 53 | 根据题目字典以及方法字典绘制图片 54 | :param p_dict: 题目字典 55 | :param m_dict: 方法字典 56 | :param c: 可以选择的颜色 57 | :param m_n: 移动的步数 58 | :return: 图片 59 | """ 60 | p_y = get_y_number(p_dict) # 题目的纵坐标序列 61 | m_y = get_y_number(p_dict) # 方法的纵坐标系列 62 | 63 | key_list = list(problem_dict.keys()) # 题目的关键词序列 64 | 65 | plt.figure(figsize=(8, 6)) # 绘图 66 | plt.xlim(0, len(p_dict) + 2) 67 | plt.ylim(0, len(p_dict) + 2) 68 | plt.axis('off') 69 | 70 | # 设置字体 71 | mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei'] 72 | 73 | # 保证题目是不一样的颜色 74 | c_p_list = [] 75 | # 得到关键词和颜色的对应字典 76 | key_c_dict = {} 77 | 78 | # 获得位置与方法的字典 79 | a_method_dict = {} 80 | 81 | for h in range(len(key_list)): 82 | # 添加题目 83 | c_p = np.random.choice([f for f in c if f not in c_p_list], 1)[0] 84 | c_p_list.append(c_p) 85 | plt.text(1 - len(p_dict[key_list[h]]) / 2 * 0.45, p_y[h], p_dict[key_list[h]], color=c_p, size=13) 86 | # 添加字典 87 | key_c_dict[h] = c_p 88 | 89 | # 保证方法和题目的颜色是对应的 90 | plt.text(5 - len(m_dict[key_list[h]]) / 2 * 0.45, m_y[h], m_dict[key_list[h]], color=c_p, size=13) 91 | 92 | a_method_dict[m_y[h]] = key_list[h] 93 | 94 | # 按照所给字母的移动顺序确定关键词的顺序 95 | # 按照字典键的从小到大顺序得到关键词的顺序 96 | s_dict = sorted(a_method_dict.items(), key=lambda x: x[0], reverse=True) 97 | s_key_list = [k[1] for k in s_dict] 98 | # 按照移动的顺序获得新的次序列表 99 | new_list = s_key_list.copy() 100 | for index, value in enumerate(s_key_list): 101 | new_list[(index + m_n) % len(new_list)] = value 102 | # 添加关键词 103 | for k in range(len(s_dict)): 104 | plt.text(9, s_dict[k][0], new_list[k], color='k', size=13) 105 | 106 | plt.text(1 - 2 * 0.45, len(p_dict) + 1.5, '趣味谜题', size=15, color='k') 107 | plt.text(5 - 2 * 0.45, len(p_dict) + 1.5, '解题算法', size=15, color='k') 108 | plt.text(9 - 1.5 * 0.45, len(p_dict) + 1.5, '关键词', size=15, color='k') 109 | plt.plot([0, len(p_dict)-2], [len(p_dict)+1.2, len(p_dict)+1.2], c='k', lw=3) 110 | fu = '\downarrow' * m_n 111 | plt.text(len(p_dict)-1, len(p_dict)-1, '提示:\n\n(1)RGB' + '\n' + r'$(2)%s$' % fu, size=12, 112 | color=(152/255, 35/255, 156/3255)) 113 | plt.savefig(r'.\puzzle.png') 114 | plt.show() 115 | 116 | 117 | figure(problem_dict, method_dict) 118 | 119 | 120 | --------------------------------------------------------------------------------