Пролог проверить, если список похож на 1,2,3,4,2,1 - PullRequest
1 голос
/ 28 декабря 2011

Мне нужно создать программу, чтобы проверить, увеличивается ли список, а затем уменьшается, как в примере ниже:

[1,2,3,4,5,6,4,3,2,1]

и должно быть как минимум на один шаг больше или меньше.

В основном:

  • должна быть одна восходящая последовательность, за которой следует одна нисходящая последовательность.
  • шаг в каждом переходе должен быть хотя бы один (рядом нет идентичных чисел).
  • шаг может быть больше , чем единица.

Я думал о том, чтобы найти наибольшее число в списке, а затем разделить список на два списка, а затем проверить, отсортированы ли они оба. Как это можно сделать проще?

Ответы [ 3 ]

1 голос
/ 11 августа 2015

Если все используемые числа являются целыми числами, рассмотрите возможность использования !

<i>:- <a href="http://www.swi-prolog.org/pldoc/doc_for?object=use_module/1" rel="nofollow">use_module</a>(<a href="http://www.swi-prolog.org/pldoc/man?section=clpfd" rel="nofollow">library(clpfd)</a>).</i>

На основе chain/2 мы можем определить up_down_zs/3 следующим образом:

<i>up_down_zs(Up, [P|Down], Zs) :-
   Up = [_,_|_],
   Down = [_|_],
   <a href="https://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue#append" rel="nofollow">append</a>(Up, Down, Zs),
   append(_, [P], Up),
   <a href="http://www.swi-prolog.org/pldoc/man?section=clpfd" rel="nofollow">chain</a>(Up, #<),
   chain([P|Down], #>).</i>

Во-первых, в некоторых случаях мы все ожидаем сбоя:

?- <i><a href="https://www.complang.tuwien.ac.at/ulrich/iso-prolog/prologue#member" rel="nofollow">member</a>(Zs, [[1,1],[1,2,2,1],[1,2,3,4],[1,2,3,4,5,5,6,4,3,2,1]]),
   up_down_zs(_, _, Zs).</i>
false.

Теперь давайте выполним выполнимых запросов!

?- <i>up_down_zs(Up, Down, [1,2,3,4,5,6,4,3,2,1]).</i>
(  Up = [1,2,3,4,5,6], Down = [6,4,3,2,1] 
;  false
).

?- <i>up_down_zs(Up, Down, [1,2,3,1]).</i>
(  Up = [1,2,3], Down = [3,1]
;  false
).

?- <i>up_down_zs(Up, Down, [1,2,1]).</i>
(  Up = [1,2], Down = [2,1]
;  false
).
1 голос
/ 28 декабря 2011

Вот как вы можете сделать это проще:

up_and_down([A, B, C|Rest]) :- 
  A < B, up_and_down([B, C|Rest]).
up_and_down([A, B, C|Rest]) :-
  A < B, B > C, goes_down([C|Rest]).
goes_down([]).
goes_down([X]).
goes_down([A, B|Rest]]) :-
  A > B, goes_down([B | Rest]).

Первый предикат проверяет, увеличивается ли последовательность.Когда мы добираемся до точки перегиба, вторая верна.После этого мы просто должны убедиться, что он снижается до конца (последние три).

0 голосов
/ 28 декабря 2011

В качестве альтернативы:

pyramid(L) :-
    append(Increase, Decrease, L),
    (   append(_, [Last], Increase), Decrease = [First|_]
     -> Last > First
     ;  true),       
    forall(append([_, [A, B], _], Increase), A < B),
    forall(append([_, [C, D], _], Decrease), C > D),
    !.

Это требует, чтобы ваша реализация имела предикат append/2, определенный, например, если вы используете swi. Адаптация к использованию append/3 не сложна для кодирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...