滑动中间带

2012年6月29日

我们在最近的演习今天我们来看一下这个问题的一个微小变化,即滑动中值,它滑动宽度窗口k个在输入流上,报告每个连续窗口的中值。

流媒体要求我们将整个输入流保存在内存中。但对于滑动中值,我们只保留最近的k个项目。我们保留两个数据结构。循环队列按输入顺序保留最新的输入项。有序映射使输入项保持有序。读完第一篇之后k个项,每次读取项时,我们都会输出当前中值,从有序映射中删除周期队列中最旧的项,将新项插入有序映射和周期队列,然后继续下一项。

您的任务是编写一个实现滑动中值计算的程序。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

广告牌挑战,第2部分

2012年6月26日

上一次练习,我们研究了一个涉及数字的编程挑战e(电子)。解决该练习并单击指定的网站将解算器带到此页面:

祝贺 你。你已经达到2级了。访问www.Linux.org,输入Bobsyourbuncle作为登录名,输入此等式的答案作为密码。

f(1)=7182818284
f(2)=8182845904
f(3)=8747135266
f(4)=7427466391
f(5)=__________

不要尝试登录;该帐户已不存在。

你的任务是编写一个程序来查找序列中的下一个数字。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

广告牌挑战,第1部分

2012年6月22日

几年前,硅谷和128号公路的技术中心出现了一个带有以下文字的广告牌:

{在连续数字中找到的第一个10位素数e(电子)}.com网站

你的任务是编写一个程序,找到在的连续数字中找到的第一个10位素数e(电子)。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

E的数字

2012年6月19日

我们给出了计算a中π的位数的算法上一次练习。今天,我们来看两种用于计算e(电子)

我们从一个算法由于斯坦利·拉比诺维茨和斯坦·瓦贡:

算法电子插口:计算第一个n个十进制数字e(电子)以下为:

1初始化:让第一个数字为2并初始化数组A类长度的n个+1到(1,1,1…,1)。

2.重复n个−1倍:

乘以10:将每个条目相乘A类10倍。

取分数部分:从右侧开始,减少第个条目A类+1,将商保留一位。

输出下一个数字:最终商是e(电子)

我们给出了前十位数字的计算示例e(电子)下一页,其中我们计算e(电子)作为2 7 1 8 2 8 1 8 2 6。正如你所看到的,这个算法的最后一个数字可能是错误的(应该是8,而不是6);事实上,正如论文所指出的,在某些情况下,最后几个数字可能是错误的。该算法还受到一个事实的影响,即它是有界的,这意味着必须提前指定数字的数量,并且它需要的空间与n个2

一个不同的算法来自杰里米·吉本斯(Jeremy Gibbons),是无界的,只需要恒定的空间;吉本斯给出了π的序列,但汤姆·莫特尔适应它是为了e(电子)当我无法根据莫特尔的描述计算出算法时,我向《编程实践》(Programming Praxis)的定期撰稿人雷姆科·尼梅耶(Remco Niemeijer)求助,他用这段漂亮的哈斯克尔代码来回应,该代码可以计算π和e(电子)以下为:

流::积分a=>(a,a)->(a,b)->[(a,a,a)]->[a]
流(lo,hi)z~(x:xs)=如果lbound==大约zhi
然后是lbbound:stream(lo,hi)(mul(10,-10*lbbound,1)z)(x:xs)
else流(lo,hi)(mul z x)xs
其中lbound=近似z-lo
近似(a,b,c)n=div(a*n+b)c
mul(a,b,c)(d,e,f)=(a*d,a*e+b*f,c*f)

stream数字::(Num a,Integral a,Enum a)=>(a->(a,a,a))->(a,a)->[a]
流数字f范围=流范围(1,0,1)[(n,a*d,d)|(n,d,a)<-map f[1..]]

stream_pi,stream_e::[整数]
stream_pi=流数字(\k->(k,2*k+1,2))(3,4)
stream_e=流数字(\k->(1,k,1))(1,2)

主::IO()
main=打印$take 30 stream_pi
打印$take 30 stream_e

尼梅耶解释说,他对吉本斯论文中的算法进行了如下修改:

单元是仅用于一个位置的常量。删除定义并直接使用该值。

comp公司是基本的2×2矩阵乘法。重命名为穆尔使目的更明确。

外部正如论文中所定义的那样,它不是为我编译的:它应该是来自整数(q*x)而不是来自整数q*x但还有更多收获:唯一的地方外部使用的前面是地板,所以基本上我们有地板(a/b),等于分区a b。因为它是用来近似实际值的,所以我给它命名大约

–该代码使用2×2矩阵表示为4元组。但是,左下角元素始终为0。删除所有位置的此元素,保留3元组并使穆尔大约更简单。

–对于π和e(电子),的下一个安全的传递给的函数流动除了使用的边界外,都是相同的,所以传入边界并将函数集成到流动

在中使用流动是下限。相应地重命名。

欺骗传递到流总是comp公司(或者就我而言穆尔). 删除参数并使用穆尔直接。

触头对于π和e(电子),因此删除参数并内联函数。

–论文中π的定义流动带有一些起始参数。e(电子)将执行相同的操作,生成函数stream数字把这个抽象出来。

–自流动现在需要的参数少得多,再也没有理由将它们全部命名。

–根据船体位置,π函数中的每项为2+k个/(2k个+ 1)x个。对于e(电子),每项为1+(1/k个)x个(或者更确切地说,它定义了e(电子)−1从开始k个=2,但如果你从k个=1你加上术语1+1/1x个,它为您提供1+1/1*(e(电子)-1) ,当然是e(电子)). 所以两者都是这样的+ (n个/d日)x个。中使用的矩阵lfts公司是(n个,*d日, 0,d日). 我不喜欢自己做乘法,所以我做了流数字取一个产生n个,d日使给定的术语更接近数学定义。此函数用于生成实际矩阵。

–添加流_e流_pi功能。

您的任务是为编写两个插口函数e(电子)如上所述。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

计算一

2012年6月15日

今天的练习是一道有趣的数学题:

考虑一个函数(f)需要一个正整数n个并返回0到之间所有整数的十进制表示形式中的1s数n个,包括在内。例如,(f)(13) =6,用于数字1、10、11(两次,用于两个1)、12和13。请注意(f)(1) = 1. 1之后,第二大的是什么n个对于其中(f)(n个) =n个?

你的任务是编写一个程序来找到解决方案。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

有序地图

2012年6月12日

在计算机科学中,映射是一种将值与键相关联的数据类型;所有键都是唯一的,唯一允许的比较是相等的(这两个键相等吗?)。有序映射将规则从相等扩展到有序(其中一个键是否小于另一个键?),如果有序映射还允许对映射的元素进行排序(此项是第一项,此项是第二项,依此类推),则可以说它提供了顺序统计信息。基本映射通常使用哈希表实现,而这两个有序变体通常使用某种平衡树(treap、avl、red-black)实现。地图有时被称为字典,尽管地图的类型经常是不明确的,字典一词可以指有序或无序地图。

今天的练习描述了一种抽象数据类型,它提供了带有订单统计信息的有序映射。我们提供了查找、插入和删除的基本操作,还提供了更新函数,可以更新现有值或在映射中插入新的键/值对。对于顺序统计,我们提供了大小、第n个和秩运算符。我们还提供了高阶函数map、fold和for-each,以及与列表的转换。最后,我们提供了一个迭代器,以在映射中按升序逐个生成键/值对。

我们使用avl树来实现我们的地图;代码分为两部分以前的 练习。我们还从上一次练习。新数据类型最近已添加到标准前奏曲

您的任务是使用如上所述的顺序统计信息实现有序映射的抽象数据类型。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

2012年6月8日

正在进行的其中一项主题在Programming Praxis中,需要重新实现Unix V7中的文本实用程序。今天我们来看一下命令:

名称

cat–链接并打印

简介

[ –u个]文件…

描述

读取每个文件并将其写入标准输出。因此

cat文件

打印文件并

cat文件1文件2>文件3

连接前两个文件并将结果放在第三个文件上。

如果没有文件给定,或者如果遇到参数“-”,从标准输入中读取。输出缓冲在512字节块中,除非标准输出是终端或–u个选项存在。

另请参阅

pr(1),cp(1

漏洞

当心“catab>a”和“catab>b”,它们会在读取输入文件之前破坏输入文件。

您的任务是编写Unix V7程序。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

二项式堆

2012年6月5日

优先级队列或堆是一种数据结构,它接受任何顺序的项,并按排序顺序发出它们。在前面的练习中,我们使用左派堆,成对堆、和最大容量堆,我们在排序算法,素数生成器,计算最小生成树图形的,分配代表权在美国众议院流媒体。在今天的练习中,我们使用从Chris Okasaki的书中窃取的二项式堆来研究优先级队列的另一个实现纯功能数据结构; 作为这本书的替代品,你可以在http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.48.973

二项式堆是二项式树的列表,由秩、元素和子树列表组成,由基本规则和递归规则定义:秩为0的二项式树状结构是一个单节点。二叉树第页+1是通过连接两个二叉树的秩来实现的第页让一棵树成为另一棵树最左边的孩子。每个子节点列表按等级降序维护;堆顺序是通过将树与较小元素的树下的较大元素链接来维护的。没有两个兄弟树具有相同的等级。链接行为的结果是所有树都包含2第页元素。

插入非常简单。首先,要插入的项被放入秩为0的单个堆中。然后,通过按秩递增的顺序遍历现有树插入新堆,沿途链接具有相同秩的树,直到找到丢失的秩。合并两个堆是类似的,遍历两个树列表,链接同等级别的树。最坏的插入情况发生在大小为2的堆上k个−1,这需要O(运行)(k个) =O(运行)(日志n个)时间;类似的分析也适用于合并。

find-min和remove-min操作都调用一个辅助函数,该函数查找根上具有最小元素的树,并返回该树和剩余树的列表。Find min只返回最小元素。Delete-min丢弃最小树根的元素,然后将其子元素与剩余树的列表合并。辅助功能和delete-min功能都能及时运行O(运行)(k个) =O(运行)(日志n个),find-min及时运行O(运行)(1) 一旦辅助功能运行。

您的任务是使用二项式堆为优先级队列实现函数库。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2

平方根

2012年6月1日

在今天的练习中,我们将学习四种不同的算法来计算正浮点数的平方根。

第一种方法是二分法。对于任何x个,√x在1和x之间。二分法重复计算二者之间中点的平方,并丢弃平方根未出现的范围的一半;当两个端点足够接近时,它们的中点作为函数的结果返回。

在第一世纪,希腊数学家亚历山大的英雄(他的名字经常拼写为Heron)设计了一种计算√x的迭代方法。如果x个k个是√x的良好近似值,然后是x个k个x个/x个k个是更好的近似值;在每个迭代步骤中,精度都会加倍。算法背后的思想是√x是1和x个,但不知道几何平均值,我们在一系列近似中使用算术平均值。

第三种方法是艾萨克·牛顿爵士发明的,也是基于迭代方法。如果x个k个是一个很好的函数近似值,那么x个k个+1=x个k个(f)(x个k个) /f’(x个k个)是更好的近似值。了解2x个是的导数x个2使计算近似序列变得容易。

第四种方法是可以应用于Heron或Newton方法的优化。输入编号x个通过连续乘以或除以2,缩小到范围[1,2)。然后,在范围如此小的情况下,将循环展开到固定的迭代次数,并将结果除以或乘以2的平方根,其次数与原始乘法或除法的次数相同。这很快,因为二进制计算机很容易用2进行乘除运算,并且通过对迭代起点进行表查找可以更快地完成,从而节省了一到两个步骤。

您的任务是实现上述四个平方根算法。完成后,欢迎您阅读运行建议的解决方案,或在下面的评论中发布自己的解决方案或讨论练习。

页:1 2