Prolog check if the list is like 1,2,3,4,2,1

一世执手 提交于 2020-01-05 08:46:05

问题


I need to create a program to check if a list increases then decreases, just like in the example below:

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

and it must be at least a one step increase or decrease.

Basically:

  • there must be a single ascending sequence followed by a single descending sequence.
  • the step in each transition must be at least one (no identical numbers side by side).
  • the step can be more than one.

I thought about finding the biggest number in the list and then splitting the list into two lists, then checking if they are both sorted. How can it be done easier?


回答1:


Here is how you can do it easier:

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]).

The first predicate checks whether the sequence is going up. When we get to the inflexion point, the second one is true. After that, we just have to check that it goes down until the end (last three).




回答2:


If all numbers used are integers, consider using clpfd!

:- use_module(library(clpfd)).

Based on chain/2, we can define up_down_zs/3 like this:

up_down_zs(Up, [P|Down], Zs) :-
   Up = [_,_|_],
   Down = [_|_],
   append(Up, Down, Zs),
   append(_, [P], Up),
   chain(Up, #<),
   chain([P|Down], #>).

First, some cases we all expect to fail:

?- member(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).
false.

Now, let's run some satisfiable queries!

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

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

?- up_down_zs(Up, Down, [1,2,1]).
(  Up = [1,2], Down = [2,1]
;  false
).



回答3:


Alternatively :

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),
    !.

That requires your implementation to have an append/2 predicate defined, which is the case if you use swi for example. An adaptation to use append/3 isn't hard to code though.



来源:https://stackoverflow.com/questions/8650789/prolog-check-if-the-list-is-like-1-2-3-4-2-1

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!