逻辑编程及格题

及格

  • 列表进阶
    • 去括号
  • 逻辑非
    • 测试
  • 平头哥
    • 调试
  • 交作业
  • 很接近答案了
    • 尝试
  • 去掉老子

列表进阶

会了这题就可以及格了,原话如下:
Ok, we’re now halfway through the book. And flattening a list is the Pons Asinorum of Prolog programming. Did you cross it ok? If so, great. Time to move on.

去括号

?- flatten([a,b,[[[[[[[c,d]]]]]]],[[1,2]],foo,[]],Flat).
要得到
Flat = [a,b,c,d,1,2,foo]
看题目里面有一项是很多的括号[[[[[[[c,d]]]]]]],单从去括号来说应该没有那么难。那就一步一步来吧。

逻辑非

一直去到不能再去括号了,完成这句话就行了是吧。会用到逻辑编程填词游戏逻辑非的方法,学到后面也会专门讲的。代码如下:

islist([_]).
not(P) :- P, !, fail ; true.
flatten([X|[]],X):-
    not(islist(X)).
flatten([X|[]],Y):-
    flatten(X,Y).

可以看到递归调用的时候[X|[]]变成了X,就是这么简单!

测试

测试单个元组的多括号是可以去了。

?- flatten([[[[5]]]],X).
X=5

但是空还是返回了一个[]
?-flatten([[[[]]]],X).
无生万物,空先放一放直接往下走。

平头哥

是不是先这样处理列表的第一个元素,再递归处理后面的就搞定了。“|”,正好前面有学这个分割头尾符号。前面改成单平头flattentou,加两句。
flatten([X|TX],[Y|TY]):-
flattentou(X,Y),flatten(TX,TY).

直接返回false了
trace, (flatten([[[[5]]]],X)).

调试

Call:true
Exit:true
Exit:not(islist(5))
Exit:flattentou([5],5)
Exit:flattentou([[5]],5)
Exit:flattentou([[[5]]],5)
Call:flatten([],_1000)
到5 那里还是对的,加上老子吧,还是要考虑无生万物,参照逻辑的空无
flatten([],laozi).
调试后面加个老子,如下:
[5|laozi]

交作业

错了,这里做了很多尝试,发现原因是有些元组没有括号。
添加元组项不是列表的情况。直接加两行,吸收前面旅行的逻辑里并的做法。
flatten([X|TX],[X|TY]):-
flatten(TX,TY).
调试是又多走了很多的判断:
trace, (%flatten([a,b,[[[[[[[c,d]]]]]]],[[1,2]],foo,[]],X)
flatten([a,b],X)).
Call:flatten([a, b],_7288)
Call:flattentou(a,_1054)
Fail:flattentou(a,_1048)
Redo:flatten([a, b],_836)
Call:flatten([b],_1062)
Call:flattentou(b,_1060)
Fail:flattentou(b,_1054)
Redo:flatten([b],_1050)
Call:flatten([],_1068)
Exit:flatten([],laozi)
Exit:flatten([b],[b|laozi])
Exit:flatten([a, b],[a, b|laozi])
答案:
[a, b|laozi]还可以接受。

很接近答案了

[a, b, [c, d], [1, 2], foo, []|laozi] 1
[a, b, [c, d], [[1, 2]], foo, []|laozi] 2
[a, b, [[[[[[[c, d]]]]]]], [1, 2], foo, []|laozi] 3
[a, b, [[[[[[[c, d]]]]]]], [[1, 2]], foo, []|laozi]
看第一项里只有 [c, d], [1, 2]多了括号,多了空和老子,[]|laozi]。

尝试

最里层有多个的时候:
trace, (flatten([[[c,d]]],X)).

Call:flatten([[c, d]],_7294)
Call:flattentou([c, d],_1060)
Fail:flattentou([c, d],_1054)
Redo:flatten([[c, d]],_842)
Call:flatten([],_1068)
Exit:flatten([],laozi)
Exit:flatten([[c, d]],[[c, d]|laozi])
调试看是最后加的两行那里。

表头是一维列表的情况没有考虑。感觉就是只去一层中括号的情况,应该不难的吧。
是不是可以把‘|’改成‘,’逗号?
flattenone([X|TX],[X,Z]).
flattenone(TX,Z) .
trace, (flattenone([5,6],X)).
[5, _] 1
true
Redo:flattenone(’<garbage_collected>’,’<garbage_collected>’)
Exit:flattenone(’<garbage_collected>’,’<garbage_collected>’)
失败。

去掉老子

可以把laozi去掉了。
%flatten([],laozi). 这里改成空
全码:

islist([_]).
not(P) :- P, !, fail ; true.
flattentou([X|[]],X):-
    not(islist(X)).
flattentou([X|[]],Y):-
    flattentou(X,Y).%没有逗号,一个元素的情况
flattenone([],[]).
flattenone([X|TX],[X,Z]):-
	flattenone(TX,Z) .
flatten([],[]). %这里改成空去掉老子
flatten([X|TX],[Y|TY]):-
    flattentou(X,Y),flatten(TX,TY).
flatten([X|TX],[X|TY]):-
    flatten(TX,TY).
% 多元素待完成    
%flatten([[XX|TXX]|TX],[XX,TXX|TY]):-
%    flattenone([XX|TXX],X),flatten(TX,TY).
逻辑编程及格题调试

谁会一不小心加这么多括号?也只有自己了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值