运行长度编码

2010年2月26日

Brian Kernighan和P.J.Plauger的一本书,Pascal中的软件工具,描述了一对程序,称为压缩扩大,提供文本文件的运行时编码。这个压缩程序将文本文件作为输入,并将文本文件的一个版本(希望较小)作为输出;这个扩大程序反转该操作。压缩是通过将四个或更多相同字符的行替换为三个字符的代码来实现的,该代码由波浪号、表示1到26次重复的字母a到Z以及要重复的字符组成。长度超过26个字符的行被多个编码替换,输入中波浪号的任何文字外观都被编码为长度为1的行。例如,字符串ABBB~CDDDDEEEEEEEEEeeEEEEEEEE编码为abb~A~C~ED~ZE~DE修道院院长

你的任务是编写压缩和扩展文本文件的程序。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

工程A分拣功能

2010年2月23日

我们在之前的运动今天我们来看看Jon Bentley的快速排序版本说话关于谷歌,他和Doug McIlroy在他们的文章中的“设计排序函数”软件-实践和经验(第23卷第11期,第1249-1265页,1993年11月)。

Bentley/McIlroy快速排序的特点是具有自适应枢轴选择、快速接近点划分、使用三元比较运算符(小于、等于、大于)启用“胖枢轴”,以及针对小型子阵列的插入排序。快速排序还使用适应数据元素大小的快速交换。自适应枢轴选择将中间元素用于小型数组,将第一个、中间和最后一个元素的中位数用于中型数组,将九个等距元素的中位用于大型数组。这种描述并没有真正做到代码的公正性;你应该读一下文章详细信息。

您的任务是使用与Bentley和McIlroy相同的算法编写一个快速排序函数。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

阿特金筛,改进

2010年2月19日

最近,我们检查了Atkin的筛子来枚举素数运动虽然阿特金的筛网有可能比埃拉托斯特尼的筛网更快,但我们的实施并没有;Eratostennes筛选需要1.219秒来枚举前100万个素数,我们实现的Atkins筛选需要22.954秒,是执行相同任务的19倍。

问题是,我们使用的天真实现执行了无用的工作。例如,考虑您正在筛选100万个数字x个初始实现的变量从1到1000不等。在第一种情况下,有4个x个² +² =k个,4·1000²+1000²=5000000,这远远超出了筛选范围的末尾。减少限制意味着更少的工作和更快的程序。

你的任务是改写阿特金斯天真的筛子,以消除无用的工作。当你完成后,欢迎你加入阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

Soundex公司

2010年2月16日

Soundex是一种算法,最初由Margaret Odell和Robert Russell在20世纪初开发,用于将人们的姓氏转换为标准编码,将相似的名字组合在一起,从而纠正拼写错误。Knuth(AoCP3,第6章简介)对算法描述如下:

  1. 保留名称的第一个字母,并在其他位置删除所有出现的a、e、h、i、o、u、w、y。
  2. 将以下数字分配给第一个字母后面的其余字母:
    • b、 f、p、v→1
    • c、 g,j,k,q,s,x,z→2
    • d、 t→3
    • l→4
    • m、 n→5
    • r→6
  3. 如果两个或多个具有相同代码的字母在原始名称中相邻(在步骤1之前),则省略除第一个字母以外的所有字母。
  4. 通过添加尾随零(如果少于三个数字)或删除最右边的数字(如果多于三个),转换为“字母、数字、数字、位数”的形式。

soundex方法并不完美。正如克努特指出的那样,罗杰斯和罗杰斯、辛克莱和圣克莱尔、切比谢夫和切比雪夫等相关名字并不匹配。另一方面,soundex工作得很好,一般来说很有用,如果你第一次尝试比赛失败,用另一种拼写方法再试一次也不难。

您的任务是编写一个接受名称并返回其相关soundex代码的函数。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

阿特金筛

2010年2月12日

我们研究了用埃拉托斯特尼筛数列素数的方法,这种方法可以追溯到古希腊人,分为两部分以前的 练习就在几年前,即2004年,a.O.L.Atkin和D.J.Bernstein开发了一种新方法,称为Atkin筛,可以更快地完成相同的任务。新方法首先标记无平方势素数,然后删除那些非无平方势素。

Atkin的筛选以长度的布尔数组(位是精细的)开始n个等于要筛分的项目数量;数组的每个元素最初都是false。

无平方势素数的标记如下:对于每个元素k个数组的k个≡1(模12)或k个lect 5(mod 12),并且存在一些4x个² +² =k个对于正整数x个,翻转筛选元素(将true元素设置为false,将false元素设置为true)。对于每个元素k个的数组k个≡7(mod 12)并且存在一些3x个² +² =k个对于正整数x个,翻转筛元件。对于每个元素k个数组的k个≡11(mod 12)并且存在一些3x个²–² =k个对于正整数x个具有x个>,翻转筛元件。

预处理完成后,从7开始通过筛子进行实际筛分。对于数组的每个真元素,将元素平方的所有倍数标记为假(无论其当前设置如何)。剩下的真元素是质数。

你的任务是编写一个函数,用Atkin的sieve筛选素数。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

数值积分

2010年2月9日

计算函数的定积分是许多计算的基础。在许多情况下,函数的积分可以用符号表示,而定积分可以直接计算。我们将在今天的练习中研究的另一种方法是用数值方法计算定积分,数值分析师称之为运算正交。我们将考虑一个函数(f)我们要在这个范围内找到定积分b条,使用<b条

回想一下你学习微积分时,定积分是曲线下的面积。如果我们将曲线切成数百条、数千条或数百万条垂直条带,我们可以通过求各个条带的面积之和来近似曲线下的面积,假设每个条带是一个高度等于条带中点处曲线值的矩形;这显然是矩形求积法。梯形法类似,但使用带钢两端曲线值的平均值;然后,该条带形成一个具有平行边的梯形,在水平轴上形成一个平底,并形成一个沿着曲线的倾斜顶部。最后一种方法称为Simpson方法,通过将曲线的高度作为其在条带左侧的值加上其在条带右侧的值加上其在条带中点的值的四倍,将抛物线拟合到条带的顶部。从矩形法(一点)到梯形法(两点)再到辛普森法(三点),精度会提高,因为近似值更接近曲线,而且切片数也会增加。梯形规则如右上图所示。

许多曲线的特点是大部分接近平坦,近似效果良好,而少数小部分变化迅速,近似效果不佳。如果增加切片数,对曲线的平坦部分几乎没有影响,因此浪费了大量工作。自适应正交通过测量不同切片的近似值,并缩小曲线快速变化的切片,使我们能够精确控制近似值。自适应求积是一个递归过程;如果近似值n个n个/两个切片足够接近,递归停止,否则范围被分割为两部分,自适应求积分别应用于两部分中的每一部分。

您的任务是编写通过矩形、梯形和辛普森方法进行数值积分的函数,以及执行自适应求积的函数。使用函数计算对数积分\mathrm{li}(x)=\int_2^x\frac{dt}{\log{t}}对于x个= 1021,其中对数积分是素数小于其参数的近似值。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

Eratosthenes分段筛

2010年2月5日

我们检查了Eratostenes筛用于计算小于n个在我们的第二个运动大约一年前。在今天的练习中,我们更新了该算法以计算范围内的素数L(左),其中范围不是从零开始的,并且太大,无法一次全部放入内存。具体来说,我们讨论了一个接受参数的函数L(左),对于范围的左端,以及,表示范围的右端,以及一个参数B类这就分裂了L(左); 我们还假设素数小于已知。实际上,L(左)会很大,可能10个16或1018、和B类会稍微小一些,可能是108或1010

我们将通过计算100到200范围内的素数来解释算法B类= 10; 由于我们不看偶数,该算法将进行五次筛选,每次筛选20个数字。

有六个素数小于200的平方根:2、3、5、7、11和13;我们将忽略2,因为它是偶数。与每个素数相关P(P)k个是我们要打的号码k个这是其中的偏移量B类当前筛分块中第一个素数的整数P(P)k个例如,当从100到120进行筛分时,底漆为3、5、7、11和13,以及相关的s是2、2、2,10和8。每个k个可以通过计算进行初始化k个=(-1/2×(L(左)+ 1 +P(P)k个))模块P(P)k个并为下一个2重新初始化B类按计算分块k个= (k个B类)模块P(P)k个; 例如从120到140的第二个筛分块处的s为1、2、6、0和11。

在每个筛选块中,我们创建一个布尔数组(实际上,通常使用位),初始化为真的然后,从k个抵消。在我们的例子中,素数3与=2使我们将位2、5和8重置为虚假的同样,素数5使我们重置位2和7,素数7使我们重置比特2和9,素数11在当前筛选块中没有奇数倍数,素数13使我们重置位元8。筛分后真的是0、1、3、4和6,对应于素数101、103、107、109和113。

用五分钟的时间手工制作示例筛是有益的。

您的任务是编写一个函数,执行上文所述的Eratostenes分段筛选。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

证明原始性

2010年2月2日

我们研究了检查二分之一数字素性的算法以前的 练习两种算法都是概率算法;Rabin-Miller算法已知假阳性,Carl Pomerance证明Baillie-Wagstaff算法有无穷多的误报,尽管没有已知的误报。

今天的练习描述了算法对于证明一个数字是质数,不太可能,但肯定是质数。该算法根据Edouard Lucas的一个定理工作,该定理基于费马小定理(如果n个那么是质数b条n个-1≡1(modn个)对于每个整数b条互质n个):

如果,对于某个整数b条,b条n个-1≡1(modn个),如果b条(n个-1)/q个≢1(型号n个)的任何素因子q个属于n个-1,那么n个是质数。

因此,如果n个-1是已知的,很容易确定n个

你的任务是编写一个函数,用卢卡斯的素性测试来确定整数的素性;用它来证明2的素性89-1.完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2