Прежде всего, ваши вторые и третьи предложения не нужны, они просто создают дубликаты решений, вот лучший предикат check/2
:
check([],[]).
check([L1|Tail], [L2|Tail2]) :-
L1 > 0,
L2 is 1,
check(Tail,Tail2).
check([L1|Tail], [L2|Tail2]) :-
L1 =:= 0,
L2 is 0,
check(Tail,Tail2).
Затем, вместо использования is/2
для присвоения значений L2, вы можете напрямую указать значение L2 в заголовке ваших предложений, например:
check([],[]).
check([L1|Tail], [1|Tail2]) :-
L1 > 0,
check(Tail,Tail2).
check([L1|Tail], [0|Tail2]) :-
L1 =:= 0,
check(Tail,Tail2).
Затем, вместо использования =:=/2
, вы можете снова указать непосредственно значение в заголовке вашего второго предложения:
check([],[]).
check([L1|Tail], [1|Tail2]) :-
L1 > 0,
check(Tail,Tail2).
check([0|Tail], [0|Tail2]) :-
check(Tail,Tail2).
Теперь ваш предикат check/2
уже выглядит намного лучше!
Давайте добавим предложение для обработки вложенности списка:
check([],[]).
check([L1|Tail], [L2|Tail2]) :-
L1 = [_|_],
check(L1, L2),
check(Tail, Tail2).
check([L1|Tail], [1|Tail2]) :-
\+ L1 = [_|_],
L1 > 0,
check(Tail,Tail2).
check([0|Tail], [0|Tail2]) :-
check(Tail,Tail2).
Как вы видели, нам также нужно было добавить тест, что L1 не является списком в нашем предыдущем предложении, чтобы список не шел по этому пути и не приводил к странным решениям.
Надеюсь, это помогло.