我正在尝试为我的考试学习并遇到以下问题:
“编写一个 Prolog 程序来查找数字 a1,....a14 以便 a1^4+....+a14^4=2013
?-solve([A1,A2,...A13]).
它不仅仅是“我需要有人为我解决的随机家庭作业”。而是为考试而学习的作业
你将如何解决这个问题?
我正在尝试为我的考试学习并遇到以下问题:
“编写一个 Prolog 程序来查找数字 a1,....a14 以便 a1^4+....+a14^4=2013
?-solve([A1,A2,...A13]).
它不仅仅是“我需要有人为我解决的随机家庭作业”。而是为考试而学习的作业
你将如何解决这个问题?
如果所有数字都必须是整数,请考虑使用有限域约束。例如,使用 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.
您的问题在解释方面留下了一些自由度。
假设您可以使用上限限制您的数字集。
那么一个天真的“生成和测试”很容易编写,但效率低下却无可救药。
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(Target^(1/4)) 的循环,并使其成为新目标,直到 Target 为 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)
结果是无用的......
我会接受句子并对其进行转换,直到序言出现:
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
像这样的东西。
一般来说,这种模式是一个“生成和测试”的问题。您需要将其分解为可管理的部分:
对于生成情况,由于您要提高到四次方,因此您知道所有项都是正数,因此生成这样的数字 A 是没有意义的A^4 > 2013
。因此,每个A
s 都将介于 0 和 2013 的四次根的底之间。
对于测试用例,我将其分解为两个步骤:编写一个映射谓词将A
s 的列表映射到 的列表A^4
,然后编写一个谓词来对列表求和并测试它是否是目标值。