问题陈述: 您将获得一个包含整数和整数列表的列表。你必须删除 来自每个子列表,第1,第2,第4,第8 ......等元素。
我的解决方案
domains
list=integer*
elem=i(integer);l(list)
clist=elem*
predicates
modify(list, list, integer, integer)
exec(clist, clist)
clauses
modify([], [], _, _).
modify([H|T], Mod, I, P):-
P=I,
!,
I1=I+1,
P1=P*2,
modify(T, Mod, I1, P1).
modify([H,T], [H|Mod], I, P):-
I1=I+1,
modify(T, Mod, I1, P).
exec([], []).
exec([i(N)|T], [i(N)|LR]):-
exec(T, LR).
exec([l(L)|T], [l(Mod)|LR]):-
modify(L, Mod, 1, 1).
do():-
exec([i(1),l([1,2,3,4,5,6,7,8,9]),l([1,2,3,4])],X),
write(X).
问题是算法有效,直到它从每个子列表中删除第一个和第二个元素,但从那时起不会删除一个东西,我不确定我做错了什么。
exec predicate
用于断言当前元素是整数还是整数列表,将整数添加到结果中,或者将修改后的列表添加到结果中。
modify predicate
修改给定列表,并应删除位置功率为2的所有元素。
我写do predicate
只是为了将其作为目标,以避免每次我想测试它时都写出列表。
答案 0 :(得分:1)
我认为你经常做P1=P*2
,然后你不匹配2的连续权力
另外,你这里有一个错字
modify([H,T], [H|Mod], I, P):- ...
应该阅读
modify([H|T], [H|Mod], I, P):- ...
我会写
modify([], [], _).
modify([_|T], Mod, I):-
is_pow2(I), !, % as noted by SQB
I1 is I+1,
modify(T, Mod, I1).
modify([H|T], [H|Mod], I):-
I1 is I+1,
modify(T, Mod, I1).
为了保持is_pow2 / 1的简单,你可以做到
is_pow2(1).
is_pow2(2).
is_pow2(4).
is_pow2(8).
is_pow2(16).
...
或使用您的Prolog算术设施。在SWI-Prolog中,一个简单的定义可能是
is_pow2(N) :-
between(0, 63, L),
N is 1 << L.
答案 1 :(得分:1)
实际上,修改的核心是正确的,因此它可能是exec中的问题。以下适用于我:
do_modify(X) :-
modify([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18], X, 2).
modify(Lin, Lout, Base) :- modify(Lin, Lout, Base, 1, 1).
modify([], [], _, _, _).
modify([_|T], X, Base, N, Power) :-
N = Power,
!,
P1 is Power * Base,
N1 is N + 1,
modify(T, X, Base, N1, P1).
modify([H|T], [H|X], Base, N, Power) :-
N1 is N + 1,
modify(T, X, Base, N1, Power).
在http://www.compileonline.com/execute_prolog_online.php上进行了测试。