首页 置换 选车 估价 问答 生活 经销商 车管所 汽车资讯 汽车销量 车牌查询 今日油价 天气预报
您的位置: 首页 > 生活 > 科技 > 大学生算法设计与编程挑战赛题目(第六章编程挑战)
大学生算法设计与编程挑战赛题目(第六章编程挑战)
更新时间:2024-07-08 04:03:04
一、在正方形中填充圆形

前面提到过mtaplotlib支持创建其他几何图形。Polygon块特别有趣,因为我们可以用它绘制具有不同边数的多边形。以下是我们绘制一个正方形(每条边的长度为4的)方式:


''' Draw a square ''' from Matplotlib import pyplot as plt def draw_square(): ax = plt.axes(xlim=(0, 6), ylim=(0, 6)) square = plt.Polygon([(1,1), (5,1), (5,5), (1, 5), closed=True]) ax.add_patch(square) ax.axis('equal') plt.show() if __name__ == '__main__': draw_square()


Polygon对象是通过将顶点左边编排作为第一个输入参数来传入的,因为我们要绘制一个正方形,所以修要传入四个点的坐标:(1,1), (5,1), (5,5), (1, 5),令closed=True,告诉matplotlib我们要绘制一个封闭的正方形,即起点和终点是相同的。

在这个挑战中,你将尝试一个“在正方形中填充圆形”问题的简化版本。在上述代码生成的正方形中,可以放入多少个半径为0.5的圆形?画出来看一看!下图展示了最终的输出结果。

大学生算法设计与编程挑战赛题目(第六章编程挑战)1

在5*5的正方形中填充半径为0.5的圆

这里的技巧是从正方形的左下角开始,即(1,1)点,然后持续添加圆形到正方形被填满。以下代码片段显示了如何创建一个圆并将其添加到图形中:


y = 1.5 while y < 5: x = 1.5 while x < 1.5: c = draw_circle(x, y) ax.add_patch(c) # ax.set_gc('r') x = 1.0 y = 1.0


这并不是在正方形中填充圆形的唯一办法,大家可以自行探讨。

代码实现:


''' circle_in_square.py Circles in a square ''' from matplotlib import pyplot as plt def draw_square(): square = plt.Polygon([(1, 1), (5, 1), (5, 5), (1, 5)], closed=True) return square def draw_circle(x, y): circle = plt.Circle((x, y), radius=0.5, fc='y') return circle if __name__ == '__main__': ax = plt.gca() s = draw_square() ax.add_patch(s) y = 1.5 while y < 5: x = 1.5 while x < 5: c = draw_circle(x, y) ax.add_patch(c) x = 1.0 y = 1.0 plt.axis('scaled') plt.show()


二、绘制Siperpinski三角

绘制Siperpinski三角(名字来源于波兰数学家Waclaw Siperpinski)是一个有内嵌其中的较小等边三角形组成的等边三角形分形。下图展示了由10000个点构成的Siperpinski三角。

大学生算法设计与编程挑战赛题目(第六章编程挑战)2

由10000个点构成的Siperpinski三角

有趣的是,我们使用绘制蕨类植物的程序在这里可以同样绘制绘制Siperpinski三角,只需要改变变换规则及其概率。以下程序可以用来绘制绘制Siperpinski三角:从点(0,0)开始,并应用以下变换之一。

(1)变换1:

(2)变换2:

(3)变换3:

每个变换被选中地概率相同,均为1/3,这里的挑战是编写一个程序绘制由输入的指定点数构成的绘制Siperpinski三角。

代码实现:


''' Draw a Siperpinski ''' from matplotlib import pyplot as plt import random def transformations_1(p): x = p[0] y = p[1] x1 = 0.5*x y1 = 0.5*y return x1, y1 def transformations_2(p): x = p[0] y = p[1] x1 = 0.5*x 0.5 y1 = 0.5*y 0.5 return x1, y1 def transformations_3(p): x = p[0] y = p[1] x1 = 0.5*x 1 y1 = 0.5*y return x1, y1 def get_x_y(n,p): transformations = [transformations_1, transformations_2, transformations_3] x = [0] y = [0] x1, y1 = 0, 0 for i in range(n): t = random.choice(transformations) x1, y1 = t((x1, y1)) x.append(x1) y.append(y1) return x, y if __name__ == '__main__': p = (0, 0) n = int(input('Enter the number of Siperpinski\'s dots: ' )) x, y = get_x_y(n, p) plt.plot(x, y,'o') plt.title('Siperpinski with {0} dots'.format(n)) plt.show()


三、探索Henon函数

1976年,Michel Henon提出了Henon函数,该函数描述了一个点P(x,y)的变换规则:

无论初始点在哪里(假设它离原点不远),你将看到随着点的增多,它们开始沿着曲线分布,如下图:

大学生算法设计与编程挑战赛题目(第六章编程挑战)3

Henon函数

这里的挑战是编写一个程序,创建一个以(1,1)为初始点,经20000次该变换规则迭代后的图形。

这是一个关于动力系统的例子,被所有点所吸引的曲线称为吸引子。更多关于此函数、动力系统和分形的基本信息,可以参考Kenneth Falconer的著作Fractals:A Very Short Introduction(牛津大学出版社,2013)。

代码实现(Henon 分形):


import matplotlib.pyplot as plt def transformation(p): x = p[0] y = p[1] x1 = y 1 - 1.4 * x**2 y1 = 0.3*x return x1, y1 def draw_Henon(n, p): x = [1] y = [1] x1, y1 = 1, 1 for i in range(n): x1, y1 = transformation((x1, y1)) x.append(x1) y.append(y1) return x, y if __name__ == '__main__': n = int(input('Enter the numbers of Henon points: ')) p = (1, 1) x, y = draw_Henon(n, p) plt.plot(x, y, 'o') plt.title('Henon with {0} points'.format(n)) plt.show()


四、绘制Mandelbrot集

这里的挑战是编写一个程序绘制Mandelbrot集,这是引用加单规则导出复杂形状的另一案例(如下图)。在讨论实现它的具体步骤之前,我们先来了解matplotlib中的imshow()函数。

大学生算法设计与编程挑战赛题目(第六章编程挑战)4

Mandelbrot集

imshow()函数

imshow()函数通常用来显示外部图像,如JPEFG或PNG图像。可以参考网址Image tutorial — Matplotlib 2.0.2 documentation中的例子。这里,我们使用这个函数通过matplotlib来绘制我们新创建的图像。

考虑笛卡尔平面的一部分,其中x和y’的坐标都位于0到5之间。现在,考虑沿每个轴的6个等距离点:x坐标和y坐标的取值均为0,1,2,3,4,5.如果我们取这些点的笛卡尔积,将得到x-y平面上的36个等距点。坐标分别为(0,0),(0,1), ... ,(0,5),(1,0),(1,1),... ,(1,5),...,(5,5)。现在假设我们要用灰色阴影给每个点上色,也就是说,随机选择呢一些点为黑色、一些点为白色以及一些点为黑白之间的颜色。下图就展示了这种情形。

为创建这个图形,我们必须定义一个包含6个列表的列表,6个列表中的每一个都依次包含着0-10之间的6个整数,每个数字对应于每个点的颜色:0表示黑色,10表示白色。然后我们将这个列表和其他必要的参数一起传递给inshow()函数。

创建一个包含多个列表的列表

一个列表可以包含其他列表作为其元素:


>>> l1 = [1,2,3] >>> l2 = [4,5,6] >>> l = [l1, l2]


大学生算法设计与编程挑战赛题目(第六章编程挑战)5

6*6的等间距点阴影上色

这里我们创建一个列表l,它包含了列表l1和列表l2。列表1的第一个元素l[0]与列表l1相同,第二个元素l[1]与列表l2相同。


>>> l[0] [1, 2, 3] >>> l[1] [4, 5, 6]


为引用这两个列表中的单个元素,我们必须指定两个索引,l[0][1]指代第一个列表的第二个元素,l[1][2]指代第二个列表的第三个元素,以此类推。

既然我们已经知道如何处理包含多个列表的列表,我们可以摆写一个程序创建一个类似于上图的图形。


import matplotlib.pyplot as plt import matplotlib.cm as cm import random def initialize_image(x_p, y_p): # ① image = [] for i in range(y_p): x_colors = [] for i in range(x_p): x_colors.append(0) image.append(x_colors) return image def color_points(): x_p = 6 y_p = 6 image = initialize_image(x_p, y_p) for i in range(y_p): for j in range(x_p): image[i][j] = random.randint(0,10) # ② plt.imshow(image, origin='lower', extent=(0, 5, 0, 5), cmap=cm.Greys_r, interpolation='nearest') # ③ plt.colorbar() plt.show() if __name__ == '__main__': color_points()


①处的initialize_image()函数创建了一个包含多个列表的列表,其中每一个元素都初始化为0,该函数有两个输入参数x_p和y_p,分别对应于x轴和y轴上的点的个数,这实际上意味着初始列表图像包含x_p个列表,其中每个列表包含y_p个0。

在color_points()函数中,一旦从initialize_image()函数返回一个图像列表,在②处就给元素image[i][j]分配一个0-10之间的随机整数。当给元素分配随机整数时,我们也给笛卡尔平面上的点(从原点出发沿y轴第i步,沿x轴第j步的点)指定了颜色。这里很重要的一点就是imshow()函数从image列表中的位置推导点的颜色,而不是依赖于具体的x坐标和y坐标。

然后,在③处调用imshow(函数,并将image作为第一个参数输入,关键字参数origin='lower指定image[0][0]的数字对应于点(0, 0)的颜色,关键字参数extent=(0,5, 0, 5)分别将图像的左下角和右上角的坐标设置为(0, 0)和(5, 5),关键字参数cmap=cm.Greys_ r说明我们要创建一个灰度图像。

最后一个关键字参数interpolation='nearest'设定matplotlib 应该给那些没有指定颜色的点用与其最近的点的颜色上色。这是什么意思呢?注意我们仅考虑并指定了坐标区域(0, 0)和(5,5)内36个点的颜色,因为该区域内有无穷多个点,所以我们应该告诉matplotlib对那些没有设定颜色的点如何上色,这就是你在图中的 每个点周围看到颜色"框”的原因。

调用colorbar()函数将在图中显示一个颜色条, 显示哪个整 数对应哪个颜色。最后调用show()函数展示图像。需要注意的是由于使用了random.randint()函数,你的图像可能会与图6-15展示的有所不同。

如果你通过在color_points()函数中将x_ p和y_ p设置为20来增加每个轴上的点数,你将会看到一个与图6-16所示类似的图像,注意颜色框的尺寸变小了。如果你增加更多的点数,你将看到颜色框的尺寸进一步缩小, 给人的错觉是每个点都有不同的颜色。

Mandelbrot集的绘制

我们考虑x-y平面上位于点(-2.5,-1.0)和(1.0,1.0)之间的区域,并把每个轴划分为400个等间距的点,这些点的笛卡尔积将给出该区域内的1600个等间距点,我们把这些点记为。

大学生算法设计与编程挑战赛题目(第六章编程挑战)6

20*20的等间距点阴影上色

通过调用之前用到的initialize_ image(函数创建一个 列表image,并将函数中的x_ p和y_ p都设置为400。 然后,为每个生成的点(x, y)执行下述步骤:

(1) 首先,创建两个复数,和。(我们用j表示 )

(2)创建一个迭代标签,并将其设置为0,即iteration=0。

(3)创建一个复数

(4)以1为单位增加iteration的值,即iteration= iteration 1。

(5)若abs(z1) < 2 且iteration < max_ iteration, 则返回第(3)步;否则进入第(6)步。max iteration 的值越大,绘制的图像越详细,当然花费的时间也就越长。这里设置max iteration=1000。 (6)将点的颜色设置为iteration 的值,即image[k][i] = iteration。一旦有了完整的image列表,调用imshow()函数,并将extent关键字参数设置为(-2.5, -1.0)和(1.0,1.0) 之间的区域。

这个算法通常称为时间逃逸算法。当一个点达到最大迭代次数时仍在区域内(即复数的模小于2),则该点属于Mandelbrot 集,将其涂成白色。那些在未达到最大迭代次数就超出区域的点称为“逃逸”,它们不属于Mandelbrot集,将其涂成黑色。你可以通过减少和增加每一个轴上点的个数来进行实验,减少点的个数会导 致颗粒图像,而增加点的个数则会产生更加细致的图像。

代码实现:


import matplotlib.pyplot as plt import matplotlib.cm as cm import random x0, x1 = -2.5, 1 y0, y1 = -1.0, 1 def initialize_image(x_p, y_p): image = [] for i in range(y_p): x_colors = [] for i in range(x_p): x_colors.append(0) image.append(x_colors) return image def color_points(): n = 400 max_iteration = 1000 z1 = complex(0, 0) image = initialize_image(n, n) dx = (x1-x0)/(n-1) dy = (y1-y0)/(n-1) x_coords = [x0 i * dx for i in range(n)] y_coords = [y0 i * dy for i in range(n)] for i,x in enumerate(x_coords): for k, y in enumerate(y_coords): z1 = complex(0, 0) iteration = 0 c = complex(x,y) while abs(z1) < 2 and iteration < max_iteration: z1 = z1 ** 2 c iteration = 1 image[k][i] = iteration print(image) plt.imshow(image, origin='lower', extent=(-2.5, -1.0, -1.0, 1.0), cmap=cm.Greys_r, interpolation='nearest') plt.colorbar() plt.show() if __name__ == '__main__': color_points()


,
相关推荐RECOMMEND
电脑静音了怎么恢复声音(有哪些方法)
电脑静音了怎么恢复声音?有时候,是因为电脑开启了静音导致电脑没声音点击任务栏右下角的小喇叭图标,在弹出的页面中,向上拖动滑块之后发现电脑就有声音了,下面我们就来说一说关于电脑静音了怎么恢复声音?我们一...
小米手机怎么关闭手机锁屏密码(小米手机怎么关掉锁屏密码)
大部分人都会给手机设置锁屏密码,是一种保护自己隐私的方式,但对于老人来说,会觉得这个功能比较麻烦。就需要我们把原先的锁屏给取消一下。那么,小米手机怎么关掉锁屏密码呢?或许还有部分小伙伴还不清楚该如何使...
什么软件打开pdf可以免费编辑(如何打开并编辑PDF文件)
在我们日常工作和日常学习中,PDF格式是我们经常接触到的文件格式。我们可以通过pdf阅读器或者编辑器来打开或者修改PDF文件。PDF阅读器和PDF编辑器都可以打开PDF文件,但阅读器的主要功能是打开、...
黑苹果傻瓜式安装教程(安装系统)
黑苹果傻瓜式安装教程?首先做一个支持苹果系统的驱动找到BOOTcomp助理,我来为大家科普一下关于黑苹果傻瓜式安装教程?以下内容希望对你有帮助!黑苹果傻瓜式安装教程首先做一个支持苹果系统的驱动。找到B...
用scratch编音乐(用Scratch编程来模拟弹钢琴)
很多孩子学编程选择从Scratch入门,一方面是Scratch的界面十分有趣,能够吸引孩子关注,另一方面Scratch的功能也非常丰富,游戏、动画、声音齐全,孩子上手会更容易。今天陈老师就来教教大家用...
网站运营方法(如何运营网站)
网站运营方法?采用稳定、处理快速的南北互通的服务器,我来为大家科普一下关于网站运营方法?以下内容希望对你有帮助!网站运营方法采用稳定、处理快速的南北互通的服务器。选择操作系统,用unix,Linux还...