旅行者,你好。
如果您读过这篇文章,我建议继续我之前写的“有趣的”材料。 如果您稍加思考,便会分为三篇文章,但主要的信息只是表明对声明式方法很感兴趣。 由于某种原因,这并不好,好像eSCuel并未公开可用,是必须的,因为没有它,就无法思考,而是如何以不同的方式处理数据。 没错,最好制定任务,而不用担心这会转化为什么。
让我们开始做生意,我在那之前写过关于试图逗你的信,所以我将继续展示一个使用序言的例子,尽管以前的文章已经表明了对python的兴趣,甚至马上就会引起数千人的兴趣,对新电池新闻的兴趣特斯拉,是stotysch的意见,并在门户网站上razrabotnichestskom不那么几个,看到这种行为背后写程序,注意到在阅读的评论,也许他们五个,这个建议埃施的二读后 它混淆的想法,它应该读更多...
事实证明,没有满足感兴趣的假设,然后我仅展示了如何使用序言,它是一种现代,发展中的,自由分发的工具,可以采用和制定它,仅是为了表明其优势可以制定它。
我会说时间旅行是不存在的,但是我们要去一周前,有一个有趣的Prolog关于磁带中的三个部分,那是解决随机遇到的新问题的话题,我选择了这个有趣的网站,也是最艰巨的任务(仅而不是将字符串转换为数字)),我将尝试在Prolog中进行操作 。
停止提高兴趣,开始...
如果数字序列由至少三个元素组成,并且任意两个连续元素之间的差相同,则称为算术序列。
例如,这些是算术序列:
1,3,5,7,9
7、7、7、7
3,-1,-5,-9
以下序列不是算术运算。
1,1,2,5,7
总而言之,应该保留两个邻居之间的差异,只需要检查一下?
继续阅读:
给出了一个由N个数字组成的零索引数组A。 该数组的子序列切片是整数(P0,P1,...,Pk)的任何序列,使得0≤P0 <P1 <... <Pk <N。
如果序列A [P0],A [P1],...,A [Pk-1],A [Pk]是算术运算,则将数组A的子序列切片(P0,P1,...,Pk)称为算术运算。 特别是,这意味着k≥2。
该函数应返回数组A中算术子序列切片的数量。
哇,您需要找出可以满足的切片数量,可以找到的子列表选项,以便相邻项目之间的差异不会发生变化。
好像子列表在输入列表的所有排列的一个大集合中。
范例:
输入:[2、4、6、8、10]
输出:7
说明:
所有算术子序列切片为:
[2,4,6]
[4,6,8]
[6,8,10]
[2,4,6,8]
[4,6,8,10]
[2,4,6,8,10]
[2,6,10]
我知道如何在序言中表达子列表:
sublists(InputList, SubList):- append(Prefix,Root,InputList), append(SubList,Suffix,Root).
如何检查所需类型的列表是否需要检查三元组:
is_seq(A,B,C]):-AB =:=BC. is_seq(A,B,C|Tail]):-AB =:=BC, is_seq(B,C|Tail]).
如果我们抛弃列表中所有元素的排列,事实证明,这不只是位于附近的元素的子列表,而是由一些项目组成的子列表。
然后这样写:
seq(_,[]). seq([H|T],[H|T1]):-seq(T,T1). seq([_|T],T1):-seq(T,T1).
这样的规则将从列表中返回所有可能的子列表,但是它可以从一个元素开始,也可以从下一个元素跳过,最后也可以丢弃任何数量。
总的来说,我们得到了高估的解决方案数量,立即清楚的是,一个空列表将返回很多次,并且当元素从末尾删除时,无法避免重复。
在审查了针对该问题的建议测试后,结果发现输入中可能存在重复值,对于这样的列表[0,1,2,2,2]应该有4个解决方案。 每个2-ka可以单独使用,应该将其视为一个单独的切片,因此三个选项[0,1,2]和一个[2,2,2]是合适的。
运气不好,因为序列生成器会产生重复的值,但是如何使计算结果唯一呢? 您必须标记它们,使列表彼此不同。 我将在生成列表,检查条件和计算解决方案数量的基础上构建整个解决方案。 以及如何重复决策...
我将对元素进行简单编号,让列表变成组件值/索引(一个结构化术语)的列表,这就是他们所说的。 对于上面的示例,该值为[0 / 1,1 / 2,2 / 3,2 / 4,2 / 5]。 此输入生成的序列将全部不同。
因此,您可以将列表变成标记的列表:
label([],[],_). label([A|T],[A/N|T1],N):-N1 is N+1, label(T,T1,N1).
好了,最重要的一点是,在进行了一系列尝试之后,考虑了标记列表,检查了is_seq算术,该规则变成了一个相当复杂的表达式。 在这里,我们检查数字的三元组是否与条件相对应,并计算此特定解决方案的密钥,以排除唯一的解决方案,需要一个密钥,这将有助于收集列表中的所有密钥,然后对其进行计数。
在输入处有一个标记列表,输出将是键值,将其计算为整数,其数字是每个元素的“值+索引”之和。
%is_seq , , is_seq([A/An,B/Bn,C/Cn],2,N):- AB=:=BC, N is 10000*(A+An)+100*(B+Bn)+(C+Cn). is_seq([A/An,B/Bn,C/Cn|T],K,N):- AB=:=BC, is_seq([B/Bn,C/Cn|T],K1,N1), K is K1+1, N is N1+(A+An)*(100**K).
为了计算所有解决方案,我将使用内置功能来实现目标并将所有唯一解决方案收集到setof()列表中。 只是简单地编译所有序列的列表被证明是完全无效的,由此产生了将键作为更简单的值的想法:
get_number(List,N) :- label(List,ListL,1), setof(Len,K^Sub^(seq(ListL,Sub),is_seq(Sub,K,Len)),Result), length(Result,N),!. get_number(_,0).
当然,在这种解决方案中并没有特别表现性能。
这是程序的完整文本,其中包含测试列表,这些都是从网站上随任务而来的硬核(这只是测试的一部分):
label([],[],_). label([A|T],[A/N|T1],N):-N1 is N+1, label(T,T1,N1). seq(_,[]). seq([H|T],[H|T1]):-seq(T,T1). seq([_|T],T1):-seq(T,T1). is_seq([A/An,B/Bn,C/Cn],2,N):- AB=:=BC, N is 10000*(A+An)+100*(B+Bn)+(C+Cn). is_seq([A/An,B/Bn,C/Cn|T],K,N):- AB=:=BC, is_seq([B/Bn,C/Cn|T],K1,N1), K is K1+1, N is N1+(A+An)*(100**K). get_number(List,N) :- label(List,ListL,1),setof(Len,K^Sub^(seq(ListL,Sub),is_seq(Sub,K,Len)),Result), length(Result,N),!. get_number(_,0). %unit-tests framework assert_are_equal(Goal, false):-get_time(St),not(Goal),!,get_time(Fin),Per is round(Fin-St),writeln(Goal->ok:Per/sec). assert_are_equal(Goal, true):- get_time(St),Goal, !,get_time(Fin),Per is round(Fin-St),writeln(Goal->ok:Per/sec). assert_are_equal(Goal, Exp):-writeln(Goal->failed:expected-Exp). %all test :-assert_are_equal(get_number([2,4,6,8,10],7),true). :-assert_are_equal(get_number([],0),true). :-assert_are_equal(get_number([1],0),true). :-assert_are_equal(get_number([1,2],0),true). :-assert_are_equal(get_number([1,2,3],1),true). :-assert_are_equal(get_number([1,2,3,4],3),true). :-assert_are_equal(get_number([1,2,3,4,5],7),true). :-assert_are_equal(get_number([1,2,3,4,5,6],12),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7],20),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8],29),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8,9],41),true). :-assert_are_equal(get_number([1,2,3,4,5,6,7,8,9,10],55),true). :-assert_are_equal(get_number([2,2,3,4],2),true). :-assert_are_equal(get_number([0,1,2,2,2],4),true). :-assert_are_equal(get_number([0,2000000000,-294967296],0),true). :-assert_are_equal(get_number([1,1,1],1),true). :-assert_are_equal(get_number([1,1,1,1],5),true). :-assert_are_equal(get_number([1,1,1,1,1],16),true). :-assert_are_equal(get_number([1,1,1,1,1,1],42),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1],99),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1],219),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1],466),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1],968),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1],1981),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1],4017),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1],8100),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1],16278),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],32647),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],65399),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],130918),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],261972),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],524097),true). :-assert_are_equal(get_number([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],1048365),true).
令人失望的结果是,这样的效率:
get_number([2, 4, 6, 8, 10], 7)->ok:0/sec get_number([], 0)->ok:0/sec get_number([1], 0)->ok:0/sec get_number([1, 2], 0)->ok:0/sec get_number([1, 2, 3], 1)->ok:0/sec get_number([1, 2, 3, 4], 3)->ok:0/sec get_number([1, 2, 3, 4, 5], 7)->ok:0/sec get_number([1, 2, 3, 4, 5, 6], 12)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7], 20)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8], 29)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8, 9], 41)->ok:0/sec get_number([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 55)->ok:0/sec get_number([2, 2, 3, 4], 2)->ok:0/sec get_number([0, 1, 2, 2, 2], 4)->ok:0/sec get_number([0, 2000000000, -294967296], 0)->ok:0/sec get_number([1, 1, 1], 1)->ok:0/sec get_number([1, 1, 1, 1], 5)->ok:0/sec get_number([1, 1, 1, 1, 1], 16)->ok:0/sec get_number([1, 1, 1, 1, 1, 1], 42)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1], 99)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1], 219)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1], 466)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 968)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 1981)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 4017)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 8100)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 16278)->ok:0/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 32647)->ok:1/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 65399)->ok:1/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 130918)->ok:3/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 261972)->ok:6/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 524097)->ok:12/sec get_number([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 1048365)->ok:27/sec
收集列表,甚至只是决策键,都非常麻烦,但这是一个声明性决策,没有它,就不可能计算所有唯一的解决方案。
结论
这就是用Prolog语言编写任务的方式;仅将问题的陈述传递给程序会导致效率不足。 也许在这个问题上,只有算法解决方案可用? 这个过程有多复杂?
我再次提出问题...
一样,寻找答案对我们的职业很有趣,对吗?