展平列表

时间:2016-07-20 13:12:22

标签: list prolog

尝试从http://www.ic.unicamp.br/~meidanis/courses/mc336/2009s2/prolog/problemas/

解决练习07

我已经开始了一次迭代,如下所示

my_flatten1([], []).
my_flatten1([[A|T]|U], [A|V]) :-
   append(T, U1, V),
   my_flatten1(U, U1).
my_flatten1([A|T], [A|U]) :-
   not(is_list(A)),
   my_flatten1(T, U).

is_flat(A) :-
   my_flatten1(A, A).

它似乎适用于以下一组查询

my_flatten1([a, [b, [c, d], e]], X).
my_flatten1(X, [a, b, c]).
my_flatten1(X, [a|T]).
my_flatten1(X, [a, b, A]).
my_flatten1([a, X], M).
my_flatten1([a|X], M).

is_flat([a|X]).
is_flat([a,[c]|X]).
is_flat([F,[c]|X]).

my_flatten1(A, B).
my_flatten1([A], B).
my_flatten1([[A]], B).
my_flatten1([[a|A]], B).
my_flatten1([a|A], B).
my_flatten1([X|B], [1,2,3,4]).
my_flatten1([[a,c|D]|X], [a|B]).

但是,基于my_flatten构建my_flatten1并不成功。总是会有一些查询失败或以无限循环结束,或者产生一个最明显的结果。

编辑以澄清我所追求的内容,例如我可以使用变量作为第一个参数调用my_flatten1以分发括号:

?- my_flatten1(X, [a, b]).
X = [[a], [b]] ;
X = [[a], b] ;
X = [[a, b]] ;
X = [a, [b]] ;
X = [a, b].

3 个答案:

答案 0 :(得分:1)

当您点击问题标题时,我不确定您是否知道99 Prolog问题包含解决方案?

无论如何,my_flatten看起来像下面这样:

my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([H|T],R) :-
    my_flatten(H,HFlat),
    my_flatten(T,TFlat),
    append(HFlat,TFlat,R).

一些疑问:

?- my_flatten([[]],R).
   R = [].

?- my_flatten([[1],[2]],R).
   R = [1, 2].

?- my_flatten([[1],[[3]]],R).
   R = [1, 3].

修改

正如@ lambda.xy.y正确观察到的那样,以上版本不会终止查询:

?- my_flatten(X,[X]).

所以我看了一下SWI内置flatten/2的行为并观察到了:

?- flatten([],[]).
   true.

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

?- flatten(X,[]).
   false.

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

?- flatten(X,[X]).
   true.

实现:

my_flatten(L,R) :-
    my_flatten(L,[],Flat),
    !,
    R=Flat.

my_flatten(X,R,[X|R])  :- \+ is_list(X), !.
my_flatten([],R,R)     :- !.
my_flatten([H|T],A1,R) :- !,
    my_flatten(H,A2,R),
    my_flatten(T,A1,A2).
my_flatten(NonList,T,[NonList|T]).

答案 1 :(得分:0)

这种简单的实现是不可逆的,但它不会产生无限循环。相反,它会失败。

flat2([],[]) :- 
    !.
flat2(X,[X]) :-
    X \= [_|_],
    !.
flat2([X|R],Result) :-
    flat2(X,XF),
    flat2(R,XR),
    append(XF,XR,Result).

测试:

?- flat2([[a,b],[c,[d,e,[f]]]],X).
X = [a, b, c, d, e, f].

测试(反向):

?- flat2(X,[1,2]).
false.
?- flat2(X,[X]).
false.

可能会简化,但此实现不可逆,在这种情况下会出现无限循环:

flat([X|R],Result) :-
    !,
    flat(X,XF),
    flat(R,XR),
    append(XF,XR,Result).

flat([],[]) :- !.
flat(X,[X]).

答案 2 :(得分:0)

  :- [library(plunit)] .

  :- abolish(flatten/2) .
  :- mode(flatten(+,-)) .

  flatten(0,_) --> [Q] , flatten(1,Q) .
  flatten(1,Q) --> \+ {is_list(Q)} , flatten(2,Q) .
  flatten(1,Q) --> \+ \+ {is_list(Q)} , flatten(3,Q) .
  flatten(2,Q) , [Q] --> flatten(0,_) .
  flatten(3,Q) --> {Q=[]} , flatten(0,_) .
  flatten(3,Q) --> {Q=[R|Ts]} , flatten(1,R) , flatten(1,Ts) .

  :- begin_tests(flatten) .

  test('1',[true(Ps=[4,5,6,7,8,9,1,2])]) :-
  flatten([4,5,[6],[7,8,9],[1,2]],Ps) .

  test('2',[true(Ps=[1,2,3,4])]) :-
  flatten([1,[2,3],[],4],Ps) .

  test('3',[true(Ps=Qs)]) :-
  flatten(Qs,Ps) .

  :- end_tests(flatten) .

/ * 样品运行。

  ?- run_tests .

  % PL-Unit: flatten ... done               
  % All 3 tests passed

  ?- flatten([1,[2,3],[],4],Ps).
  Ps = [1,2,3,4].

  ?- flatten([4,5,[6],[7,8,9],[1,2]],Ps) .
  Ps = [4,5,6,7,8,9,1,2].

  ?- flatten(Qs,Ps) .
  Ps = [Qs].

* /