Prolog程序查找多个数字4的幂的总和

时间:2013-10-09 07:46:40

标签: prolog

我正在尝试为我考试并遇到以下问题:

“编写一个Prolog程序,找到数字a1,...... a14,以便a1 ^ 4 + .... + a14 ^ 4 = 2013

?-solve([A1,A2,...A13]).

它不仅仅是一个“随机的家庭作业,我需要有人为我解决它”。而是为了参加考试而获得的分配

你会如何解决这个问题?

4 个答案:

答案 0 :(得分:1)

如果所有数字都必须是整数,请考虑使用有限域约束。例如,使用SWI-Prolog:

:- use_module(library(clpfd)).

solution(Vs) :-
        length(Vs, 14),
        Vs ins 0..sup,
        chain(Vs, #=<),
        maplist(pow4, Vs, Ps),
        sum(Ps, #=, 2013).

pow4(X, Y) :- Y #= X^4.

事实证明,该解决方案在订购时是独一无二的:

?- solution(Vs), label(Vs).
Vs = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 6] ;
false.

答案 1 :(得分:0)

我会把这个句子改成它直到prolog出来:

Write a Prolog program that finds numbers a1,....a14 so that a1^4+....+a14^4=2013

=

finds numbers a1,....a14 all >= 0 and < 2013
so that a1^4+....+a14^4=2013

=

between(0, 2013, A1), and so on
 A1^4+....+A14^4 = 2013
像这样的东西。

答案 2 :(得分:0)

通常,此模式是“生成和测试”问题。你需要把它分解成可管理的部分:

  • 生成N个数字的列表(例如,在您的情况下N = 14)
  • 测试这些数字的四次幂之和总和为目标M(在您的情况下,这是2013年)
  • 使用回溯来查找所有解决方案

对于生成案例,由于你提升到第四个幂,你知道所有的术语都是正数,所以没有必要生成一个数字A,A^4 > 2013。因此A中的每一个都将介于零和2013年第四根的最低点之间。

对于测试用例,我将其分解为两个步骤:编写地图谓词以将A列表映射到A^4列表,然后编写谓词以对列表求和测试它是否是目标值。

答案 3 :(得分:0)

你的问题留下了解释的自由度。

假设您可以使用上限限制您的数字集。

然后一个天真的'生成和测试'很容易写,但没有效率。

find_4th_power_sum(CountNumbers, Target, Numbers) :-
    U is floor(Target^(1/4)), % upper bound
    length(Numbers, CountNumbers),
    maplist(gen_4th_power(U), Numbers, Powers),
    sum_list(Powers, Target).

gen_4th_power(U, N, Pow4th) :-
    between(0, U, N),
    Pow4th is N^4.

唉,即使floor(Target^(1/4))只有6,整个搜索空间也是

?- X is 7^13.
X = 96889010407.

问题在于冗余:解决方案的任何排列都将成为解决方案。

我会坚持一个较少的Prolog-ish方式:做一个循环从Target中减去  floor(目标^(1/4)),并使其成为新目标,直到目标为1.保持数字列表在路上。

当然,这就是我在任何命令式程序中解决问题的方法......

以下是代码:

list_4th_power_sum(CountNumbers, Target, [N|Numbers]) :-
    (   Target > 1
    ->  N is floor(Target^(1/4)),
        Target1 is Target-N^4,
        CountNumbers1 is CountNumbers-1,
        list_4th_power_sum(CountNumbers1, Target1, Numbers)
    ;   N = 1,
        findall(0, between(1,CountNumbers,_), Numbers)
    ).

令我惊讶的是,填0,即findall(0, between(1,CountNumbers,_), Numbers)原来是没用的......